aboutsummaryrefslogtreecommitdiffstats
path: root/alv
diff options
context:
space:
mode:
Diffstat (limited to 'alv')
-rw-r--r--alv/ast.moon2
-rw-r--r--alv/base/init.moon15
-rw-r--r--alv/base/input.moon27
-rw-r--r--alv/base/match.moon29
-rw-r--r--alv/builtin.moon75
-rw-r--r--alv/cell.moon11
-rw-r--r--alv/copilot.moon8
-rw-r--r--alv/init.moon16
-rw-r--r--alv/invoke.moon27
-rw-r--r--alv/parsing.moon10
-rw-r--r--alv/result/base.moon (renamed from alv/stream/base.moon)14
-rw-r--r--alv/result/const.moon (renamed from alv/stream/value.moon)161
-rw-r--r--alv/result/evt.moon (renamed from alv/stream/event.moon)23
-rw-r--r--alv/result/init.moon21
-rw-r--r--alv/result/io.moon (renamed from alv/stream/io.moon)12
-rw-r--r--alv/result/sig.moon121
-rw-r--r--alv/rtnode.moon (renamed from alv/result.moon)28
-rw-r--r--alv/scope.moon25
-rw-r--r--alv/stream/init.moon18
-rw-r--r--alv/types.moon101
20 files changed, 474 insertions, 270 deletions
diff --git a/alv/ast.moon b/alv/ast.moon
index 7090869..cff8947 100644
--- a/alv/ast.moon
+++ b/alv/ast.moon
@@ -1,7 +1,7 @@
----
-- AST Node Interface.
--
--- implemented by `ValueStream` and `Cell`.
+-- implemented by `Constant` and `Cell`.
--
-- @classmod AST
diff --git a/alv/base/init.moon b/alv/base/init.moon
index c37d85c..71e9cea 100644
--- a/alv/base/init.moon
+++ b/alv/base/init.moon
@@ -11,10 +11,11 @@
-- @see Input
-- @see base.match.val
-- @see base.match.evt
--- @see ValueStream
--- @see EventStream
+-- @see Constant
+-- @see SigStream
+-- @see EvtStream
-- @see IOStream
--- @see Result
+-- @see RTNode
-- @see Error
import Op from require 'alv.base.op'
@@ -22,8 +23,8 @@ import Builtin from require 'alv.base.builtin'
import FnDef from require 'alv.base.fndef'
import Input from require 'alv.base.input'
import val, evt from require 'alv.base.match'
-import ValueStream, EventStream, IOStream from require 'alv.stream'
-import Result from require 'alv.result'
+import Constant, SigStream, EvtStream, IOStream from require 'alv.result'
+import RTNode from require 'alv.rtnode'
import Error from require 'alv.error'
{
@@ -34,6 +35,6 @@ import Error from require 'alv.error'
:val, :evt
-- redundant exports, to keep anything an extension might need in one import
- :ValueStream, :EventStream, :IOStream
- :Result, :Error
+ :Constant, :SigStream, :EvtStream, :IOStream
+ :RTNode, :Error
}
diff --git a/alv/base/input.moon b/alv/base/input.moon
index fe01f88..dea91c9 100644
--- a/alv/base/input.moon
+++ b/alv/base/input.moon
@@ -2,8 +2,8 @@
-- Update scheduling policy for `Op` arguments.
--
-- @classmod Input
-import ValueStream, EventStream, IOStream from require 'alv.stream'
-import Result from require 'alv.result'
+import Constant, SigStream, EvtStream, IOStream from require 'alv.result'
+import RTNode from require 'alv.rtnode'
inherits = (klass, frm) ->
assert klass, "cant find the ancestor of nil"
@@ -53,7 +53,7 @@ class Input
--
-- must return a boolean indicating whether `Op`s that refer to this instance
-- should be notified (via `Op:tick`). If not overwritten, delegates to
- -- `stream`:@{ValueStream:dirty|dirty}.
+ -- `stream`:@{SigStream:dirty|dirty}.
--
-- @treturn bool whether processing is necessary
dirty: => @stream\dirty!
@@ -77,7 +77,7 @@ class Input
--- the current value
--
- -- @tfield ValueStream stream
+ -- @tfield SigStream stream
--- members
-- @section members
@@ -98,9 +98,9 @@ class Input
-- Never marked dirty. Use this for input streams that are only read when
-- another `Input` is dirty.
--
- -- @tparam Stream|Result value
+ -- @tparam Stream|RTNode value
@cold: (value) ->
- if value.__class == Result
+ if value.__class == RTNode
value = assert value.value, "Input from result without value!"
ColdInput value
@@ -108,15 +108,15 @@ class Input
--
-- Behaviour depends on what kind of `Stream` `value` is:
--
- -- - `ValueStream`: Marked dirty only if old and new `ValueStream` differ.
- -- - `EventStream` and `IOStream`: Marked dirty only if the current
- -- `EventStream` is dirty.
+ -- - `SigStream`: Marked dirty only if old and new `SigStream` differ.
+ -- - `EvtStream` and `IOStream`: Marked dirty only if the current
+ -- `EvtStream` is dirty.
--
-- This is the most common `Input` strategy.
--
- -- @tparam Stream|Result value
+ -- @tparam Stream|RTNode value
@hot: (value) ->
- if value.__class == Result
+ if value.__class == RTNode
value = assert value.value, "Input from result without value!"
InputType = match_parent value, mapping
@@ -137,8 +137,9 @@ class IOInput extends Input
io: true
mapping = {
- [ValueStream]: ValueInput
- [EventStream]: Input
+ [Constant]: ColdInput
+ [SigStream]: ValueInput
+ [EvtStream]: Input
[IOStream]: IOInput
}
diff --git a/alv/base/match.moon b/alv/base/match.moon
index 62075c0..819b0b4 100644
--- a/alv/base/match.moon
+++ b/alv/base/match.moon
@@ -2,7 +2,7 @@
--- Pattern capturing for Op argument parsing.
--
-- There is only one basic buildings block for assembling patterns:
--- `Type`. It can match `ValueStream`s and `EventStream`s depending on its
+-- `Type`. It can match `SigStream`s and `EvtStream`s depending on its
-- metatype argument and can take an optional type name to match as an argument.
--
-- In addition to this primitive, the following modifiers are available:
@@ -21,12 +21,12 @@
-- - `-pat`: Shorthand for `Optional(pat)`
--
-- To perform the actual matching, call the `:match` method on a pattern and
--- pass a sequence of `Result`s. The method will either return the captured
--- `Result`s (or a table structuring them)
+-- pass a sequence of `RTNode`s. The method will either return the captured
+-- `RTNode`s (or a table structuring them)
--
-- Any ambiguous pattern can be set to 'recall mode' by invoking it.
--- Recalling patterns will memorize the first Result they match, and
--- only match further Results of the same type. For example
+-- Recalling patterns will memorize the first RTNode they match, and
+-- only match further RTNodes of the same type. For example
--
-- arg = (val.num / val.str)!
-- pattern = arg + arg
@@ -45,14 +45,11 @@
--
-- @module base.match
import Error from require 'alv.error'
-import ValueStream, EventStream from require 'alv.stream'
+import Primitive from require 'alv.types'
local Repeat, Sequence, Choice, Optional
-typestr = (result) ->
- str = result\type!
- str ..= '!' if result\metatype! == 'event'
- str
+typestr = (result) -> tostring result.value
class Pattern
match: (seq) =>
@@ -107,13 +104,17 @@ class Type extends Pattern
capture: (seq, i) =>
return unless seq[i]
type, mt = seq[i]\type!, seq[i]\metatype!
- return unless @metatype == mt
+ if @metatype == 'event'
+ return unless mt == '!'
+ else
+ return if mt == '!'
+
match = if @type then type == @type else @remember type
if match
1, seq[i]
__tostring: =>
- str = @type or @metatype
+ str = tostring @type or @metatype
str ..= '!' if @metatype == 'event'
str
@@ -272,7 +273,7 @@ class Optional extends Pattern
-- @table val
val = setmetatable {}, {
__index: (key) =>
- with v = Type 'value', key
+ with v = Type 'value', Primitive key
@[key] = v
__call: (...) => Type 'value', ...
@@ -290,7 +291,7 @@ val = setmetatable {}, {
-- @table evt
evt = setmetatable {}, {
__index: (key) =>
- with v = Type 'event', key
+ with v = Type 'event', Primitive key
@[key] = v
__call: (...) => Type 'event', ...
diff --git a/alv/builtin.moon b/alv/builtin.moon
index c80e483..767d8e1 100644
--- a/alv/builtin.moon
+++ b/alv/builtin.moon
@@ -6,16 +6,17 @@
--
-- @module builtin
import Builtin, Op, FnDef, Input, val, evt from require 'alv.base'
-import ValueStream, LiteralValue from require 'alv.stream.value'
+import Constant from require 'alv.result'
import Error from require 'alv.error'
-import Result from require 'alv.result'
+import RTNode from require 'alv.rtnode'
import Cell from require 'alv.cell'
import Scope from require 'alv.scope'
import Tag from require 'alv.tag'
import op_invoke from require 'alv.invoke'
+import Primitive from require 'alv.types'
lfs = require 'lfs'
-doc = ValueStream.meta
+doc = Constant.meta
meta:
name: 'doc'
summary: "Print documentation in console."
@@ -36,11 +37,11 @@ doc = ValueStream.meta
assert #tail == 1, "'doc' takes exactly one parameter"
result = L\push tail[1]\eval, scope
- with Result children: { def }
+ with RTNode children: { def }
meta = result.value.meta
L\print "(doc #{tail[1]}):\n#{format_meta meta}\n"
-def = ValueStream.meta
+def = Constant.meta
meta:
name: 'def'
summary: "Declare symbols in current scope."
@@ -63,9 +64,9 @@ Define the symbols `sym1`, `sym2`, … to resolve to the values of `val-expr1`,
with val_expr\eval scope
scope\set name, \make_ref!
- Result :children
+ RTNode :children
-use = ValueStream.meta
+use = Constant.meta
meta:
name: 'use'
summary: "Merge scopes into current scope."
@@ -82,9 +83,9 @@ All arguments have to be evaltime constant."
value = result\const!
scope\use value\unwrap 'scope', "'use' only works on scopes"
- Result!
+ RTNode!
-require_ = ValueStream.meta
+require_ = Constant.meta
meta:
name: 'require'
summary: "Load a module."
@@ -102,7 +103,7 @@ require_ = ValueStream.meta
L\trace @, "loading module #{name}"
COPILOT\require name
-import_ = ValueStream.meta
+import_ = Constant.meta
meta:
name: 'import'
summary: "Require and define modules."
@@ -120,9 +121,9 @@ current scope."
name = child\unwrap 'sym'
with COPILOT\require name
scope\set name, \make_ref!
- Result :children
+ RTNode :children
-import_star = ValueStream.meta
+import_star = Constant.meta
meta:
name: 'import*'
summary: "Require and use modules."
@@ -138,9 +139,9 @@ Requires modules `sym1`, `sym2`, … and merges them into the current scope."
children = for i, child in ipairs tail
with COPILOT\require child\unwrap 'sym'
scope\use .value\unwrap 'scope'
- Result :children
+ RTNode :children
-export_ = ValueStream.meta
+export_ = Constant.meta
meta:
name: 'export'
summary: "Evaluate definitions in a new scope and return it."
@@ -152,9 +153,9 @@ Evaluate `expr1`, `expr2`, … in a new Scope and return scope."
eval: (scope, tail) =>
new_scope = Scope scope
children = [expr\eval new_scope for expr in *tail]
- Result :children, value: ValueStream.wrap new_scope
+ RTNode :children, value: Constant.wrap new_scope
-export_star = ValueStream.meta
+export_star = Constant.meta
meta:
name: 'export*'
summary: "Export specific symbol definitions as a module/scope."
@@ -179,9 +180,9 @@ Copies the containing scope if no symbols are given."
with result = scope\get name
new_scope\set name, result
- Result :children, value: ValueStream.wrap new_scope
+ RTNode :children, value: Constant.wrap new_scope
-fn = ValueStream.meta
+fn = Constant.meta
meta:
name: 'fn'
summary: "Declare a function."
@@ -201,13 +202,13 @@ function is invoked."
assert param.type == 'sym', "function parameter declaration has to be a symbol"
param
- Result value: with ValueStream.wrap FnDef param_symbols, body, scope
+ RTNode value: with Constant.wrap FnDef param_symbols, body, scope
.meta = {
summary: "(user defined function)"
examples: { "(??? #{table.concat [p! for p in *param_symbols], ' '})" }
}
-defn = ValueStream.meta
+defn = Constant.meta
meta:
name: 'defn'
summary: "Define a function."
@@ -229,16 +230,16 @@ function is invoked."
assert param.type == 'sym', "function parameter declaration has to be a symbol"
param
- value = with ValueStream.wrap FnDef param_symbols, body, scope
+ value = with Constant.wrap FnDef param_symbols, body, scope
.meta =
:name
summary: "(user defined function)"
examples: { "(#{name} #{table.concat [p! for p in *param_symbols], ' '})" }
- scope\set name, Result :value
- Result!
+ scope\set name, RTNode :value
+ RTNode!
-do_expr = ValueStream.meta
+do_expr = Constant.meta
meta:
name: 'do'
summary: "Evaluate multiple expressions in a new scope."
@@ -250,9 +251,9 @@ Evaluate `expr1`, `expr2`, … and return the value of the last expression."
eval: (scope, tail) =>
scope = Scope scope
children = [expr\eval scope for expr in *tail]
- Result :children, value: children[#children].value
+ RTNode :children, value: children[#children].value
-if_ = ValueStream.meta
+if_ = Constant.meta
meta:
name: 'if'
summary: "Make an evaltime const choice."
@@ -277,7 +278,7 @@ to `then-expr`, otherwise it is equivalent to `else-xpr` if given, or nil otherw
elseif xelse
xelse\eval scope
-trace_ = ValueStream.meta
+trace_ = Constant.meta
meta:
name: 'trace!'
summary: "Trace an expression's value at evaltime."
@@ -291,7 +292,7 @@ trace_ = ValueStream.meta
with result = L\push tail[1]\eval, scope
L\print "trace! #{tail[1]\stringify!}: #{result.value}"
-trace = ValueStream.meta
+trace = Constant.meta
meta:
name: 'trace'
summary: "Trace an expression's values at runtime."
@@ -313,13 +314,13 @@ trace = ValueStream.meta
tag = @tag\clone Tag.parse '-1'
inner = Cell tag, {
- LiteralValue 'opdef', traceOp, 'trace'
- ValueStream.str tostring tail[1]
+ Constant.literal (Primitive 'opdef'), traceOp, 'trace'
+ Constant.str tostring tail[1]
tail[1]
}
inner\eval scope
-print = ValueStream.meta
+print = Constant.meta
meta:
name: 'print'
summary: "Print string values."
@@ -348,23 +349,23 @@ Scope.from_table {
export: export_
'export*': export_star
- true: ValueStream.meta
+ true: Constant.meta
meta:
name: 'true'
summary: "The boolean constant `true`."
- value: ValueStream.bool true
+ value: Constant.bool true
- false: ValueStream.meta
+ false: Constant.meta
meta:
name: 'false'
summary: "The boolean constant `false`."
- value: ValueStream.bool false
+ value: Constant.bool false
- bang: ValueStream.meta
+ bang: Constant.meta
meta:
name: 'bang'
summary: "A `bang` value-constant."
- value: ValueStream 'bang', true
+ value: Constant 'bang', true
:fn, :defn
'do': do_expr
diff --git a/alv/cell.moon b/alv/cell.moon
index 6d5e207..2e00195 100644
--- a/alv/cell.moon
+++ b/alv/cell.moon
@@ -5,9 +5,10 @@
-- nodes), a `Tag`, and optionally the internal whitespace as parsed.
--
-- @classmod Cell
-import ValueStream from require 'alv.stream'
+import Constant from require 'alv.result'
import Error from require 'alv.error'
import op_invoke, fn_invoke from require 'alv.invoke'
+import Primitive from require 'alv.types'
import Tag from require 'alv.tag'
local RootCell
@@ -73,11 +74,11 @@ class Cell
head = assert @head!, Error 'syntax', "cannot evaluate empty expr"
head = (head\eval scope)\const!
Builtin = switch head.type
- when 'opdef'
+ when (Primitive 'opdef')
op_invoke
- when 'fndef'
+ when (Primitive 'fndef')
fn_invoke
- when 'builtin'
+ when (Primitive 'builtin')
head\unwrap!
else
error Error 'type', "#{head} is not an opdef, fndef or builtin"
@@ -157,7 +158,7 @@ class Cell
-- @type RootCell
class RootCell extends Cell
- head: => ValueStream.sym 'do'
+ head: => Constant.sym 'do'
tail: => @children
clone: (parent) =>
diff --git a/alv/copilot.moon b/alv/copilot.moon
index 7ef2134..d9b674f 100644
--- a/alv/copilot.moon
+++ b/alv/copilot.moon
@@ -6,8 +6,8 @@ lfs = require 'lfs'
import Scope from require 'alv.scope'
import Module from require 'alv.module'
import Error from require 'alv.error'
-import Result from require 'alv.result'
-import ValueStream from require 'alv.stream'
+import RTNode from require 'alv.rtnode'
+import Constant from require 'alv.result'
export COPILOT
@@ -41,12 +41,12 @@ class Copilot
--- require a module.
-- @tparam string name
- -- @treturn Result result
+ -- @treturn RTNode root
require: (name) =>
Error.wrap "loading module '#{name}'", ->
ok, lua = pcall require, "alv-lib.#{name}"
if ok
- Result value: ValueStream.wrap lua
+ RTNode value: Constant.wrap lua
else
assert @modules, "no current eval cycle?"
if mod = @modules[name]
diff --git a/alv/init.moon b/alv/init.moon
index f2fed2f..95432f3 100644
--- a/alv/init.moon
+++ b/alv/init.moon
@@ -13,8 +13,9 @@ cycle = require 'alv.cycle'
version = require 'alv.version'
import Logger from require 'alv.logger'
-import ValueStream, EventStream, IOStream from require 'alv.stream'
-import Result from require 'alv.result'
+
+import Constant, SigStream, EvtStream, IOStream from require 'alv.result'
+import RTNode from require 'alv.rtnode'
import Scope from require 'alv.scope'
import Error from require 'alv.error'
import Registry, SimpleRegistry from require 'alv.registry'
@@ -34,10 +35,11 @@ import Copilot from require 'alv.copilot'
--- exports
-- @table exports
-- @tfield version version
--- @tfield ValueStream ValueStream
--- @tfield EventStream EventStream
+-- @tfield Constant Constant
+-- @tfield SigStream SigStream
+-- @tfield EvtStream EvtStream
-- @tfield IOStream IOStream
--- @tfield Result Result
+-- @tfield RTNode RTNode
-- @tfield Cell Cell
-- @tfield RootCell RootCell
-- @tfield Scope Scope
@@ -51,9 +53,9 @@ import Copilot from require 'alv.copilot'
{
:version
- :ValueStream, :EventStream, :IOStream
+ :Constant, :SigStream, :EvtStream, :IOStream
:Cell, :RootCell
- :Result, :Scope, :Error
+ :RTNode, :Scope, :Error
:Registry, :SimpleRegistry, :Tag
diff --git a/alv/invoke.moon b/alv/invoke.moon
index 439af49..4d9dfc9 100644
--- a/alv/invoke.moon
+++ b/alv/invoke.moon
@@ -2,10 +2,15 @@
-- Builtins for invoking `Op`s and `FnDef`s.
--
-- @module invoke
-import Result from require 'alv.result'
+import RTNode from require 'alv.rtnode'
import Builtin from require 'alv.base'
import Scope from require 'alv.scope'
import Error from require 'alv.error'
+import Primitive from require 'alv.types'
+
+opdef = Primitive 'opdef'
+fndef = Primitive 'fndef'
+sym = Primitive 'sym'
get_name = (value, raw) ->
meta = if value.meta then value.meta.name
@@ -34,7 +39,7 @@ class op_invoke extends Builtin
@op = prev.op\fork!
prev.forked = COPILOT.T
else
- def = @head\unwrap 'opdef', "cant op-invoke #{@head}"
+ def = @head\unwrap opdef, "cant op-invoke #{@head}"
@op = def!
--- `Builtin:destroy` implementation.
@@ -50,11 +55,11 @@ class op_invoke extends Builtin
-- checks if any of `op`:@{Op:all_inputs|all_inputs} are @{Input:dirty|dirty},
-- and if so, calls `op`:@{Op:tick|tick}.
--
- -- The `Result` contains `op`, `Op.value` and all the `Result`s from the tail.
+ -- The `RTNode` contains `op`, `Op.value` and all the `RTNode`s from the tail.
--
-- @tparam Scope scope the active scope
-- @tparam {AST,...} tail the arguments to this expression
- -- @treturn Result
+ -- @treturn RTNode
eval: (scope, tail) =>
children = [L\push expr\eval, scope for expr in *tail]
@@ -73,7 +78,7 @@ class op_invoke extends Builtin
for input in @op\all_inputs!
input\finish_setup!
- Result :children, value: @op.out, op: @op
+ RTNode :children, value: @op.out, op: @op
--- The `Op` instance.
--
@@ -92,18 +97,18 @@ class fn_invoke extends Builtin
-- `FnDef.body` with the prefix `Builtin.tag`, and `AST:eval`s it in the newly
-- created `Scope`.
--
- -- The `Result` contains the `Stream` from the cloned AST, and its children
- -- are all the `Result`s from evaluating the tail as well as the cloned
+ -- The `RTNode` contains the `Stream` from the cloned AST, and its children
+ -- are all the `RTNode`s from evaluating the tail as well as the cloned
-- `AST`s.
--
-- @tparam Scope caller_scope the active scope
-- @tparam {AST,...} tail the arguments to this expression
- -- @treturn Result the result of this evaluation
+ -- @treturn RTNode the result of this evaluation
eval: (caller_scope, tail) =>
name = get_name @head, @cell\head!
frame = "invoking function #{name} at [#{@tag}]"
- fndef = @head\unwrap 'fndef', "cant fn-invoke #{@head}"
+ fndef = @head\unwrap fndef, "cant fn-invoke #{@head}"
{ :params, :body } = fndef
if #params != #tail
err = Error 'argument', "expected #{#params} arguments, found #{#tail}"
@@ -113,7 +118,7 @@ class fn_invoke extends Builtin
fn_scope = Scope fndef.scope, caller_scope
children = for i=1,#params
- name = params[i]\unwrap 'sym'
+ name = params[i]\unwrap sym
with L\push tail[i]\eval, caller_scope
fn_scope\set name, \make_ref!
@@ -121,7 +126,7 @@ class fn_invoke extends Builtin
result = Error.wrap frame, clone\eval, fn_scope
table.insert children, result
- Result :children, value: result.value
+ RTNode :children, value: result.value
{
:op_invoke, :fn_invoke
diff --git a/alv/parsing.moon b/alv/parsing.moon
index f9d6f98..9cc46d7 100644
--- a/alv/parsing.moon
+++ b/alv/parsing.moon
@@ -2,7 +2,7 @@
-- Lpeg Grammar for parsing `alive` code.
--
-- @module parsing
-import ValueStream from require 'alv.stream'
+import Constant from require 'alv.result'
import Cell from require 'alv.cell'
import Tag from require 'alv.tag'
import R, S, P, V, C, Ct from require 'lpeg'
@@ -20,15 +20,15 @@ mspace = (comment + wc)^0 / 1 -- optional whitespace
-- atoms
digit = R '09'
first = (R 'az', 'AZ') + S '-_+*/.!?=%'
-sym = first * (first + digit)^0 / ValueStream\parse 'sym'
+sym = first * (first + digit)^0 / Constant\parse 'sym'
-strd = '"' * (C ((P '\\"') + (P '\\\\') + (1 - P '"'))^0) * '"' / ValueStream\parse 'str', '\"'
-strq = "'" * (C ((P "\\'") + (P '\\\\') + (1 - P "'"))^0) * "'" / ValueStream\parse 'str', '\''
+strd = '"' * (C ((P '\\"') + (P '\\\\') + (1 - P '"'))^0) * '"' / Constant\parse 'str', '\"'
+strq = "'" * (C ((P "\\'") + (P '\\\\') + (1 - P "'"))^0) * "'" / Constant\parse 'str', '\''
str = strd + strq
int = digit^1
float = (digit^1 * '.' * digit^0) + (digit^0 * '.' * digit^1)
-num = ((P '-')^-1 * (float + int)) / ValueStream\parse 'num'
+num = ((P '-')^-1 * (float + int)) / Constant\parse 'num'
atom = num + sym + str
diff --git a/alv/stream/base.moon b/alv/result/base.moon
index 37cc8a4..26af4b4 100644
--- a/alv/stream/base.moon
+++ b/alv/result/base.moon
@@ -1,7 +1,7 @@
----
-- base Stream interface.
--
--- implemented by `ValueStream`, `EventStream`, and `IOStream`.
+-- implemented by `Constant`, `SigStream`, `EvtStream`, and `IOStream`.
--
-- @classmod Stream
@@ -9,7 +9,7 @@ class Stream
--- Stream interface.
--
-- Methods that have to be implemented by `Stream` implementations
--- (`ValueStream`, `EventStream`, `IOStream`).
+-- (`SigStream`, `EvtStream`, `IOStream`).
--
-- @section interface
@@ -25,6 +25,9 @@ class Stream
-- @function fork
-- @treturn Stream
+ __tostring: => "<#{@type}#{@metatype} #{@type\pp @value}>"
+ __inherited: (cls) => cls.__base.__tostring or= @__tostring
+
--- the type name of this Stream's value.
--
-- the following builtin typenames are used:
@@ -41,6 +44,13 @@ class Stream
--
-- @tfield string type
+ --- the metatype string for this Stream.
+ --
+ -- one of `=` (`Constant`), `~` (`SigStream`),
+ -- `!` (`EvtStream` and `IOStream`).
+ --
+ -- @tfield string type
+
--- documentation metadata.
--
-- an optional table containing metadata for error messages and
diff --git a/alv/stream/value.moon b/alv/result/const.moon
index 3409537..10bc943 100644
--- a/alv/stream/value.moon
+++ b/alv/result/const.moon
@@ -1,13 +1,19 @@
----
--- Continuous stream of values.
+-- Constant Value.
--
--- Implements the `Stream` and `AST` intefaces.
+-- Implements the `Stream` and `AST` inteface.
--
--- @classmod ValueStream
-import Stream from require 'alv.stream.base'
-import Result from require 'alv.result'
+-- @classmod Constant
+import Stream from require 'alv.result.base'
+import RTNode from require 'alv.rtnode'
import Error from require 'alv.error'
import scope, base from require 'alv.cycle'
+import Primitive from require 'alv.types'
+
+num = Primitive 'num'
+str = Primitive 'str'
+sym = Primitive 'sym'
+bool = Primitive 'bool'
ancestor = (klass) ->
assert klass, "cant find the ancestor of nil"
@@ -15,22 +21,11 @@ ancestor = (klass) ->
klass = klass.__parent
klass
-class ValueStream extends Stream
---- members
--- @section members
-
- --- return whether this stream was changed in the current tick.
+class Constant extends Stream
+ --- Whether this Result is dirty.
--
- -- @treturn bool
- dirty: => @updated == COPILOT.T
-
- --- update this stream's value.
- --
- -- Marks this stream as dirty for the remainder of the current tick.
- set: (value) =>
- if value != @value
- @value = value
- @updated = COPILOT.T
+ -- @tresult bool always `false`.
+ dirty: => false
--- unwrap to the Lua type.
--
@@ -47,67 +42,25 @@ class ValueStream extends Stream
--
-- Used to insulate eval-cycles from each other.
--
- -- @treturn ValueStream
- fork: =>
- with ValueStream @type, @value, @raw
- .updated = @updated
+ -- @treturn Constant
+ fork: => @
--- alias for `unwrap`.
__call: (...) => @unwrap ...
--- compare two values.
--
- -- Compares two `ValueStream`s by comparing their types and their Lua values.
+ -- Compares two `SigStream`s by comparing their types and their Lua values.
__eq: (other) => other.type == @type and other.value == @value
- __tostring: =>
- value = if @meta.name
- @meta.name
- else if 'table' == (type @value) and rawget @value, '__base'
- @value.__name
- else
- tostring @value
- "<#{@@__name} #{@type}: #{value}>"
-
--- Stream metatype.
--
- -- @tfield string metatype
- metatype: 'value'
-
- --- the type name of this stream.
- --
- -- the following builtin typenames are used:
- --
- -- - `str` - strings, `value` is a Lua string
- -- - `sym` - symbols, `value` is a Lua string
- -- - `num` - numbers, `value` is a Lua number
- -- - `bool` - booleans, `value` is a Lua boolean
- -- - `bang` - trigger signals, `value` is a Lua boolean
- -- - `opdef` - `value` is an `Op` subclass
- -- - `builtin` - `value` is a `Builtin` subclass
- -- - `fndef` - `value` is a `FnDef` instance
- -- - `scope` - `value` is a `Scope` instance
- --
- -- @tfield string type
-
- --- the wrapped Lua value.
- -- @tfield any value
-
- --- documentation metadata.
- --
- -- an optional table containing metadata for error messages and
- -- documentation. The following keys are recognized:
- --
- -- - `name`: optional name
- -- - `summary`: single-line description (markdown)
- -- - `examples`: optional list of single-line code examples
- -- - `description`: optional full-text description (markdown)
- --
- -- @tfield ?table meta
+ -- @tfield string metatype (`=`)
+ metatype: '='
--- AST interface
--
--- `ValueStream` implements the `AST` interface.
+-- `SignStream` implements the `AST` interface.
-- @section ast
--- evaluate this literal constant.
@@ -117,12 +70,14 @@ class ValueStream extends Stream
-- Resolves `sym`s in `scope` and returns a reference to them.
--
-- @tparam Scope scope the scope to evaluate in
- -- @treturn Result the evaluation result
+ -- @treturn RTNode the evaluation result
eval: (scope) =>
+ return RTNode value: @ if @literal
+
switch @type
- when 'num', 'str'
- Result value: @
- when 'sym'
+ when num, str
+ RTNode value: @
+ when sym
Error.wrap "resolving symbol '#{@value}'", scope\get, @value
else
error "cannot evaluate #{@}"
@@ -132,17 +87,17 @@ class ValueStream extends Stream
-- Throws an error if `raw` is not set.
--
-- @treturn string the exact string this stream was parsed from
- stringify: => assert @raw, "stringifying ValueStream that wasn't parsed"
+ stringify: => @raw
--- clone this literal constant.
--
- -- @treturn ValueStream self
+ -- @treturn SignStream self
clone: (prefix) => @
--- static functions
-- @section static
- --- construct a new ValueStream.
+ --- construct a new Constant.
--
-- @classmethod
-- @tparam string type the type name
@@ -157,9 +112,9 @@ class ValueStream extends Stream
-- @tparam string sep the seperator char (only for `str`)
@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
+ 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
--- wrap a Lua value.
--
@@ -167,7 +122,7 @@ class ValueStream extends Stream
--
-- @tparam any val the value to wrap
-- @tparam[opt] string name the name of this value (for error logging)
- -- @treturn ValueStream
+ -- @treturn Constant
@wrap: (val, name='(unknown)') ->
typ = switch type val
when 'number' then 'num'
@@ -190,46 +145,52 @@ class ValueStream extends Stream
error "#{name}: cannot wrap '#{val.__class.__name}' instance"
else
-- plain table
- return ValueStream 'scope', scope.Scope.from_table val
+ val = scope.Scope.from_table val
+ 'scope'
else
error "#{name}: cannot wrap Lua type '#{type val}'"
- ValueStream typ, val
+ Constant (Primitive typ), val
--- create a constant number.
- -- @tparam number num the number
- -- @treturn ValueStream
- @num: (num) -> ValueStream 'num', num, tostring num
+ -- @tparam number val the number
+ -- @treturn Constant
+ @num: (val) -> Constant num, val, tostring val
--- create a constant string.
- -- @tparam string str the string
- -- @treturn ValueStream
- @str: (str) -> ValueStream 'str', str, "'#{str}'"
+ -- @tparam string val the string
+ -- @treturn Constant
+ @str: (val) -> Constant str, val, "'#{val}'"
--- create a constant symbol.
- -- @tparam string sym the symbol
- -- @treturn ValueStream
- @sym: (sym) -> ValueStream 'sym', sym, sym
+ -- @tparam string val the symbol
+ -- @treturn Constant
+ @sym: (val) -> Constant sym, val, val
--- create a constant boolean.
- -- @tparam boolean bool the boolean
- -- @treturn ValueStream
- @bool: (bool) -> ValueStream 'bool', bool, tostring bool
+ -- @tparam boolean val the boolean
+ -- @treturn Constant
+ @bool: (val) -> Constant bool, val, tostring val
+
+ --- create a forced-literal Constant.
+ --
+ -- For internal use in `Builtin`s only.
+ --
+ -- @treturn Constant
+ @literal: (...) ->
+ with Constant ...
+ .literal = true
--- wrap and document a value.
--
-- wraps `args.value` using `wrap`, then assigns `meta`.
--
-- @tparam table args table with keys `value` and `meta`
- -- @treturn ValueStream
+ -- @treturn Constant
@meta: (args) ->
- with ValueStream.wrap args.value
+ with Constant.wrap args.value
.meta = args.meta if args.meta
-class LiteralValue extends ValueStream
- eval: => Result value: @
-
{
- :ValueStream
- :LiteralValue
+ :Constant
}
diff --git a/alv/stream/event.moon b/alv/result/evt.moon
index 16716be..0559a70 100644
--- a/alv/stream/event.moon
+++ b/alv/result/evt.moon
@@ -1,13 +1,10 @@
----
-- Stream of momentary events.
--
--- @classmod EventStream
-import Stream from require 'alv.stream.base'
-import Result from require 'alv.result'
-import Error from require 'alv.error'
-import scope, base from require 'alv.cycle'
+-- @classmod EvtStream
+import Stream from require 'alv.result.base'
-class EventStream extends Stream
+class EvtStream extends Stream
--- members
-- @section members
@@ -44,19 +41,17 @@ class EventStream extends Stream
--
-- Used to wrap insulate eval-cycles from each other.
--
- -- @treturn EventStream
+ -- @treturn EvtStream
fork: => @@ @type
--- alias for `unwrap`.
__call: (...) => @unwrap ...
-
- __tostring: =>
- "<#{@@__name} #{@type}>"
+ __tostring: => "<#{@type}#{@metatype} #{@type\pp @value}>"
--- Stream metatype.
--
- -- @tfield string metatype
- metatype: 'event'
+ -- @tfield string metatype (`!`)
+ metatype: '!'
--- the type name of the stream.
--
@@ -89,12 +84,12 @@ class EventStream extends Stream
--- static functions
-- @section static
- --- construct a new EventStream.
+ --- construct a new EvtStream.
--
-- @classmethod
-- @tparam string type the type name
new: (type) => super type
{
- :EventStream
+ :EvtStream
}
diff --git a/alv/result/init.moon b/alv/result/init.moon
new file mode 100644
index 0000000..aa7a115
--- /dev/null
+++ b/alv/result/init.moon
@@ -0,0 +1,21 @@
+----
+-- `Stream` interface and implementations.
+--
+-- @see Stream
+-- @see Constant
+-- @see SigStream
+-- @see EvtStream
+-- @see IOStream
+--
+-- @module stream
+import Constant from require 'alv.result.const'
+import SigStream from require 'alv.result.sig'
+import EvtStream from require 'alv.result.evt'
+import IOStream from require 'alv.result.io'
+
+{
+ :Constant
+ :SigStream
+ :EvtStream
+ :IOStream
+}
diff --git a/alv/stream/io.moon b/alv/result/io.moon
index e17daa8..b12322c 100644
--- a/alv/stream/io.moon
+++ b/alv/result/io.moon
@@ -4,12 +4,12 @@
-- Unlike other `Stream`s, this is not updated/set by an `Op` instace, but is
-- continuously polled for changes by the runtime and may mark itself as
-- *dirty* at any point in time. All runtime execution happens due to IOStream
--- updates, which ripple through the `Result` tree.
+-- updates, which ripple through the `RTNode` tree.
--
-- @classmod IOStream
-import EventStream from require 'alv.stream.event'
+import EvtStream from require 'alv.result.evt'
-class IOStream extends EventStream
+class IOStream extends EvtStream
--- IOStream interface.
--
-- methods that have to be implemented by `IOStream` implementations.
@@ -42,13 +42,13 @@ class IOStream extends EventStream
-- via `Input.hot` should be notified (via `Op:tick`). May be called multiple
-- times. May be called before `poll` on the first frame after construction.
--
- -- If this is not overrided, the `EventStream` interface can be used, see
- -- `EventStream.add`, `EventStream.unwrap`, and `EventStream.dirty`.
+ -- If this is not overriden, the `EvtStream` interface can be used, see
+ -- `EvtStream.add`, `EvtStream.unwrap`, and `EvtStream.dirty`.
--
-- @function dirty
-- @treturn bool whether processing is required
- __inherited: (cls) => cls.__base.__tostring = @__tostring
+ __inherited: (cls) => cls.__base.__tostring or= @__tostring
{
:IOStream
diff --git a/alv/result/sig.moon b/alv/result/sig.moon
new file mode 100644
index 0000000..d7c18a3
--- /dev/null
+++ b/alv/result/sig.moon
@@ -0,0 +1,121 @@
+----
+-- Continuous stream of values.
+--
+-- @classmod SigStream
+import Stream from require 'alv.result.base'
+import Primitive from require 'alv.types'
+
+class SigStream extends Stream
+--- members
+-- @section members
+
+ --- return whether this stream was changed in the current tick.
+ --
+ -- @treturn bool
+ dirty: => @updated == COPILOT.T
+
+ --- update this stream's value.
+ --
+ -- Marks this stream as dirty for the remainder of the current tick.
+ set: (value) =>
+ if value != @value
+ @value = value
+ @updated = COPILOT.T
+
+ --- unwrap to the Lua type.
+ --
+ -- Asserts `@type == type` if `type` is given.
+ --
+ -- @tparam[opt] string type the type to check for
+ -- @tparam[optchain] string msg message to throw if type don't match
+ -- @treturn any `value`
+ unwrap: (type, msg) =>
+ assert type == @type, msg or "#{@} is not a #{type}" if type
+ @value
+
+ --- create a mutable copy of this stream.
+ --
+ -- Used to insulate eval-cycles from each other.
+ --
+ -- @treturn SigStream
+ fork: =>
+ with @@ @type, @value
+ .updated = @updated
+
+ --- alias for `unwrap`.
+ __call: (...) => @unwrap ...
+
+ --- compare two values.
+ --
+ -- Compares two `SigStream`s by comparing their types and their Lua values.
+ __eq: (other) => other.type == @type and other.value == @value
+
+ --- Stream metatype.
+ --
+ -- @tfield string metatype (`~`)
+ metatype: '~'
+
+ --- the type name of this stream.
+ --
+ -- the following builtin typenames are used:
+ --
+ -- - `str` - strings, `value` is a Lua string
+ -- - `sym` - symbols, `value` is a Lua string
+ -- - `num` - numbers, `value` is a Lua number
+ -- - `bool` - booleans, `value` is a Lua boolean
+ -- - `bang` - trigger signals, `value` is a Lua boolean
+ -- - `opdef` - `value` is an `Op` subclass
+ -- - `builtin` - `value` is a `Builtin` subclass
+ -- - `fndef` - `value` is a `FnDef` instance
+ -- - `scope` - `value` is a `Scope` instance
+ --
+ -- @tfield string type
+
+ --- the wrapped Lua value.
+ -- @tfield any value
+
+ --- documentation metadata.
+ --
+ -- an optional table containing metadata for error messages and
+ -- documentation. The following keys are recognized:
+ --
+ -- - `name`: optional name
+ -- - `summary`: single-line description (markdown)
+ -- - `examples`: optional list of single-line code examples
+ -- - `description`: optional full-text description (markdown)
+ --
+ -- @tfield ?table meta
+
+--- static functions
+-- @section static
+
+ --- construct a new SigStream.
+ --
+ -- @classmethod
+ -- @tparam string type the type name
+ -- @tparam any value the Lua value to be accessed through `unwrap`
+ new: (type, @value) => super type
+
+ --- create a number stream.
+ -- @tparam number val the number
+ -- @treturn SigStream
+ @num: (val) -> SigStream Primitive'num', val
+
+ --- create a string stream.
+ -- @tparam string val the string
+ -- @treturn SigStream
+ @str: (val) -> SigStream Primitive'str', val
+
+ --- create a symbol stream.
+ -- @tparam string val the symbol
+ -- @treturn symbol
+ @sym: (val) -> SigStream Primitive'sym', val
+
+ --- create a boolean stream.
+ -- @tparam boolean val the boolean
+ -- @treturn SigStream
+ @bool: (val) -> SigStream Primitive'bool', val
+
+{
+ :SigStream
+}
diff --git a/alv/result.moon b/alv/rtnode.moon
index 6f5ea28..dab4507 100644
--- a/alv/result.moon
+++ b/alv/rtnode.moon
@@ -1,15 +1,15 @@
----
--- Result of evaluating an expression.
+-- RTNode of evaluating an expression.
--
--- `Result`s form a tree that controls execution order and message passing
+-- `RTNode`s form a tree that controls execution order and message
-- between `Op`s.
--
--- @classmod Result
-class Result
+-- @classmod RTNode
+class RTNode
--- members
-- @section members
- --- return whether this Result's value is const.
+ --- return whether this RTNode's value is const.
is_const: => not next @side_inputs
--- assert value-constness and return the value.
@@ -22,20 +22,20 @@ class Result
--- assert this result has a value, return its type.
-- @treturn string
type: =>
- assert @value, "Result with value expected"
+ assert @value, "RTNode with value expected"
@value.type
--- assert this result has a value, returns its metatype.
-- @treturn string `"value"` or `"event"`
metatype: =>
- assert @value, "Result with value expected"
+ assert @value, "RTNode with value expected"
@value.metatype
--- create a copy of this result with value-copy semantics.
-- the copy has the same @value and @side_inputs, but will not update
-- anything on \tick.
make_ref: =>
- with Result value: @value
+ with RTNode value: @value
.side_inputs = @side_inputs
--- poll all IOStream instances that are effecting this (sub)tree.
@@ -73,7 +73,7 @@ class Result
@op\tick!
__tostring: =>
- buf = "<result=#{@value}"
+ buf = "<RT=#{@value}"
buf ..= " #{@op}" if @op
buf ..= " (#{#@children} children)" if #@children > 0
buf ..= ">"
@@ -87,11 +87,11 @@ class Result
--
-- @tfield ?Op op
- --- list of child `Result`s from subexpressions
+ --- list of child `RTNode`s from subexpressions
--
- -- @tfield {}|{Result,...} children
+ -- @tfield {}|{RTNode,...} children
- --- cached mapping of all `Stream`/`Input` pairs affecting this Result.
+ --- cached mapping of all `Stream`/`Input` pairs affecting this RTNode.
--
-- This is the union of all `children`s `side_inputs` and all `Input`s from
-- `op` that are not the `value` of any child.
@@ -101,7 +101,7 @@ class Result
--- static functions
-- @section static
- --- create a new Result.
+ --- create a new RTNode.
-- @classmethod
-- @param params table with optional keys op, value, children. default: {}
new: (params={}) =>
@@ -122,5 +122,5 @@ class Result
@side_inputs[input.stream] = input
{
- :Result
+ :RTNode
}
diff --git a/alv/scope.moon b/alv/scope.moon
index 6a0e2a5..575c36e 100644
--- a/alv/scope.moon
+++ b/alv/scope.moon
@@ -1,10 +1,11 @@
----
--- Mapping from `sym`s to `Result`s.
+-- Mapping from `sym`s to `RTNode`s.
--
-- @classmod Scope
-import ValueStream from require 'alv.stream'
-import Result from require 'alv.result'
+import Constant from require 'alv.result'
+import RTNode from require 'alv.rtnode'
import Error from require 'alv.error'
+import Primitive from require 'alv.types'
class Scope
--- members
@@ -12,21 +13,21 @@ class Scope
--- set a Lua value in the scope.
--
- -- wraps `val` in a `ValueStream` and `Result` before calling `set`.
+ -- wraps `val` in a `Constant` and `RTNode` before calling `set`.
--
-- @tparam string key
-- @tparam any val
set_raw: (key, val) =>
- value = ValueStream.wrap val, key
- @values[key] = Result :value
+ value = Constant.wrap val, key
+ @values[key] = RTNode :value
- --- set a symbol to a `Result`.
+ --- set a symbol to a `RTNode`.
--
-- @tparam string key
- -- @tparam Result val
+ -- @tparam RTNode val
set: (key, val) =>
L\trace "setting #{key} = #{val} in #{@}"
- assert val.__class == Result, "expected #{key}=#{val} to be Result"
+ assert val.__class == RTNode, "expected #{key}=#{val} to be RTNode"
assert val.value, Error 'type', "cannot define symbol to nil"
assert not @values[key], Error 'type', "cannot redefine symbol '#{key}'!"
@values[key] = val
@@ -42,7 +43,7 @@ class Scope
--- resolve a key in this Scope.
--
-- @tparam string key the key to resolve
- -- @treturn ?Result the value of the definition that was found, or `nil`
+ -- @treturn ?RTNode the value of the definition that was found, or `nil`
get: (key) =>
L\debug "checking for #{key} in #{@}"
if val = @values[key]
@@ -56,7 +57,7 @@ class Scope
child = @get start
if not child
error Error 'reference', "undefined symbol '#{start}'"
- if child\type! != 'scope'
+ if child\type! != (Primitive 'scope')
error Error 'reference', "'#{start}' is not a scope"
child.value!\get rest, while_msg
@@ -104,7 +105,7 @@ class Scope
--- convert a Lua table to a Scope.
--
-- `tbl` may contain more tables (or `Scope`s).
- -- Uses `ValueStream.wrap` on the values recursively.
+ -- Uses `Constant.wrap` on the values recursively.
--
-- @tparam table tbl the table to convert
-- @treturn Scope
diff --git a/alv/stream/init.moon b/alv/stream/init.moon
deleted file mode 100644
index f9393b0..0000000
--- a/alv/stream/init.moon
+++ /dev/null
@@ -1,18 +0,0 @@
-----
--- `Stream` interface and implementations.
---
--- @see Stream
--- @see ValueStream
--- @see EventStream
--- @see IOStream
---
--- @module stream
-import ValueStream from require 'alv.stream.value'
-import EventStream from require 'alv.stream.event'
-import IOStream from require 'alv.stream.io'
-
-{
- :ValueStream
- :EventStream
- :IOStream
-}
diff --git a/alv/types.moon b/alv/types.moon
new file mode 100644
index 0000000..3fcf722
--- /dev/null
+++ b/alv/types.moon
@@ -0,0 +1,101 @@
+-- what do i need types for?
+--
+-- ## implementation side
+-- argument specs - without values
+-- output specs & output streams
+-- - evt outputs are created without values,
+-- - val outputs are created *with* values!
+--
+-- ## language side
+-- explicit casting
+
+-- Check whether two tables have all the same,
+-- and *only the same* keys.
+shared_shape = (a, b) ->
+ for key in pairs a
+ return false unless b[key]
+
+ for key in pairs b
+ return false unless a[key]
+
+ true
+
+same = (a, b) ->
+ return unless shared_shape a, b
+ for key, val in pairs a
+ return false unless val == b[key]
+
+ true
+
+class Type
+ __eq: (a, b) ->
+ if a.__class == b.__class
+ a.__class.__base.__self_eq a, b
+
+ __inherited: (cls) =>
+ cls.__base.__self_eq = cls.__base.__eq
+ cls.__base.__eq = @__eq
+
+class Primitive extends Type
+ new: (@type) =>
+
+ pp: (value) => tostring value
+
+ __eq: (other) => @type == other.type
+ __tostring: => @type
+
+class Struct extends Type
+ new: (@types) =>
+
+ --- create a new struct with a selection of keys
+ project: (keys) =>
+ types = {}
+ for key in *keys
+ types[key] = @types[key]
+ @@ types
+
+ pp: (value) =>
+ inner = table.concat ["#{k}: #{@types[k]\pp v}" for k, v in pairs value], ', '
+ "{#{inner}}"
+
+ __eq: (other) => same @types, other.types
+ __tostring: =>
+ inner = table.concat ["#{k}: #{v}" for k, v in pairs @types], ', '
+ "{#{inner}}"
+
+class Array extends Type
+ new: (@size, @type) =>
+
+ pp: (value) =>
+ inner = table.concat [@type\pp v for v in *value], ' '
+ "[#{inner}]"
+
+ __eq: (other) => @size == other.size and @type == other.type
+ __tostring: => "#{@type}[#{@size}]"
+
+"
+bool = Primitive 'bool'
+num = Primitive 'num'
+str = Primitive 'str'
+
+vec3 = Array 3, num
+noteevt = Struct { note: str, dur: num }
+
+assert.is.equal 'num[3]', tostring vec3
+assert.is.equal '{dur: num, note: str}', tostring noteevt
+
+assert.is.equal vec3 == Array 3, num
+assert.not.equal vec3, Array 3, str
+assert.is.equal noteevt, Struct { oct: num, note: str, dur: num }
+assert.not.equal noteevt, Struct { oct: num, note: str, dur: str }
+
+print Constant bool, false
+print SigStream vec3, { 0.5, 0.3, 0.7 }
+print EvtStream noteevt
+"
+
+{
+ :Primitive
+ :Array
+ :Struct
+}