aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authors-ol <s-ol@users.noreply.github.com>2020-02-03 13:41:05 +0000
committers-ol <s-ol@users.noreply.github.com>2020-02-03 13:41:05 +0000
commit08022c13ba1c4cd932a59f4b6ac7d964606f747e (patch)
treea9cd222563b881d7317169b5097fe092f86f4a1e /lib
parentForward references (diff)
downloadalive-08022c13ba1c4cd932a59f4b6ac7d964606f747e.tar.gz
alive-08022c13ba1c4cd932a59f4b6ac7d964606f747e.zip
50% of functions
Diffstat (limited to 'lib')
-rw-r--r--lib/builtin.moon137
-rw-r--r--lib/time.moon2
2 files changed, 116 insertions, 23 deletions
diff --git a/lib/builtin.moon b/lib/builtin.moon
index 8615afa..440e553 100644
--- a/lib/builtin.moon
+++ b/lib/builtin.moon
@@ -1,34 +1,56 @@
import Macro, Const, Forward from require 'base'
import Scope from require 'scope'
+-- (def sym1 val-expr1
+-- [sym2 val-expr2]...)
+--
+-- declare symbols in parent scope
+--
+-- if val-expr is a expand-time constant, defines a `Const`,
+-- otherwise places a `Forward` for the expr
class def extends Macro
expand: (scope) =>
+ L\trace "expanding #{@}"
assert #@node > 2, "'def' requires at least 3 arguments"
assert #@node % 2 == 1, "'def' requires an even number of arguments"
- L\trace @
L\push ->
for i=2,#@node,2
- name, val = @node[i], @node[i+1]
+ name, val_expr = @node[i], @node[i+1]
assert name.atom_type == 'sym', "'def's argument ##{i} has to be a symbol"
- val\expand @node.scope
-
- if val.value
- -- expand-time constant
- scope\set name.raw, val.value
- else
- -- patch-time expression
- scope\set name.raw, Forward val
+ name = name\expand_quoted!\getc!
+
+ scope\set name, val_expr\expand @node.scope
+
+ -- @TODO: expand to Forward in Xpr:expand
+ -- if val = val_expr\expand @node.scope
+ -- -- expand-time constant
+ -- scope\set name, val
+ -- else
+ -- -- patch-time expression
+ -- scope\set name, Forward val_expr
nil
+ patch: (map) =>
+ L\trace "patching #{@}"
+ for child in *@node[3,,2]
+ L\push child\patch, map
+
+ update: (dt) =>
+ L\trace "updating #{@}"
+ for child in *@node[3,,2]
+ L\push child\update, dt
+
+-- (require name-str)
+--
+-- require a lua module and return its `Scope`
+-- name-str has to be an expand-time constant
class _require extends Macro
expand: (scope) =>
+ L\trace "expanding #{@}"
assert #@node == 2, "'require' takes only one parameter"
-
- L\trace @
- L\push ->
- for child in *@node[2,]
- child\expand @node.scope
+ for child in *@node[2,]
+ L\push child\expand, @node.scope
name = @node\tail!
assert name.type == 'str', "'require' only works on strings"
@@ -37,20 +59,91 @@ class _require extends Macro
scope = Scope.from_table require "lib.#{name\getc!}"
Const 'scope', scope
+-- (use scope1 [scope2]...)
+--
+-- merge scopes into parent scope
+-- scopes have to be expand-time constants
class use extends Macro
expand: (scope) =>
- L\trace @
- L\push ->
- for child in *@node[2,]
- value = child\expand @node.scope
- L\trace @, "merging #{value} into #{scope}"
- assert value.type == 'scope', "'use' only works on scopes"
- scope\use value\getc!
+ L\trace "expanding #{@}"
+ for child in *@node[2,]
+ value = L\push child\expand, @node.scope
+ L\trace @, "merging #{value} into #{scope}"
+ assert value.type == 'scope', "'use' only works on scopes"
+ scope\use value\getc!
nil
+-- ((fn ...) arg-expr1 [arg-expr2]...)
+--
+-- invoke a function
+class FunctionInvocation extends Macro
+ new: (@node, @params, @body_tpl) =>
+ super @node
+
+ expand: (scope) =>
+ L\trace "expanding #{@}"
+ assert (#@params + 1) == #@node, "argument count mismatch in #{@node[1]}"
+
+ for i=1,#@params
+ param = @params[i]\getc!
+ argument = @node[i+1]
+ L\trace "EXPANDING ARG", argument
+ @node.scope\set param, L\push argument\expand, scope
+
+ @body = @body_tpl\clone @node.tag
+ val = @body\expand @node.scope
+ val
+
+ patch: (map) =>
+ L\trace "patching #{@}:"
+ for child in *@node[2,]
+ L\push child\patch, map
+
+ @body\patch map
+
+ update: (dt) =>
+ L\trace "updating #{@}:"
+ @body\update dt
+
+ for child in *@node[2,]
+ L\push child\update, dt
+
+ destroy: (dt) =>
+ L\trace "destroying #{@}"
+ @body.value\destroy! if @body.value
+
+ mt = { __call: (...) => @call ... }
+ with_def: (params, body) ->
+ call = (node) => FunctionInvocation node, params, body
+ setmetatable { :call, __name: 'Invocation' }, mt
+
+-- (fn (p1 [p2]...) body-expr)
+--
+-- declare a function
+--
+-- pX are symbols that will resolve to a 'Forward' in the body
+class fn extends Macro
+ expand: (scope) =>
+ L\trace "expanding #{@}"
+ assert #@node == 3, "'fn' takes exactly three arguments"
+ params, body = @node[2], @node[3]
+
+ assert params.type == 'Xpr', "'fn's first argument has to be an expression"
+ param_symbols = for param in *params
+ assert param.atom_type == 'sym', "function parameter declaration has to be a symbol"
+ param\expand_quoted!
+
+ Const 'macrodef', FunctionInvocation.with_def param_symbols, body
+
+ patch: (map) =>
+ L\trace "patching #{@}"
+
+ update: (dt) =>
+
{
:def
require: _require
:use
+ :fn
}
diff --git a/lib/time.moon b/lib/time.moon
index 4fe5d7c..3252b9f 100644
--- a/lib/time.moon
+++ b/lib/time.moon
@@ -6,9 +6,9 @@ class lfo extends Op
super ...
@phase = 0
-
default_wave = Const 'str', 'sin'
setup: (@freq, @wave=default_wave) =>
+ L\trace "setup #{@}, freq=#{@freq}, wave=#{@wave}"
update: (dt) =>
@phase += dt * @freq\get!