aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authors-ol <s-ol@users.noreply.github.com>2020-02-28 12:21:57 +0000
committers-ol <s-ol@users.noreply.github.com>2020-02-28 21:01:19 +0000
commitdf8141c3214a5fb8d447297be64bdf5619b7d8a7 (patch)
treef401303d36724c1055e25e0aaef9e0a27107c8a1
parentlots of fixes (diff)
downloadalive-df8141c3214a5fb8d447297be64bdf5619b7d8a7.tar.gz
alive-df8141c3214a5fb8d447297be64bdf5619b7d8a7.zip
doc and tag spec
-rw-r--r--core/cell.moon42
-rw-r--r--core/parsing.moon8
-rw-r--r--core/registry.moon3
-rw-r--r--core/tag.moon36
-rw-r--r--spec/core/cell_spec.moon (renamed from spec/cell_spec.moon)0
-rw-r--r--spec/core/parsing_spec.moon (renamed from spec/parsing_spec.moon)0
-rw-r--r--spec/core/registry_spec.moon (renamed from spec/registry_spec.moon)0
-rw-r--r--spec/core/scope_spec.moon (renamed from spec/scope_spec.moon)0
-rw-r--r--spec/core/tag_spec.moon100
-rw-r--r--spec/core/value_spec.moon (renamed from spec/value_spec.moon)11
10 files changed, 161 insertions, 39 deletions
diff --git a/core/cell.moon b/core/cell.moon
index 0cb8e9f..4b28a04 100644
--- a/core/cell.moon
+++ b/core/cell.moon
@@ -3,24 +3,9 @@ import Value from require 'core.value'
import op_invoke, fn_invoke from require 'core.invoke'
import Tag from require 'core.tag'
--- ALV Cell type
+-- An S-Expression with a head expression and any number of tail expressions,
+-- an optional tag, and optionally the internal whitespace as parsed.
class Cell
--- common
- -- tag: the parsed Tag
- -- children: sequence of child AST Nodes
- -- white: optional sequence of whitespace segments ([0 .. #@children])
- new: (@tag=Tag.blank!, @children, @white) =>
- if not @white
- @white = ['' for i=1,#@children]
- @white[0] = ''
-
- assert #@white == #@children, "mismatched whitespace length"
-
- head: => @children[1]
- tail: => [c for c in *@children[2,]]
-
- destroy: =>
-
-- AST interface
eval: (scope) =>
head = (@head!\eval scope)\const!
@@ -42,12 +27,15 @@ class Cell
Action\eval_cell scope, @tag, head, @tail!
+ -- quoting a Cell recursively quotes children, but preserves identity this
+ -- means that a quoted Cell may only be 'used' once. use :clone() otherwise.
quote: (scope) =>
children = [child\quote scope for child in *@children]
Cell @tag, children, @white
+ -- creates a clone of this Cell with its own identity by prepending a `parent`
+ -- tag and cloning all child expressoins recursively.
clone: (parent) =>
- @tag\ensure!
tag = @tag\clone parent
children = [child\clone parent for child in *@children]
Cell tag, children, @white
@@ -67,6 +55,20 @@ class Cell
'(' .. @tag\stringify! .. buf .. ')'
+-- internal
+ -- tag: the parsed Tag
+ -- children: sequence of child AST Nodes
+ -- white: optional sequence of whitespace segments ([0 .. #@children])
+ new: (@tag=Tag.blank!, @children, @white) =>
+ if not @white
+ @white = [' ' for i=1,#@children]
+ @white[0] = ''
+
+ assert #@white == #@children, "mismatched whitespace length"
+
+ head: => @children[1]
+ tail: => [c for c in *@children[2,]]
+
-- static
__tostring: => @stringify 2
@@ -85,9 +87,9 @@ class Cell
tag, children, white = parse_args ...
@ tag, children, white
--- A parenthesis-less Cell (root of an ALV document)
+-- A parenthesis-less Cell (root of an ALV document).
--
--- evaluates with an implicit 'do' in the head
+-- has an implicit head of 'do'.
class RootCell extends Cell
head: => Value.sym 'do'
tail: => @children
diff --git a/core/parsing.moon b/core/parsing.moon
index 0123469..ac4f878 100644
--- a/core/parsing.moon
+++ b/core/parsing.moon
@@ -44,13 +44,7 @@ cell = P {
:expr, :explist, :cell
}
-parse_error = (root, rest) ->
- if #rest > 0
- error "failed to parse, rest is:\n#{rest}"
-
- root
-
-program = root * (C (P 1)^0) * -1 / parse_error
+program = root * -1
{
:comment
diff --git a/core/registry.moon b/core/registry.moon
index e8272fa..2ac5825 100644
--- a/core/registry.moon
+++ b/core/registry.moon
@@ -73,9 +73,6 @@ class SimpleRegistry extends Registry
last: (index) =>
replace: (index, expr) =>
- finalize: =>
- assert @ == @@active_registry, "not the active registry!"
- @@active_registry, @prev = @prev, nil
{
:Registry
diff --git a/core/tag.moon b/core/tag.moon
index 122c67e..f38d36a 100644
--- a/core/tag.moon
+++ b/core/tag.moon
@@ -10,43 +10,59 @@ class DummyReg
dummy = DummyReg!
class Tag
- new: (@value) =>
-
- clone: (parent) => ClonedTag @, parent
-
+ -- obtain the value that was previously registered (using keep or replace) for
+ -- this tag
last: =>
if index = @index!
Registry.active!\last index
+ -- 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.
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.
+ -- registers blank tags.
replace: (expr) =>
if index = @index!
Registry.active!\replace index, expr
else
Registry.active!\init @, expr
- ensure: =>
+ -- create a copy of this tag scoped to a `parent` tag.
+ -- registers blank tags.
+ clone: (parent) =>
+ -- 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
else
Registry.active!\init @, dummy
+ assert parent, "need parent to clone!"
+ ClonedTag @, parent
+
+-- internal
+ new: (@value) =>
+
index: => @value
+ -- callback from `Registry` when the eval cycle is ending and a tag value has
+ -- been generated
set: (value) =>
- assert not @value, "setting #{@} again"
+ assert not @value, "#{@} is not blank"
@value = value
+-- static
+
@blank: -> Tag!
@parse: (num) => @ tonumber num
stringify: => if @value then "[#{@value}]" else ''
-
- __tostring: => if @value then "#{@value}" else '[blank]'
+ __tostring: => if @value then "#{@value}" else '?'
class ClonedTag extends Tag
new: (@original, @parent) =>
@@ -57,7 +73,9 @@ class ClonedTag extends Tag
if orig and parent
"#{parent}.#{orig}"
- set: (value) => @original\set value
+ set: (value) =>
+ assert @parent.value, "cloned tag #{@} set before parent"
+ @original\set value
stringify: => error "cant stringify ClonedTag"
diff --git a/spec/cell_spec.moon b/spec/core/cell_spec.moon
index fcf9861..fcf9861 100644
--- a/spec/cell_spec.moon
+++ b/spec/core/cell_spec.moon
diff --git a/spec/parsing_spec.moon b/spec/core/parsing_spec.moon
index ddf760f..ddf760f 100644
--- a/spec/parsing_spec.moon
+++ b/spec/core/parsing_spec.moon
diff --git a/spec/registry_spec.moon b/spec/core/registry_spec.moon
index 6fe2e3a..6fe2e3a 100644
--- a/spec/registry_spec.moon
+++ b/spec/core/registry_spec.moon
diff --git a/spec/scope_spec.moon b/spec/core/scope_spec.moon
index 471bbce..471bbce 100644
--- a/spec/scope_spec.moon
+++ b/spec/core/scope_spec.moon
diff --git a/spec/core/tag_spec.moon b/spec/core/tag_spec.moon
new file mode 100644
index 0000000..7855fd6
--- /dev/null
+++ b/spec/core/tag_spec.moon
@@ -0,0 +1,100 @@
+import Tag from require 'core.tag'
+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
+
+describe 'Tag', ->
+ describe 'should be constructable', ->
+ it 'by parsing', ->
+ tag = Tag\parse '2'
+ assert tag
+ assert.is.equal 2, tag.value
+ assert.is.equal '[2]', tag\stringify!
+ assert.is.equal '2', tostring tag
+
+ it 'as blank Tags', ->
+ tag = Tag\blank!
+ assert tag
+ assert.is.nil tag.value
+ assert.is.equal '', tag\stringify!
+ assert.is.equal '?', tostring tag
+
+ describe 'should be clonable', ->
+ do_asserts = (tag, expect) ->
+ assert tag
+ assert.is.nil tag.value
+ assert.is.equal expect, tostring tag
+ assert.has.error tag\stringify
+
+ it 'from parsed tags', with_reg ->
+ 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 ->
+ parent = Tag\parse '1'
+ original = Tag\blank!
+ tag = original\clone parent
+ do_asserts tag, '1.?'
+
+ it 'with blank parent', with_reg ->
+ parent = Tag\blank!
+ original = Tag\parse '2'
+ tag = original\clone parent
+ do_asserts tag, '?.2'
+
+ it 'completely blank', with_reg ->
+ parent = Tag\blank!
+ original = Tag\blank!
+ tag = original\clone parent
+ do_asserts tag, '?.?'
+
+ describe 'should be set-able', ->
+ it 'only if blank', with_reg ->
+ tag = Tag\parse '42'
+ assert.has.error -> tag\set 43
+
+ clone = tag\clone Tag\parse '3'
+ assert.has.error -> clone\set 42
+
+ clone = tag\clone Tag\blank!
+ assert.has.error -> clone\set 42
+
+ it 'and stores the value', with_reg ->
+ blank = Tag\blank!
+ blank\set 12
+
+ assert.is.equal blank.value, 12
+
+ it 'sets the original if cloned', with_reg ->
+ original = Tag\blank!
+ parent = Tag\parse '7'
+
+ o_set = spy.on original, 'set'
+ p_set = spy.on parent, 'set'
+
+ clone = original\clone parent
+ clone\set 11
+
+ assert.spy(o_set).was_called_with (match.is_ref original), 11
+ assert.spy(p_set).was_not_called!
+
+ assert.is.equal original.value, 11
+
+ it 'requires the parent to be registered if cloned', with_reg ->
+ original = Tag\blank!
+ parent = Tag\blank!
+
+ clone = original\clone parent
+ assert.has.error -> clone\set 11
diff --git a/spec/value_spec.moon b/spec/core/value_spec.moon
index bc68c5b..cda7123 100644
--- a/spec/value_spec.moon
+++ b/spec/core/value_spec.moon
@@ -66,6 +66,17 @@ describe 'Value', ->
assert.has_error -> (Value.str 'hi')\unwrap 'num'
assert.has_error -> (Value.sym 'hi')\unwrap 'str'
+ test 'with __call shorthand', ->
+ assert.is.equal 3.14, (Value.num 3.14)!
+ assert.is.equal 'hi', (Value.str 'hi')!
+ assert.is.equal 'hi', (Value.sym 'hi')!
+ assert.is.equal 3.14, (Value.num 3.14) 'num'
+ assert.is.equal 'hi', (Value.str 'hi') 'str'
+ assert.is.equal 'hi', (Value.sym 'hi') 'sym'
+ assert.has_error -> (Value.num 3.14) 'sym'
+ assert.has_error -> (Value.str 'hi') 'num'
+ assert.has_error -> (Value.sym 'hi') 'str'
+
describe 'checks equality', ->
test 'using the type', ->
val = Value 'num', 3