diff options
| author | s-ol <s-ol@users.noreply.github.com> | 2020-02-01 18:21:42 +0000 |
|---|---|---|
| committer | s-ol <s-ol@users.noreply.github.com> | 2020-02-01 18:21:42 +0000 |
| commit | 21b002554452e8eee4e5e65006863bf8b30c92c3 (patch) | |
| tree | 4d6b1259fa344bca189677575ce0d271937c3ee1 | |
| parent | add README (diff) | |
| download | alive-21b002554452e8eee4e5e65006863bf8b30c92c3.tar.gz alive-21b002554452e8eee4e5e65006863bf8b30c92c3.zip | |
more flexible AST\walk
| -rw-r--r-- | ast.moon | 22 | ||||
| -rw-r--r-- | registry.moon | 7 | ||||
| -rw-r--r-- | spec/ast_spec.moon | 47 | ||||
| -rw-r--r-- | test.alv | 22 |
4 files changed, 55 insertions, 43 deletions
@@ -8,10 +8,12 @@ unescape = (str) -> str class Atom + type: 'Atom' + new: (@raw, @style='', value) => @value = Const value - _walk_sexpr: => + _walk: => coroutine.yield @type, @ stringify: => switch @style @@ -32,6 +34,8 @@ class Atom __tostring: => @stringify! class Xpr + type: 'Xpr' + new: (parts, @style='(', tag) => @white = {} @white[0] = parts[1] @@ -43,19 +47,21 @@ class Xpr if tag @tag = tag.value\getc! - _walk_sexpr: => - -- depth first + _walk: (dir, yield_self=true) => + coroutine.yield @type, @ if yield_self and dir == 'outin' + for frag in *@ - frag\_walk_sexpr! + frag\_walk dir + + coroutine.yield @type, @ if yield_self and dir == 'inout' - if @style == '(' - coroutine.yield @ head: => @[1].value tail: => unpack [p.value for p in *@[2,]] - walk_sexpr: => - coroutine.wrap -> @_walk_sexpr! + walk: (dir, yield_self=true) => + assert dir == 'inout' or dir == 'outin', "dir has to be either inout or outin" + coroutine.wrap -> @_walk dir, yield_self stringify: => buf = '' diff --git a/registry.moon b/registry.moon index a7b4c9d..394267c 100644 --- a/registry.moon +++ b/registry.moon @@ -25,7 +25,9 @@ class Registry seen = {} to_tag = {} - for sexpr in @root\walk_sexpr! + for typ, sexpr in @root\walk 'inout', false + continue unless typ == 'Xpr' + if not sexpr.tag @spawn_expr sexpr table.insert to_tag, sexpr @@ -72,7 +74,8 @@ class Registry update: (dt) => -- for tag, sexpr in pairs @map - for sexpr in @root\walk_sexpr! + for typ, sexpr in @root\walk 'inout', false + continue unless typ == 'Xpr' continue unless sexpr.value ok, err = pcall sexpr.value.update, sexpr.value, dt diff --git a/spec/ast_spec.moon b/spec/ast_spec.moon index cfb64cf..80fbb56 100644 --- a/spec/ast_spec.moon +++ b/spec/ast_spec.moon @@ -1,15 +1,36 @@ import Atom, Xpr from require 'ast' -describe 'Xpr', -> - it 'can be walked', -> - aa = Xpr { '', (Atom '1', '', 1), '' } - ab = Xpr { '', (Atom '2', '', 2), '' } - ac = Xpr { '', (Atom '3', '', 3), '' } - b = Xpr { '', aa, ' ', ab, '' } - - root = Xpr { '', ac, ' ', b, '' }, 'naked' - - iter = root\walk_sexpr! - for res in *{ ac, aa, ab, b } - assert.is.equal res, iter! - assert.is.nil iter! +describe 'AST', -> + describe 'can be walked', -> + a1 = Atom '1', '', 1 + a2 = Atom '2', '', 2 + a3 = Atom '3', '', 3 + x1 = Xpr { '', a1, '' } + x21 = Xpr { '', a2, '' } + x22 = Xpr { '', a3, '' } + x2 = Xpr { '', x21, ' ', x22, '' } + + root = Xpr { '', x1, ' ', x2, '' }, 'naked' + + assert_yields = (expected_order, iter) -> + for val in *expected_order + got_typ, got_val = iter! + assert.is.equal val.type, got_typ + assert.is.equal val, got_val + assert.is.nil iter! + + it 'inside-out', -> + assert_yields { a1, x1, a2, x21, a3, x22, x2, root }, root\walk 'inout' + + it 'inside-out, skipping the root', -> + assert_yields { a1, x1, a2, x21, a3, x22, x2 }, root\walk 'inout', false + + it 'outside-in', -> + assert_yields { root, x1, a1, x2, x21, a2, x22, a3 }, root\walk 'outin' + + it 'outside-in, skipping the root', -> + assert_yields { x1, a1, x2, x21, a2, x22, a3 }, root\walk 'outin', false + + it 'errors when direction is wrong or absent', -> + assert.has.errors -> root\walk! + assert.has.errors -> root\walk 'backandforth' @@ -1,20 +1,2 @@ -#(this is a comment) -([2]debug/out 'a' ([6]math/mix 0.5 1 ([5]time/lfo 1))) - - -([16]util/pick 2 3) - -([14]math/mix 0 2 0.5) - -([13]debug/out 'b' ([12]math/mix 0 ([11]util/pick ([10]time/tick 4) - 0.25 - 0.5 - 0.75 - 1) ([3]time/lfo 1 tri))) - -([9]debug/out 'name' ([8]util/pick ([7]time/tick 1) - 0.1 - 0.6 - 0.3 - 0.9)) - +([2]osc/out '127.0.0.1' 9000 '/param/radius/set' ([1]time/lfo 1)) +([4]osc/out '127.0.0.1' 9000 '/param/offset/set' ([3]time/lfo 1.0 'saw')) |
