aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authors-ol <s-ol@users.noreply.github.com>2020-02-10 14:30:03 +0000
committers-ol <s-ol@users.noreply.github.com>2020-02-10 14:31:39 +0000
commit2174e57f3626b95b69eeb543f1d11ee867b67a63 (patch)
tree28e4483952928d5babe04b57cb57bad1da723128
parentswitch from luaposix to luasystem (diff)
downloadalive-2174e57f3626b95b69eeb543f1d11ee867b67a63.tar.gz
alive-2174e57f3626b95b69eeb543f1d11ee867b67a63.zip
reorganization
-rw-r--r--base.moon258
-rw-r--r--core/base.moon69
-rw-r--r--core/cell.moon85
-rw-r--r--core/const.moon106
-rw-r--r--core/init.moon13
-rw-r--r--core/invoke.moon79
-rw-r--r--core/scope.moon (renamed from scope.moon)8
-rw-r--r--lib/builtin.moon3
-rw-r--r--lib/debug.moon2
-rw-r--r--lib/gui.moon2
-rw-r--r--lib/math.moon2
-rw-r--r--lib/osc.moon2
-rw-r--r--lib/time.moon2
-rw-r--r--lib/util.moon2
-rw-r--r--parsing.moon2
-rw-r--r--registry.moon3
-rw-r--r--spec/cell_spec.moon7
-rw-r--r--spec/const_spec.moon3
-rw-r--r--spec/parsing_spec.moon2
-rw-r--r--spec/registry_spec.moon2
-rw-r--r--spec/scope_spec.moon3
21 files changed, 370 insertions, 285 deletions
diff --git a/base.moon b/base.moon
deleted file mode 100644
index bfdf7da..0000000
--- a/base.moon
+++ /dev/null
@@ -1,258 +0,0 @@
-import Scope from require 'scope'
-
-unpack or= table.unpack
-
-ancestor = (klass) ->
- assert klass, "cant find the ancestor of nil"
- while klass.__parent
- klass = klass.__parent
- klass
-
-class Op
--- common
- new: =>
- -- (...) => @setup ...
-
- get: => @value
- getc: =>
- L\warn "stream #{@} cast to constant"
- @value
-
--- Value interface
- update: =>
-
- destroy: =>
-
--- static
- __tostring: => "<op: #{@@__name}>"
- __inherited: (cls) => cls.__base.__tostring = @__tostring
-
- spawn: (Opdef, ...) ->
- Opdef ...
-
-class Action
--- common
- new: (head, @tag, @registry) =>
- @patch head
-
- register: =>
- @tag = @registry\register @, @tag
-
--- AST interface
- -- * eval args
- -- * perform scope effects
- -- * patch nested exprs
- -- * return runtime-tree value
- eval: (scope, tail) => error "not implemented"
-
- -- free resources
- destroy: =>
-
- -- update this instance for :eavl() with new head
- -- if :patch() returns false, this instance is :destroy'ed and recreated instead
- -- must *not* return false when called after :new()
- -- only considered if Action types match
- patch: (head) =>
- if head == @head
- true
-
- @head = head
-
--- static
- @get_or_create: (ActionType, head, tag, registry) ->
- last = tag and registry\prev tag
- compatible = last and
- (last.__class == ActionType) and
- (last\patch head) and
- last
-
- if not compatible
- last\destroy! if last
- compatible = ActionType head, tag, registry
-
- with compatible
- \register!
-
- __tostring: => "<action: #{@@__name}>"
- __inherited: (cls) => cls.__base.__tostring = @__tostring
-
-class Const
- types = {
- sym: true
- str: true
- num: true
- scope: true
- op: true
- opdef: true
- fndef: true
- builtin: true
- }
-
- new: (@type, @value, @raw) =>
- assert types[@type], "invalid Const type: #{@type}"
-
--- Value interface
- get: (type) =>
- assert not type or type == @type, "#{@} is not a #{type}"
- @value
-
- getc: (type) =>
- assert not type or type == @type, "#{@} is not a #{type}"
- @value
-
- update: (dt) =>
- switch @type
- when 'op'
- @value\update dt
-
--- AST interface
- eval: (scope) =>
- switch @type
- when 'num', 'str'
- @
- when 'sym'
- assert (scope\get @value), "undefined reference to symbol '#{@value}'"
- else
- error "cannot evaluate #{@}"
-
- quote: => @
-
- stringify: => @raw
-
--- static
- __tostring: =>
- value = if @type == 'opdef' or @type == 'builtin' then @value.__name else @value
- "<#{@type}: #{value}>"
-
- __eq: (other) =>
- other.type == @type and other.value == @value
-
- unescape = (str) -> str\gsub '\\([\'"\\])', '%1'
-
- @parse: (type, sep) =>
- switch type
- when 'num' then (match) -> @ 'num', (tonumber match), match
- when 'sym' then (match) -> @ 'sym', match, match
- when 'str' then (match) -> @ 'str', (unescape match), sep .. match .. sep
-
- @num: (num) -> Const 'num', num, tostring num
- @str: (str) -> Const 'str', str, "'#{str}'"
- @sym: (sym) -> Const 'sym', sym, sym
- @empty: -> Const 'str', '', "''"
-
- @wrap: (val, name='(unknown)') ->
- typ = switch type val
- when 'number' then 'num'
- when 'string' then 'str'
- when 'table'
- if base = rawget val, '__base'
- -- a class
- switch ancestor val
- when Op then 'opdef'
- when Action then 'builtin'
- else
- error "#{name}: cannot wrap class '#{val.__name}'"
- elseif val.__class
- -- an instance
- switch ancestor val.__class
- when Op then 'op'
- when Scope then 'scope'
- when Const
- return val
- else
- error "#{name}: cannot wrap '#{val.__class.__name}' instance"
- else
- -- plain table
- return Const 'scope', Scope.from_table val
- else
- error "#{name}: cannot wrap Lua type '#{type val}'"
-
- Const typ, val
-
-local builtin
-class Cell
--- common
- new: (@tag, @children, @white) =>
- if not @white
- @white = ['' for i=1,#@children+1]
-
- builtin or= require 'lib.builtin'
-
- head: => @children[1]
- tail: => [c for c in *@children[2,]]
-
--- AST interface
- eval: (scope, registry) =>
- head = @head!\eval scope, registry
- Action = switch head.type
- when 'opdef'
- -- scope\get 'op-invoke'
- builtin['op-invoke']
- when 'fndef'
- -- scope\get 'fn-invoke'
- builtin['fn-invoke']
- when 'builtin'
- head\getc!
- else
- error "cannot evaluate expr with head #{head}"
-
- action = Action\get_or_create head, @tag, registry
- @tag or= action.tag
- action\eval scope, @tail!
-
- quote: (scope, registry) =>
- @tag = registry\register @, @tag
- children = [child\quote scope, registry for child in *@children]
- @
-
- stringify: (depth=-1) =>
- buf = ''
- buf ..= if depth > 0 then ' ' else @white[0]
- if depth == 0
- buf ..= '...'
- else
- for i, child in ipairs @children
- buf ..= child\stringify depth - 1
- buf ..= if depth > 0 then ' ' else @white[i]
-
- tag = if @tag then "[#{@tag\stringify!}]" else ''
- '(' .. tag .. buf .. ')'
-
--- static
- __tostring: => @stringify 2
-
- parse_args = (tag, parts) ->
- if not parts
- parts, tag = tag, nil
-
- children, white = {}, { [0]: parts[1] }
-
- for i = 2,#parts,2
- children[i/2] = parts[i]
- white[i/2] = parts[i+1]
-
- tag, children, white
- @parse: (...) =>
- tag, children, white = parse_args ...
- @ tag, children, white
-
-class RootCell extends Cell
- head: => Const.sym 'do'
- tail: => @children
-
- stringify: =>
- buf = ''
- buf ..= @white[0]
-
- for i, child in ipairs @children
- buf ..= child\stringify!
- buf ..= @white[i]
-
- buf
-
-{
- :Op
- :Const
- :Action
- :Cell, :RootCell
-}
diff --git a/core/base.moon b/core/base.moon
new file mode 100644
index 0000000..1805bea
--- /dev/null
+++ b/core/base.moon
@@ -0,0 +1,69 @@
+class Op
+-- common
+ new: =>
+ -- (...) => @setup ...
+
+ get: => @value
+ getc: =>
+ L\warn "stream #{@} cast to constant"
+ @value
+
+-- Value interface
+ update: =>
+
+ destroy: =>
+
+-- static
+ __tostring: => "<op: #{@@__name}>"
+ __inherited: (cls) => cls.__base.__tostring = @__tostring
+
+ spawn: (Opdef, ...) ->
+ Opdef ...
+
+class Action
+-- common
+ new: (head, @tag, @registry) =>
+ @patch head
+
+ register: =>
+ @tag = @registry\register @, @tag
+
+-- AST interface
+ -- * eval args
+ -- * perform scope effects
+ -- * patch nested exprs
+ -- * return runtime-tree value
+ eval: (scope, tail) => error "not implemented"
+
+ -- free resources
+ destroy: =>
+
+ -- update this instance for :eavl() with new head
+ -- if :patch() returns false, this instance is :destroy'ed and recreated instead
+ -- must *not* return false when called after :new()
+ -- only considered if Action types match
+ patch: (head) =>
+ if head == @head
+ true
+
+ @head = head
+
+-- static
+ @get_or_create: (ActionType, head, tag, registry) ->
+ last = tag and registry\prev tag
+ compatible = last and
+ (last.__class == ActionType) and
+ (last\patch head) and
+ last
+
+ if not compatible
+ last\destroy! if last
+ compatible = ActionType head, tag, registry
+
+ with compatible
+ \register!
+
+ __tostring: => "<action: #{@@__name}>"
+ __inherited: (cls) => cls.__base.__tostring = @__tostring
+
+:Op, :Action
diff --git a/core/cell.moon b/core/cell.moon
new file mode 100644
index 0000000..199c4c3
--- /dev/null
+++ b/core/cell.moon
@@ -0,0 +1,85 @@
+import Const from require 'core.const'
+import op_invoke, fn_invoke from require 'core.invoke'
+
+class Cell
+-- common
+ new: (@tag, @children, @white) =>
+ if not @white
+ @white = ['' for i=1,#@children+1]
+
+ head: => @children[1]
+ tail: => [c for c in *@children[2,]]
+
+-- AST interface
+ eval: (scope, registry) =>
+ head = @head!\eval scope, registry
+ Action = switch head.type
+ when 'opdef'
+ -- scope\get 'op-invoke'
+ op_invoke
+ when 'fndef'
+ -- scope\get 'fn-invoke'
+ fn_invoke
+ when 'builtin'
+ head\getc!
+ else
+ error "cannot evaluate expr with head #{head}"
+
+ action = Action\get_or_create head, @tag, registry
+ @tag or= action.tag
+ action\eval scope, @tail!
+
+ quote: (scope, registry) =>
+ tag = registry\register @, @tag
+ children = [child\quote scope, registry for child in *@children]
+ Cell tag, children, @white
+
+ stringify: (depth=-1) =>
+ buf = ''
+ buf ..= if depth > 0 then '' else @white[0]
+ if depth == 0
+ buf ..= '...'
+ else
+ for i, child in ipairs @children
+ buf ..= child\stringify depth - 1
+ buf ..= if depth > 0 then ' ' else @white[i]
+
+ if depth > 0
+ buf = buf\sub 1, #buf - 1
+
+ tag = if @tag then "[#{@tag\stringify!}]" else ''
+ '(' .. tag .. buf .. ')'
+
+-- static
+ __tostring: => @stringify 2
+
+ parse_args = (tag, parts) ->
+ if not parts
+ parts, tag = tag, nil
+
+ children, white = {}, { [0]: parts[1] }
+
+ for i = 2,#parts,2
+ children[i/2] = parts[i]
+ white[i/2] = parts[i+1]
+
+ tag, children, white
+ @parse: (...) =>
+ tag, children, white = parse_args ...
+ @ tag, children, white
+
+class RootCell extends Cell
+ head: => Const.sym 'do'
+ tail: => @children
+
+ stringify: =>
+ buf = ''
+ buf ..= @white[0]
+
+ for i, child in ipairs @children
+ buf ..= child\stringify!
+ buf ..= @white[i]
+
+ buf
+
+:Cell, :RootCell
diff --git a/core/const.moon b/core/const.moon
new file mode 100644
index 0000000..564ab53
--- /dev/null
+++ b/core/const.moon
@@ -0,0 +1,106 @@
+import Op, Action from require 'core.base'
+
+local Scope
+load_ = ->
+ import Scope from require 'core.scope'
+
+ancestor = (klass) ->
+ assert klass, "cant find the ancestor of nil"
+ while klass.__parent
+ klass = klass.__parent
+ klass
+
+class Const
+ types = {
+ sym: true
+ str: true
+ num: true
+ scope: true
+ op: true
+ opdef: true
+ fndef: true
+ builtin: true
+ }
+
+ new: (@type, @value, @raw) =>
+ assert types[@type], "invalid Const type: #{@type}"
+
+-- Value interface
+ get: (type) =>
+ assert not type or type == @type, "#{@} is not a #{type}"
+ @value
+
+ getc: (type) =>
+ assert not type or type == @type, "#{@} is not a #{type}"
+ @value
+
+ update: (dt) =>
+ switch @type
+ when 'op'
+ @value\update dt
+
+-- AST interface
+ eval: (scope) =>
+ switch @type
+ when 'num', 'str'
+ @
+ when 'sym'
+ assert (scope\get @value), "undefined reference to symbol '#{@value}'"
+ else
+ error "cannot evaluate #{@}"
+
+ quote: => @
+
+ stringify: => @raw
+
+-- static
+ __tostring: =>
+ value = if @type == 'opdef' or @type == 'builtin' then @value.__name else @value
+ "<#{@type}: #{value}>"
+
+ __eq: (other) =>
+ other.type == @type and other.value == @value
+
+ unescape = (str) -> str\gsub '\\([\'"\\])', '%1'
+
+ @parse: (type, sep) =>
+ switch type
+ when 'num' then (match) -> @ 'num', (tonumber match), match
+ when 'sym' then (match) -> @ 'sym', match, match
+ when 'str' then (match) -> @ 'str', (unescape match), sep .. match .. sep
+
+ @num: (num) -> Const 'num', num, tostring num
+ @str: (str) -> Const 'str', str, "'#{str}'"
+ @sym: (sym) -> Const 'sym', sym, sym
+ @empty: -> Const 'str', '', "''"
+
+ @wrap: (val, name='(unknown)') ->
+ typ = switch type val
+ when 'number' then 'num'
+ when 'string' then 'str'
+ when 'table'
+ if base = rawget val, '__base'
+ -- a class
+ switch ancestor val
+ when Op then 'opdef'
+ when Action then 'builtin'
+ else
+ error "#{name}: cannot wrap class '#{val.__name}'"
+ elseif val.__class
+ -- an instance
+ switch ancestor val.__class
+ when Op then 'op'
+ when Scope then 'scope'
+ when Const
+ return val
+ else
+ error "#{name}: cannot wrap '#{val.__class.__name}' instance"
+ else
+ -- plain table
+ return Const 'scope', Scope.from_table val
+ else
+ error "#{name}: cannot wrap Lua type '#{type val}'"
+
+ Const typ, val
+
+:Const, :load_
diff --git a/core/init.moon b/core/init.moon
new file mode 100644
index 0000000..713f326
--- /dev/null
+++ b/core/init.moon
@@ -0,0 +1,13 @@
+import Op, Action from require 'core.base'
+
+import Const, load_ from require 'core.const'
+import Scope from require 'core.scope'
+load_!
+
+import Cell, RootCell from require 'core.cell'
+
+{
+ :Const, :Cell, :RootCell
+ :Op, :Action
+ :Scope
+}
diff --git a/core/invoke.moon b/core/invoke.moon
new file mode 100644
index 0000000..78c40a2
--- /dev/null
+++ b/core/invoke.moon
@@ -0,0 +1,79 @@
+import Const from require 'core.const'
+import Action from require 'core.base'
+import Scope from require 'core.scope'
+
+class UpdateChildren
+ new: (@children) =>
+
+ update: (dt) =>
+ for child in *@children
+ L\trace "updating #{child}"
+ L\push child\update, dt
+
+ get: => @children[#@children]\get!
+ getc: => @children[#@children]\getc!
+
+ __tostring: => '<forwarder>'
+
+class op_invoke extends Action
+ patch: (head) =>
+ return true if head == @head
+
+ @op\destroy! if @op
+
+ @head = head
+ assert @head.type == 'opdef', "cant op-invoke #{@head}"
+ @op = @head\getc!!
+
+ true
+
+ eval: (scope, tail) =>
+ args = [expr\eval scope, @registry for expr in *tail]
+ -- Const 'op', with @op
+ with @op
+ \setup unpack args
+
+class fn_invoke extends Action
+ -- @TODO:
+ -- need to :patch() the case where the new head is a new fndef
+ -- but corresponds to the last head over time
+
+ patch: (head) =>
+ return true if head == @head
+
+ @head = head
+
+ true
+
+ eval: (scope, tail) =>
+ assert @head.type == 'fndef', "cant fn-invoke #{@head}"
+ { :params, :body } = @head\getc!
+
+ assert #params == #tail, "argument count mismatch in #{@head}"
+
+ fn_scope = Scope @, scope
+
+ for i=1,#params
+ name = params[i]\getc!
+ argm = tail[i]
+ fn_scope\set name, L\push argm\eval, scope, @registry
+
+ body\eval fn_scope, @registry
+
+class do_expr extends Action
+ class DoWrapper
+ new: (@children) =>
+
+ update: (dt) =>
+ for child in *@children
+ L\push child\update, dt
+
+ get: => @children[#@children]\get!
+ getc: => @children[#@children]\getc!
+
+ __tostring: => '<dowrapper>'
+
+ eval: (scope, tail) =>
+ UpdateChildren [(expr\eval scope, @registry) or Const.empty! for expr in *tail]
+
+:op_invoke, :fn_invoke
diff --git a/scope.moon b/core/scope.moon
index 7378dd5..a840ba7 100644
--- a/scope.moon
+++ b/core/scope.moon
@@ -1,9 +1,7 @@
-local Const
+import Const from require 'core.const'
class Scope
new: (@node, @parent) =>
- import Const from require 'base'
-
@values = {}
set_raw: (key, val) => @values[key] = Const.wrap val, key
@@ -54,6 +52,4 @@ class Scope
buf ..= ">"
buf
-{
- :Scope
-}
+:Scope
diff --git a/lib/builtin.moon b/lib/builtin.moon
index 5c3d7d4..b4d6dc7 100644
--- a/lib/builtin.moon
+++ b/lib/builtin.moon
@@ -1,5 +1,4 @@
-import Action, Const, Cell from require 'base'
-import Scope from require 'scope'
+import Const, Cell, Action, Scope from require 'core'
class UpdateChildren
new: (@children) =>
diff --git a/lib/debug.moon b/lib/debug.moon
index f87b06a..6888d89 100644
--- a/lib/debug.moon
+++ b/lib/debug.moon
@@ -1,4 +1,4 @@
-import Op from require 'base'
+import Op from require 'core'
class out extends Op
setup: (name, @chld) =>
diff --git a/lib/gui.moon b/lib/gui.moon
index 37df233..69c97a3 100644
--- a/lib/gui.moon
+++ b/lib/gui.moon
@@ -1,5 +1,5 @@
{ graphics: lg } = love
-import Op from require 'base'
+import Op from require 'core'
import Registry from require 'registry'
import Copilot from require 'copilot'
diff --git a/lib/math.moon b/lib/math.moon
index 0a514a6..ca7321c 100644
--- a/lib/math.moon
+++ b/lib/math.moon
@@ -1,4 +1,4 @@
-import Op from require 'base'
+import Op from require 'core'
unpack or= table.unpack
class BinOp extends Op
diff --git a/lib/osc.moon b/lib/osc.moon
index 02e3ade..a2c992b 100644
--- a/lib/osc.moon
+++ b/lib/osc.moon
@@ -1,4 +1,4 @@
-import Op from require 'base'
+import Op from require 'core'
import pack, unpack from require 'osc'
import dns, udp from require 'socket'
diff --git a/lib/time.moon b/lib/time.moon
index 22457bb..567b16f 100644
--- a/lib/time.moon
+++ b/lib/time.moon
@@ -1,4 +1,4 @@
-import Op, Const from require 'base'
+import Const, Op from require 'core'
class lfo extends Op
tau = math.pi * 2
diff --git a/lib/util.moon b/lib/util.moon
index 5079b1b..ed643aa 100644
--- a/lib/util.moon
+++ b/lib/util.moon
@@ -1,4 +1,4 @@
-import Op from require 'base'
+import Op from require 'core'
class pick extends Op
setup: (@i, ...) =>
diff --git a/parsing.moon b/parsing.moon
index ba1f02e..91ad260 100644
--- a/parsing.moon
+++ b/parsing.moon
@@ -1,4 +1,4 @@
-import Const, Cell, RootCell from require 'base'
+import Const, Cell, RootCell from require 'core'
import R, S, P, V, C, Ct from require 'lpeg'
-- whitespace
diff --git a/registry.moon b/registry.moon
index 70955cb..51fa187 100644
--- a/registry.moon
+++ b/registry.moon
@@ -1,5 +1,4 @@
-import Scope from require 'scope'
-import Const from require 'base'
+import Const, Scope from require 'core'
class Registry
new: () =>
diff --git a/spec/cell_spec.moon b/spec/cell_spec.moon
index 2b0860c..6ec9fc8 100644
--- a/spec/cell_spec.moon
+++ b/spec/cell_spec.moon
@@ -1,5 +1,4 @@
-import Cell, RootCell, Const from require 'base'
-import Scope from require 'scope'
+import Cell, RootCell, Const, Scope from require 'core'
import Registry from require 'registry'
import Logger from require 'logger'
Logger.init 'silent'
@@ -7,7 +6,6 @@ Logger.init 'silent'
hello_world = Cell nil, { (Const.sym 'hello'), (Const.str 'world') }
two_plus_two = Cell nil, { (Const.sym '+'), (Const.num 2), (Const.num 2) }
-
describe 'Cell', ->
describe 'quoting', ->
it 'quotes children', ->
@@ -38,7 +36,8 @@ describe 'Cell', ->
reg = mock register: =>
root\quote nil, reg
- (assert.spy reg.register).was.called_with reg, root, (Const.num 2)
+ (assert.spy reg.register).was.called!
+ (assert.spy reg.register).was.called_with reg, match._, Const.num 2
describe 'evaluation', ->
registry = Registry!
diff --git a/spec/const_spec.moon b/spec/const_spec.moon
index 4e4028f..4def3a6 100644
--- a/spec/const_spec.moon
+++ b/spec/const_spec.moon
@@ -1,5 +1,4 @@
-import Const, Op, Action from require 'base'
-import Scope from require 'scope'
+import Const, Op, Action, Scope from require 'core'
import Logger from require 'logger'
Logger.init 'silent'
diff --git a/spec/parsing_spec.moon b/spec/parsing_spec.moon
index 4bd5067..c405245 100644
--- a/spec/parsing_spec.moon
+++ b/spec/parsing_spec.moon
@@ -1,5 +1,5 @@
import space, atom, expr, explist, cell, program, comment from require 'parsing'
-import Const from require 'base'
+import Const from require 'core'
import Logger from require 'logger'
Logger.init 'silent'
diff --git a/spec/registry_spec.moon b/spec/registry_spec.moon
index 53a406c..de79744 100644
--- a/spec/registry_spec.moon
+++ b/spec/registry_spec.moon
@@ -1,5 +1,5 @@
import Registry from require 'registry'
-import Const from require 'base'
+import Const from require 'core'
mk = ->
mock destroy: =>
diff --git a/spec/scope_spec.moon b/spec/scope_spec.moon
index 97bc436..9e7ab80 100644
--- a/spec/scope_spec.moon
+++ b/spec/scope_spec.moon
@@ -1,5 +1,4 @@
-import Op, Const from require 'base'
-import Scope from require 'scope'
+import Scope, Const, Op from require 'core'
import Logger from require 'logger'
Logger.init 'silent'