aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authors-ol <s-ol@users.noreply.github.com>2020-03-22 10:51:30 +0000
committers-ol <s-ol@users.noreply.github.com>2020-03-22 10:55:49 +0000
commitde154813f056cd1bef891bb02a6852d9c11b3f4f (patch)
tree1d624c9c8fa92875db035aba50e3999e388a1f6e
parentnew meta/doc system (diff)
downloadalive-de154813f056cd1bef891bb02a6852d9c11b3f4f.tar.gz
alive-de154813f056cd1bef891bb02a6852d9c11b3f4f.zip
more Errors, doc
-rw-r--r--core/base/action.moon2
-rw-r--r--core/cell.moon5
-rw-r--r--core/registry.moon104
-rw-r--r--core/tag.moon35
-rw-r--r--spec/core/tag_spec.moon28
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!