aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authors-ol <s-ol@users.noreply.github.com>2020-02-01 18:21:42 +0000
committers-ol <s-ol@users.noreply.github.com>2020-02-01 18:21:42 +0000
commit21b002554452e8eee4e5e65006863bf8b30c92c3 (patch)
tree4d6b1259fa344bca189677575ce0d271937c3ee1
parentadd README (diff)
downloadalive-21b002554452e8eee4e5e65006863bf8b30c92c3.tar.gz
alive-21b002554452e8eee4e5e65006863bf8b30c92c3.zip
more flexible AST\walk
-rw-r--r--ast.moon22
-rw-r--r--registry.moon7
-rw-r--r--spec/ast_spec.moon47
-rw-r--r--test.alv22
4 files changed, 55 insertions, 43 deletions
diff --git a/ast.moon b/ast.moon
index b6be5f5..d7735fd 100644
--- a/ast.moon
+++ b/ast.moon
@@ -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'
diff --git a/test.alv b/test.alv
index 81b1b65..370ae41 100644
--- a/test.alv
+++ b/test.alv
@@ -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'))