diff options
| author | s-ol <s-ol@users.noreply.github.com> | 2020-04-24 21:16:01 +0000 |
|---|---|---|
| committer | s-ol <s-ol@users.noreply.github.com> | 2020-04-26 09:36:07 +0000 |
| commit | c106b5d8503fe6ac1c8f45f0e4e2dcf819e3c973 (patch) | |
| tree | 4239fd2b8fa2eee769bcbd40e0b797186a759be8 | |
| parent | relative imports (diff) | |
| download | alive-c106b5d8503fe6ac1c8f45f0e4e2dcf819e3c973.tar.gz alive-c106b5d8503fe6ac1c8f45f0e4e2dcf819e3c973.zip | |
fix registry/module bugs
- registry not released when errors occur
- registry is no longer grabbed, problem solved ;)
- ops not reliably destroyed
- only destroy ops who were *not* forked
| -rw-r--r-- | alv/base/builtin.moon | 1 | ||||
| -rw-r--r-- | alv/copilot.moon | 8 | ||||
| -rw-r--r-- | alv/invoke.moon | 5 | ||||
| -rw-r--r-- | alv/module.moon | 9 | ||||
| -rw-r--r-- | alv/registry.moon | 31 | ||||
| -rw-r--r-- | alv/tag.moon | 6 |
6 files changed, 18 insertions, 42 deletions
diff --git a/alv/base/builtin.moon b/alv/base/builtin.moon index b9e7e55..f675207 100644 --- a/alv/base/builtin.moon +++ b/alv/base/builtin.moon @@ -83,7 +83,6 @@ class Builtin if compatible builtin\setup last else - last\destroy! if last builtin\setup nil builtin\eval scope, cell\tail! diff --git a/alv/copilot.moon b/alv/copilot.moon index 2b97d48..7ef2134 100644 --- a/alv/copilot.moon +++ b/alv/copilot.moon @@ -20,6 +20,7 @@ class Copilot -- @tparam string file name/path of the alive file to watch and execute new: (file) => @T = 0 + @last_modification = 0 @last_modules = {} @open file if file @@ -54,8 +55,11 @@ class Copilot last = @active_module prefix = @active_module.file\match('(.*)/[^/]*$') .. '/' or '' mod = @last_modules[name] or Module "#{prefix}#{name}.alv" + L\trace "entering module #{mod}" + @modules[name] = mod @active_module = mod ok, err = pcall mod\eval + L\trace "returning to module #{mod}" @active_module = last if ok mod.root @@ -90,11 +94,12 @@ class Copilot poll: => dirty = {} for name, mod in pairs @last_modules - if mod\poll! + if mod\poll! > @last_modification table.insert dirty, mod return if #dirty == 0 + @last_modification = os.time! L\set_time 'eval' L\print "changes to files: #{table.concat [m.file for m in *dirty], ', '}" @@ -115,6 +120,7 @@ class Copilot for name, mod in pairs @modules mod\finish! + @last_modification = os.time! @last_modules, @modules = @modules, nil { diff --git a/alv/invoke.moon b/alv/invoke.moon index fba6485..439af49 100644 --- a/alv/invoke.moon +++ b/alv/invoke.moon @@ -32,6 +32,7 @@ class op_invoke extends Builtin setup: (prev) => if prev @op = prev.op\fork! + prev.forked = COPILOT.T else def = @head\unwrap 'opdef', "cant op-invoke #{@head}" @op = def! @@ -39,7 +40,9 @@ class op_invoke extends Builtin --- `Builtin:destroy` implementation. -- -- calls `op`:@{Op:destroy|destroy}. - destroy: => @op\destroy! + destroy: => + if @forked ~= COPILOT.T + @op\destroy! --- perform an `Op` invocation. -- diff --git a/alv/module.moon b/alv/module.moon index 356bcf5..8fc3ba7 100644 --- a/alv/module.moon +++ b/alv/module.moon @@ -26,7 +26,6 @@ class Module -- @classmethod new: (@file) => @registry = Registry! - @last_modification = 0 --- members -- @section members @@ -36,23 +35,19 @@ class Module poll: => { :mode, :modification } = (lfs.attributes @file) or {} assert mode == 'file', Error 'io', "not a file: '#{file}'" - - if @last_modification < modification - true + modification --- start an evaluation cycle. -- -- If the module has already been evaluated this tick, this is a noop. -- Otherwise, register the module with the `Copilot`. Updates `root`. eval: => - @last_modification = os.time! + @registry\begin_eval! @ast = Error.wrap "parsing '#{@file}'", -> program\match slurp @file assert @ast, Error 'syntax', "failed to parse" scope = Scope builtin - @registry\begin_eval! @root = Error.wrap "evaluating '#{@file}'", @ast\eval, scope, @registry - @registry\release! --- rollback the last evaluation cycle. rollback: => @registry\rollback_eval! diff --git a/alv/registry.moon b/alv/registry.moon index d4dcccc..1b24e9a 100644 --- a/alv/registry.moon +++ b/alv/registry.moon @@ -40,19 +40,15 @@ class Registry --- begin an evaluation cycle. -- - -- Set the active Registry and clear out pending registrations. - -- -- All calls go `begin_eval` must be matched with either a call to -- `end_eval` or `rollback_eval`. begin_eval: => - @grab! assert not @map, "unfinished evaluation cycle" @map, @pending = {}, {} --- abort an evaluation cycle. - -- - -- Unset the active Registry. rollback_eval: => + assert @map, "no eval cycle to abort" for { :tag, :expr } in *@pending expr\destroy! @@ -61,11 +57,10 @@ class Registry --- end an evaluation cycle. -- -- Register all pending `Tag`s and destroy all orphaned registrations. - -- Unset the active Registry. -- @treturn bool whether any changes to the AST were made end_eval: => for tag, val in pairs @last_map - val\destroy! unless @map[tag] + val\destroy! for { :tag, :expr } in *@pending -- tag was solved by another pending registration @@ -82,16 +77,6 @@ class Registry dirty - --- set the active Registry. - grab: => - assert not @prev, "already have a previous registry? #{@prev}" - @prev, Registry.active_registry = Registry.active_registry, @ - - --- unset the active Registry. - release: => - assert @ == Registry.active_registry, "not the active registry!" - Registry.active_registry, @prev = @prev, nil - --- destroy this Registry and all associated Registrations. -- needs to be called *after* `:eval`. destroy: => @@ -109,13 +94,6 @@ class Registry new: => @last_map = {} - --- get the active Registry. - -- - -- Raises an error when there is no active Registry. - -- - -- @treturn Registry - @active: -> assert Registry.active_registry, "no active Registry!" - class SimpleRegistry extends Registry new: => @cnt = 1 @@ -127,11 +105,6 @@ class SimpleRegistry extends Registry last: (index) => register: (index, expr) => - wrap: (fn) => (...) -> - @grab! - with fn ... - @release! - { :Registry :SimpleRegistry diff --git a/alv/tag.moon b/alv/tag.moon index d7becab..4b39bcb 100644 --- a/alv/tag.moon +++ b/alv/tag.moon @@ -30,14 +30,14 @@ class Tag -- @treturn ?any last: => if index = @index! - Registry.active!\last index + COPILOT.active_module.registry\last index --- register `expr` for this tag for the current eval cycle. -- -- Will mark blank tags for auto-assignment at the end of the eval cycle. -- -- @tparam any expr the value to register - register: (expr) => Registry.active!\register @, expr + register: (expr) => COPILOT.active_module.registry\register @, expr --- create a copy of this tag scoped to a `parent` tag. -- @@ -48,7 +48,7 @@ class Tag clone: (parent) => -- ensure this tag is registered for the current eval cycle, -- even if it is blank and has no associated value - Registry.active!\register @, dummy, true + COPILOT.active_module.registry\register @, dummy, true assert parent, "need parent to clone!" ClonedTag @, parent |
