diff options
| author | s-ol <s-ol@users.noreply.github.com> | 2020-03-22 10:51:30 +0000 |
|---|---|---|
| committer | s-ol <s-ol@users.noreply.github.com> | 2020-03-22 10:55:49 +0000 |
| commit | de154813f056cd1bef891bb02a6852d9c11b3f4f (patch) | |
| tree | 1d624c9c8fa92875db035aba50e3999e388a1f6e | |
| parent | new meta/doc system (diff) | |
| download | alive-de154813f056cd1bef891bb02a6852d9c11b3f4f.tar.gz alive-de154813f056cd1bef891bb02a6852d9c11b3f4f.zip | |
more Errors, doc
| -rw-r--r-- | core/base/action.moon | 2 | ||||
| -rw-r--r-- | core/cell.moon | 5 | ||||
| -rw-r--r-- | core/registry.moon | 104 | ||||
| -rw-r--r-- | core/tag.moon | 35 | ||||
| -rw-r--r-- | spec/core/tag_spec.moon | 28 |
5 files changed, 71 insertions, 103 deletions
diff --git a/core/base/action.moon b/core/base/action.moon index 7ada4ba..d10712f 100644 --- a/core/base/action.moon +++ b/core/base/action.moon @@ -19,7 +19,7 @@ class Action -- @tparam Value head the (`AST:eval`d) `head` of the Cell to evaluate new: (@cell, @head) => @tag = @cell.tag - @tag\replace @ + @tag\register @ --- perform the actual evaluation. -- diff --git a/core/cell.moon b/core/cell.moon index b7f4a1d..14bea2c 100644 --- a/core/cell.moon +++ b/core/cell.moon @@ -6,6 +6,7 @@ -- -- @classmod Cell import Value from require 'core.value' +import Error from require 'core.error' import op_invoke, fn_invoke from require 'core.invoke' import Tag from require 'core.tag' @@ -69,7 +70,7 @@ class Cell -- @tparam Scope scope the scope to evaluate in -- @treturn Result the evaluation result eval: (scope) => - head = assert @head!, "cannot evaluate expr without head" + head = assert @head!, Error 'syntax', "cannot evaluate empty expr" head = (head\eval scope)\const! Action = switch head.type when 'opdef' @@ -81,7 +82,7 @@ class Cell when 'builtin' head\unwrap! else - error "cannot evaluate expr with head #{head}" + error Error 'type', "#{head} is not an opdef, fndef or builtin" Action\eval_cell @, scope, head diff --git a/core/registry.moon b/core/registry.moon index 981f815..1183a0d 100644 --- a/core/registry.moon +++ b/core/registry.moon @@ -9,68 +9,52 @@ import Result from require 'core.result' unpack or= table.unpack class Registry --- methods for Tag +--- internals for `Tag` +-- @section internals + --- lookup the last registration. + -- + -- @tparam number|string index the registration index + -- @treturn any last: (index) => @last_map[index] - replace: (index, expr, ignore_dup=false) => + --- set the current registration. + -- + -- @tparam string\number index the registration index + -- @tparam any expr the registration value + -- @tparam[default=false] boolean ignore_dup ignore duplicate registrations + register: (index, expr, ignore_dup=false) => L\trace "reg: setting #{index} to #{expr}" assert not @map[index] or ignore_dup, "duplicate tags with index #{index}!" @map[index] = expr + --- request identity and registration for blank tag. + -- + -- @tparam Tag tag the blank tag + -- @tparam any expr the registration value init: (tag, expr) => L\trace "reg: init pending to #{expr}" table.insert @pending, { :tag, :expr } - next_tag: => #@map + 1 - --- members -- @section members - --- wrap a function with an eval-cycle. + --- begin an evaluation cycle. -- - -- Sets the active Registry and destroys unused `Action`s and `Op`s. + -- Begin an evaltime cycle (and tick). + -- Set the active Registry and clear out pending registrations. -- - -- @tparam function fn - -- @treturn function `fn` wrapped with eval-cycle logic - wrap_eval: (fn) => (...) -> - @grab! - @map, @pending = {}, {} - @tick += 1 - L\log "eval at tick #{@tick}" - - results = { pcall fn, ... } - ok = table.remove results, 1 - - if not ok - @tick -= 1 - @release! - L\log "rollback to tick #{@tick}" - error unpack results - error "WHAT?" - - for tag, val in pairs @last_map - val\destroy! unless @map[tag] - - for { :tag, :expr } in *@pending - -- tag was solved by another pending registration - -- (e.g. first [A] is solved, then [5.A] is solved) - continue if tag\index! - - next_tag = @next_tag! - L\trace "assigned new tag #{next_tag} to #{tag} #{expr}" - tag\set next_tag - @map[tag\index!] = expr - - @last_map = @map - @release! - unpack results - + -- All calls go `begin_eval` must be matched with either a call to + -- `end_eval` or `rollback_eval`. begin_eval: => @latest_map = @last_map @begin_tick! @map, @pending = {}, {} + --- end an evaluation cycle. + -- + -- Register all pending `Tag`s and destroy all orphaned registrations. + -- Unset the active Registry. end_eval: => for tag, val in pairs @last_map val\destroy! unless @map[tag] @@ -80,7 +64,7 @@ class Registry -- (e.g. first [A] is solved, then [5.A] is solved) continue if tag\index! - next_tag = @next_tag! + next_tag = #@map + 1 L\trace "assigned new tag #{next_tag} to #{tag} #{expr}" tag\set next_tag @map[tag\index!] = expr @@ -88,43 +72,35 @@ class Registry @last_map = @map @end_tick! + --- abort an evaluation cycle. + -- + -- Unset the active Registry. rollback_eval: => @end_tick! - next_tick: => - @tick += 1 - + --- begin a run cycle. + -- + -- Increment the tick index and set the active Registry. begin_tick: => @grab! @next_tick! + --- end a run cycle. + -- + -- Unset the active Registry. end_tick: => @release! - --- wrap a function with a tick. - -- - -- Sets the active Registry and increments the global tick count. - -- - -- @tparam function fn - -- @treturn function `fn` wrapped with tick logic - wrap_tick: (fn) => (...) -> - @grab! + --- manually increment the tick index (for testing). + next_tick: => @tick += 1 - results = { pcall fn, ... } - ok = table.remove results, 1 - - if not ok - @release! - error unpack results - - @release! - unpack results - + --- 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 @@ -158,7 +134,7 @@ class SimpleRegistry extends Registry @cnt += 1 last: (index) => - replace: (index, expr) => + register: (index, expr) => wrap: (fn) => (...) -> @grab! diff --git a/core/tag.moon b/core/tag.moon index a3ce1ae..55cd472 100644 --- a/core/tag.moon +++ b/core/tag.moon @@ -24,33 +24,22 @@ class Tag --- obtain the registered value of the last eval-cycle. -- - -- Obtain the value that was previously registered (using `keep` or - -- `replace`) for this tag on the last eval-cylce. + -- Obtain the value that was previously registered for this tag on the last + -- eval-cylce. -- -- @treturn ?any last: => if index = @index! Registry.active!\last index - --- keep using a the value from the last eval-cycle. - -- - -- Assert that `expr` is the value that was previously registered for this - -- tag, and keep it for the current eval cycle. Fails for blank tags. - -- - -- @tparam any expr the value to register - keep: (expr) => - index = assert @index! - assert expr == Registry.active!\last index - Registry.active!\replace index, expr - --- 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 - replace: (expr) => + register: (expr) => if index = @index! - Registry.active!\replace index, expr + Registry.active!\register index, expr else Registry.active!\init @, expr @@ -64,7 +53,7 @@ class Tag -- ensure this tag is registered for the current eval cycle, -- even if it is blank and has no associated value if index = @index! - Registry.active!\replace index, dummy, true + Registry.active!\register index, dummy, true else Registry.active!\init @, dummy @@ -74,13 +63,21 @@ class Tag stringify: => if @value then "[#{@value}]" else '' __tostring: => if @value then "#{@value}" else '?' --- internal +--- internals for `Registry` +-- @section internals + new: (@value) => + --- get a unique index value for this Tag. + -- + -- The index is equal to `value` for simple tags and a path-like string for + -- cloned tags. + -- + -- @treturn ?number|string index: => @value - -- callback from `Registry` when the eval cycle is ending and a tag value has - -- been generated + --- callback to set value for blank tags. + -- @tparam number value set: (value) => assert not @value, "#{@} is not blank" @value = value diff --git a/spec/core/tag_spec.moon b/spec/core/tag_spec.moon index a4491b0..87e02e2 100644 --- a/spec/core/tag_spec.moon +++ b/spec/core/tag_spec.moon @@ -3,15 +3,9 @@ import Registry from require 'core.registry' import Logger from require 'logger' Logger.init 'silent' -with_reg = (fn) -> - registry = Registry! - fn = registry\wrap_eval fn - fn, registry - -do_reg = (fn) -> - fn, reg = with_reg fn - fn! - reg +reg = Registry! +setup -> reg\begin_eval! +teardown -> reg\end_eval! describe 'Tag', -> describe 'should be constructable', -> @@ -36,32 +30,32 @@ describe 'Tag', -> assert.is.equal expect, tostring tag assert.has.error tag\stringify - it 'from parsed tags', with_reg -> + it 'from parsed tags', -> parent = Tag.parse '1' original = Tag.parse '2' tag = original\clone parent do_asserts tag, '1.2' - it 'but not from blank tags', with_reg -> + it 'but not from blank tags', -> parent = Tag.parse '1' original = Tag.blank! tag = original\clone parent do_asserts tag, '1.?' - it 'with blank parent', with_reg -> + it 'with blank parent', -> parent = Tag.blank! original = Tag.parse '2' tag = original\clone parent do_asserts tag, '?.2' - it 'completely blank', with_reg -> + it 'completely blank', -> parent = Tag.blank! original = Tag.blank! tag = original\clone parent do_asserts tag, '?.?' describe 'should be set-able', -> - it 'only if blank', with_reg -> + it 'only if blank', -> tag = Tag.parse '42' assert.has.error -> tag\set 43 @@ -71,13 +65,13 @@ describe 'Tag', -> clone = tag\clone Tag.blank! assert.has.error -> clone\set 42 - it 'and stores the value', with_reg -> + it 'and stores the value', -> blank = Tag.blank! blank\set 12 assert.is.equal blank.value, 12 - it 'sets the original if cloned', with_reg -> + it 'sets the original if cloned', -> original = Tag.blank! parent = Tag.parse '7' @@ -92,7 +86,7 @@ describe 'Tag', -> assert.is.equal original.value, 11 - it 'requires the parent to be registered if cloned', with_reg -> + it 'requires the parent to be registered if cloned', -> original = Tag.blank! parent = Tag.blank! |
