diff options
| author | s-ol <s-ol@users.noreply.github.com> | 2020-05-09 14:49:08 +0000 |
|---|---|---|
| committer | s-ol <s+removethis@s-ol.nu> | 2025-03-02 14:23:21 +0000 |
| commit | 61eb86951287667ca0ee305baa5c3cd6ad29ba36 (patch) | |
| tree | 7551d6b9c8af01c049adab0ee027dbad68f28808 /alv | |
| parent | more internal doc fixes (diff) | |
| download | alive-61eb86951287667ca0ee305baa5c3cd6ad29ba36.tar.gz alive-61eb86951287667ca0ee305baa5c3cd6ad29ba36.zip | |
add types.T, fix spec + docs
Diffstat (limited to 'alv')
| -rw-r--r-- | alv/base/init.moon | 8 | ||||
| -rw-r--r-- | alv/base/input.moon | 30 | ||||
| -rw-r--r-- | alv/builtin.moon | 24 | ||||
| -rw-r--r-- | alv/cell.moon | 8 | ||||
| -rw-r--r-- | alv/copilot.moon | 2 | ||||
| -rw-r--r-- | alv/error.moon | 15 | ||||
| -rw-r--r-- | alv/init.moon | 8 | ||||
| -rw-r--r-- | alv/invoke.moon | 31 | ||||
| -rw-r--r-- | alv/module.moon | 2 | ||||
| -rw-r--r-- | alv/result/base.moon | 8 | ||||
| -rw-r--r-- | alv/result/const.moon | 43 | ||||
| -rw-r--r-- | alv/result/evt.moon | 9 | ||||
| -rw-r--r-- | alv/result/sig.moon | 27 | ||||
| -rw-r--r-- | alv/rtnode.moon | 19 | ||||
| -rw-r--r-- | alv/scope.moon | 4 | ||||
| -rw-r--r-- | alv/type.moon | 89 |
16 files changed, 159 insertions, 168 deletions
diff --git a/alv/base/init.moon b/alv/base/init.moon index 62de2ab..90f1dfc 100644 --- a/alv/base/init.moon +++ b/alv/base/init.moon @@ -15,6 +15,10 @@ -- @see SigStream -- @see EvtStream -- @see IOStream +-- @see type.T +-- @see type.Primitive +-- @see type.Array +-- @see type.Struct -- @see RTNode -- @see Error @@ -24,7 +28,7 @@ import FnDef from require 'alv.base.fndef' import Input from require 'alv.base.input' import val, evt from require 'alv.base.match' import Constant, SigStream, EvtStream, IOStream from require 'alv.result' -import Primitive, Array, Struct from require 'alv.type' +import T, Primitive, Array, Struct from require 'alv.type' import RTNode from require 'alv.rtnode' import Error from require 'alv.error' @@ -41,7 +45,7 @@ import Error from require 'alv.error' :Constant, :SigStream, :EvtStream, :IOStream -- Types - :Primitive, :Array, :Struct + :T, :Primitive, :Array, :Struct :RTNode :Error diff --git a/alv/base/input.moon b/alv/base/input.moon index a9f0e32..b73a476 100644 --- a/alv/base/input.moon +++ b/alv/base/input.moon @@ -35,9 +35,9 @@ class Input --- create a new Input. -- -- @classmethod - -- @tparam Result stream - new: (@stream) => - assert @stream, "nil passed to Input: #{value}" + -- @tparam Result result + new: (@result) => + assert @result, "nil passed to Input: #{value}" --- copy state from old instance (optional). -- @@ -53,10 +53,10 @@ 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`:@{SigStream:dirty|dirty}. + -- `result`:@{SigStream:dirty|dirty}. -- -- @treturn bool whether processing is necessary - dirty: => @stream\dirty! + dirty: => @result\dirty! --- leave setup state (optional). -- @@ -67,25 +67,25 @@ class Input --- unwrap to Lua value (optional). -- -- @treturn any the raw Lua value - unwrap: => @stream\unwrap! + unwrap: => @result\unwrap! --- return the type name of this `Input` (optional). - type: => @stream.type + type: => @result.type --- return the metatype name of this `Input` (optional). - metatype: => @stream.metatype + metatype: => @result.metatype --- the current value -- - -- @tfield SigStream stream + -- @tfield SigStream result --- members -- @section members --- alias for `unwrap`. - __call: => @stream\unwrap! + __call: => @result\unwrap! - __tostring: => "#{@@__name}:#{@stream}" + __tostring: => "#{@@__name}:#{@result}" __inherited: (cls) => cls.__base.__call = @__call cls.__base.__tostring = @__tostring @@ -95,7 +95,7 @@ class Input --- Create a `cold` `Input`. -- - -- Never marked dirty. Use this for input streams that are only read when + -- Never marked dirty. Use this for input results that are only read when -- another `Input` is dirty. -- -- @tparam Result|RTNode value @@ -128,17 +128,17 @@ class ColdInput extends Input dirty: => false class ValueInput extends Input - setup: (old) => @dirty_setup = not old or @stream != old.stream + setup: (old) => @dirty_setup = not old or @result != old.result finish_setup: => @dirty_setup = nil dirty: => return @dirty_setup if @dirty_setup != nil - @stream\dirty! + @result\dirty! class IOInput extends Input io: true mapping = { - [Constant]: ColdInput + [Constant]: ValueInput [SigStream]: ValueInput [EvtStream]: Input [IOStream]: IOInput diff --git a/alv/builtin.moon b/alv/builtin.moon index 29602e2..45ee626 100644 --- a/alv/builtin.moon +++ b/alv/builtin.moon @@ -5,7 +5,7 @@ -- documentation. -- -- @module builtin -import Builtin, Op, Primitive, FnDef, Input, val, evt from require 'alv.base' +import Builtin, Op, T, FnDef, Input, val, evt from require 'alv.base' import Constant from require 'alv.result' import Error from require 'alv.error' import RTNode from require 'alv.rtnode' @@ -58,7 +58,7 @@ Define the symbols `sym1`, `sym2`, … to resolve to the values of `val-expr1`, children = L\push -> return for i=1,#tail,2 name, val_expr = tail[i], tail[i+1] - name = name\unwrap 'sym' + name = name\unwrap T.sym with val_expr\eval scope scope\set name, \make_ref! @@ -117,7 +117,7 @@ current scope." assert #tail > 0, "'import' requires at least one arguments" children = for i, child in ipairs tail - name = child\unwrap 'sym' + name = child\unwrap T.sym with COPILOT\require name scope\set name, \make_ref! RTNode :children @@ -136,8 +136,8 @@ Requires modules `sym1`, `sym2`, … and merges them into the current scope." assert #tail > 0, "'import' requires at least one arguments" children = for i, child in ipairs tail - with COPILOT\require child\unwrap 'sym' - scope\use .value\unwrap 'scope' + with COPILOT\require child\unwrap T.sym + scope\use .result\unwrap T.scope RTNode :children export_ = Constant.meta @@ -175,7 +175,7 @@ Copies the containing scope if no symbols are given." node else for child in *tail - name = child\unwrap 'sym' + name = child\unwrap T.sym with node = scope\get name new_scope\set name, node @@ -198,7 +198,7 @@ function is invoked." assert params.__class == Cell, "'fn's first argument has to be an expression" param_symbols = for param in *params.children - assert param.type == 'sym', "function parameter declaration has to be a symbol" + assert param.type == T.sym, "function parameter declaration has to be a symbol" param RTNode result: with Constant.wrap FnDef param_symbols, body, scope @@ -223,10 +223,10 @@ function is invoked." assert #tail == 3, "'defn' takes exactly three arguments" { name, params, body } = tail - name = name\unwrap 'sym' + name = name\unwrap T.sym assert params.__class == Cell, "'defn's second argument has to be an expression" param_symbols = for param in *params.children - assert param.type == 'sym', "function parameter declaration has to be a symbol" + assert param.type == T.sym, "function parameter declaration has to be a symbol" param result = with Constant.wrap FnDef param_symbols, body, scope @@ -305,7 +305,7 @@ trace = Constant.meta value: Input.hot inputs[2] tick: => - L\print "trace #{@inputs.prefix!}: #{@inputs.value.stream}" + L\print "trace #{@inputs.prefix!}: #{@inputs.value\type!\pp @inputs.value!}" eval: (scope, tail) => L\trace "evaling #{@}" @@ -313,7 +313,7 @@ trace = Constant.meta tag = @tag\clone Tag.parse '-1' inner = Cell tag, { - Constant.literal Primitive.op, traceOp, 'trace' + Constant.literal T.opdef, traceOp, 'trace' Constant.str tostring tail[1] tail[1] } @@ -364,7 +364,7 @@ Scope.from_table { meta: name: 'bang' summary: "A `bang` value-constant." - value: Constant 'bang', true + value: Constant T.bang, true :fn, :defn 'do': do_expr diff --git a/alv/cell.moon b/alv/cell.moon index 759e7aa..36d5f43 100644 --- a/alv/cell.moon +++ b/alv/cell.moon @@ -5,7 +5,7 @@ -- nodes), a `Tag`, and optionally the internal whitespace as parsed. -- -- @classmod Cell -import Primitive from require 'alv.type' +import T from require 'alv.type' import Constant from require 'alv.result' import Error from require 'alv.error' import op_invoke, fn_invoke from require 'alv.invoke' @@ -74,11 +74,11 @@ class Cell head = assert @head!, Error 'syntax', "cannot evaluate empty expr" head = (head\eval scope)\const! Builtin = switch head.type - when Primitive.op + when T.opdef op_invoke - when Primitive.fn + when T.fndef fn_invoke - when Primitive.builtin + when T.builtin head\unwrap! else error Error 'type', "#{head} is not an opdef, fndef or builtin" diff --git a/alv/copilot.moon b/alv/copilot.moon index 55e00c8..e6eb293 100644 --- a/alv/copilot.moon +++ b/alv/copilot.moon @@ -53,7 +53,7 @@ class Copilot mod.root\make_ref! else last = @active_module - prefix = @active_module.file\match('(.*)/[^/]*$') .. '/' or '' + prefix = if b = last.file\match'(.*)/[^/]*$' then b .. '/' else '' mod = @last_modules[name] or Module "#{prefix}#{name}.alv" L\trace "entering module #{mod}" @modules[name] = mod diff --git a/alv/error.moon b/alv/error.moon index e72cc5f..c049f8f 100644 --- a/alv/error.moon +++ b/alv/error.moon @@ -48,7 +48,9 @@ class Error if err.__class == Error err else - Error 'implementation', err, debug.traceback "Lua error below:", 2 + trace = debug.traceback "Lua error below:", 2 + Error 'implementation', err, trace + --- Wrap function errors in a traceback frame. -- -- Execute `fn(...)`, and turn any error thrown as a result into an @@ -65,8 +67,8 @@ class Error if ok unpack results else - error with results[1] - \add_frame frame + results[1]\add_frame frame if frame + error results[1] --- Capture and wrap function errors in traceback frame. -- @@ -76,7 +78,7 @@ class Error -- When `Error` instances are caught, `frame` is added to the traceback. -- All other error values are turned into `'implementation'` Errors. -- - -- @tparam string frame + -- @tparam ?string frame -- @tparam function fn -- @treturn boolean `ok` true if exeuction suceeded without errors -- @treturn Error|any `error_or_results` the `Error` instance or results @@ -86,9 +88,8 @@ class Error if ok ok, unpack results else - ok, with results[1] - \add_frame frame - + results[1]\add_frame frame if frame + ok, unpack results { :Error } diff --git a/alv/init.moon b/alv/init.moon index ec90a10..fc85f8b 100644 --- a/alv/init.moon +++ b/alv/init.moon @@ -14,7 +14,7 @@ cycle = require 'alv.cycle' version = require 'alv.version' import Logger from require 'alv.logger' -import Primitive, Struct, Array from require 'alv.type' +import T, Primitive, Struct, Array from require 'alv.type' import Constant, SigStream, EvtStream, IOStream from require 'alv.result' import RTNode from require 'alv.rtnode' import Scope from require 'alv.scope' @@ -40,6 +40,10 @@ import Copilot from require 'alv.copilot' -- @tfield SigStream SigStream -- @tfield EvtStream EvtStream -- @tfield IOStream IOStream +-- @tfield type.T T +-- @tfield type.Primitive Primitive +-- @tfield type.Array Array +-- @tfield type.Struct Struct -- @tfield RTNode RTNode -- @tfield Cell Cell -- @tfield RootCell RootCell @@ -58,7 +62,7 @@ import Copilot from require 'alv.copilot' :Cell, :RootCell :RTNode, :Scope, :Error - :Primitive, :Struct, :Array + :T, :Primitive, :Struct, :Array :Registry, :SimpleRegistry, :Tag diff --git a/alv/invoke.moon b/alv/invoke.moon index 390e19f..9acb77c 100644 --- a/alv/invoke.moon +++ b/alv/invoke.moon @@ -5,7 +5,7 @@ import RTNode from require 'alv.rtnode' import Builtin from require 'alv.base' import Scope from require 'alv.scope' -import Primitive from require 'alv.type' +import T from require 'alv.type' import Error from require 'alv.error' get_name = (value, raw) -> @@ -35,14 +35,14 @@ class op_invoke extends Builtin @op = prev.op\fork! prev.forked = COPILOT.T else - def = @head\unwrap Primitive.opdef, "cant op-invoke #{@head}" + def = @head\unwrap T.opdef, "cant op-invoke #{@head}" @op = def! --- `Builtin:destroy` implementation. -- -- calls `op`:@{Op:destroy|destroy}. destroy: => - if @forked ~= COPILOT.T + if @op and @forked ~= COPILOT.T @op\destroy! --- perform an `Op` invocation. @@ -60,19 +60,20 @@ class op_invoke extends Builtin children = [L\push expr\eval, scope for expr in *tail] frame = "invoking op #{get_name @head, @cell\head!} at [#{@tag}]" - Error.wrap frame, @op\setup, [node for node in *children], scope + Error.wrap frame, -> + @op\setup [node for node in *children], scope - any_dirty = false - for input in @op\all_inputs! - if input\dirty! - any_dirty = true - break + any_dirty = false + for input in @op\all_inputs! + if input\dirty! + any_dirty = true + break - if any_dirty - @op\tick true + if any_dirty + @op\tick true - for input in @op\all_inputs! - input\finish_setup! + for input in @op\all_inputs! + input\finish_setup! RTNode :children, result: @op.out, op: @op @@ -104,7 +105,7 @@ class fn_invoke extends Builtin name = get_name @head, @cell\head! frame = "invoking function #{name} at [#{@tag}]" - fndef = @head\unwrap Primitive.fndef, "cant fn-invoke #{@head}" + fndef = @head\unwrap T.fndef, "cant fn-invoke #{@head}" { :params, :body } = fndef if #params != #tail err = Error 'argument', "expected #{#params} arguments, found #{#tail}" @@ -114,7 +115,7 @@ class fn_invoke extends Builtin fn_scope = Scope fndef.scope, caller_scope children = for i=1,#params - name = params[i]\unwrap Primitive.sym + name = params[i]\unwrap T.sym with L\push tail[i]\eval, caller_scope fn_scope\set name, \make_ref! diff --git a/alv/module.moon b/alv/module.moon index 7179ab6..0e95593 100644 --- a/alv/module.moon +++ b/alv/module.moon @@ -34,7 +34,7 @@ class Module -- @treturn bool whether the file was changed since the last call poll: => { :mode, :modification } = (lfs.attributes @file) or {} - assert mode == 'file', Error 'io', "not a file: '#{file}'" + assert mode == 'file', Error 'io', "not a file: '#{@file}'" modification --- start an evaluation cycle. diff --git a/alv/result/base.moon b/alv/result/base.moon index 6accb1e..7775349 100644 --- a/alv/result/base.moon +++ b/alv/result/base.moon @@ -24,7 +24,11 @@ class Result -- @function fork -- @treturn Result - __tostring: => "<#{@type}#{@metatype} #{@type\pp @value}>" + __tostring: => + if @value then + "<#{@type}#{@metatype} #{@type\pp @value}>" + else + "<#{@type}#{@metatype}>" __inherited: (cls) => cls.__base.__tostring or= @__tostring --- the type of this Result's value. @@ -56,12 +60,14 @@ class Result --- static functions -- @section static + _type = type --- construct a new Result. -- -- @classmethod -- @tparam type.Type type the type -- @tparam ?table meta the `meta` table new: (@type, @meta={}) => + assert @type and (_type @type) == 'table', "not a type: #{@type}" { :Result diff --git a/alv/result/const.moon b/alv/result/const.moon index b88de2c..077a2d8 100644 --- a/alv/result/const.moon +++ b/alv/result/const.moon @@ -5,16 +5,11 @@ -- -- @classmod Constant import Result from require 'alv.result.base' -import Primitive from require 'alv.type' +import T from require 'alv.type' import RTNode from require 'alv.rtnode' import Error from require 'alv.error' import scope, base from require 'alv.cycle' -num = Primitive 'num' -str = Primitive 'str' -sym = Primitive 'sym' -bool = Primitive 'bool' - ancestor = (klass) -> assert klass, "cant find the ancestor of nil" while klass.__parent @@ -78,9 +73,9 @@ class Constant extends Result return RTNode result: @ if @literal switch @type - when num, str + when T.num, T.str RTNode result: @ - when sym + when T.sym Error.wrap "resolving symbol '#{@value}'", scope\get, @value else error "cannot evaluate #{@}" @@ -106,7 +101,9 @@ class Constant extends Result -- @tparam string type the type name -- @tparam any value the Lua value to be accessed through `unwrap` -- @tparam string raw the raw string that resulted in this value. Used by `parsing`. - new: (type, @value, @raw) => super type + new: (type, @value, @raw) => + super type + assert @value ~= nil, "Constant without value" unescape = (str) -> str\gsub '\\([\'"\\])', '%1' --- create a capture-function (for parsing with Lpeg). @@ -115,9 +112,9 @@ class Constant extends Result -- @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) -> @ T.num, (tonumber match), match + when 'sym' then (match) -> @ T.sym, match, match + when 'str' then (match) -> @ T.str, (unescape match), sep .. match .. sep --- wrap a Lua value. -- @@ -128,28 +125,28 @@ class Constant extends Result -- @treturn Constant @wrap: (val, name='(unknown)') -> typ = switch type val - when 'number' then Primitive.num - when 'string' then Primitive.str + when 'number' then T.num + when 'string' then T.str when 'table' if rawget val, '__base' -- a class switch ancestor val - when base.Op then Primitive.op - when base.Builtin then Primitive.builtin + when base.Op then T.opdef + when base.Builtin then T.builtin else error "#{name}: cannot wrap class '#{val.__name}'" elseif val.__class -- an instance switch ancestor val.__class - when scope.Scope then Primitive.scope - when base.FnDef then Primitive.fn + when scope.Scope then T.scope + when base.FnDef then T.fndef when Result then return val else error "#{name}: cannot wrap '#{val.__class.__name}' instance" else -- plain table val = scope.Scope.from_table val - Primitive.scope + T.scope else error "#{name}: cannot wrap Lua type '#{type val}'" @@ -158,22 +155,22 @@ class Constant extends Result --- create a constant number. -- @tparam number num the number -- @treturn Constant - @num: (num) -> Constant Primitive.num, num, tostring num + @num: (num) -> Constant T.num, num, tostring num --- create a constant string. -- @tparam string str the string -- @treturn Constant - @str: (str) -> Constant Primitive.str, str, "'#{str}'" + @str: (str) -> Constant T.str, str, "'#{str}'" --- create a constant symbol. -- @tparam string sym the symbol -- @treturn Constant - @sym: (sym) -> Constant Primitive.sym, sym, sym + @sym: (sym) -> Constant T.sym, sym, sym --- create a constant boolean. -- @tparam boolean bool the boolean -- @treturn Constant - @bool: (bool) -> Constant Primitive.bool, bool, tostring bool + @bool: (bool) -> Constant T.bool, bool, tostring bool --- create a forced-literal Constant. -- diff --git a/alv/result/evt.moon b/alv/result/evt.moon index bab502c..7e6a249 100644 --- a/alv/result/evt.moon +++ b/alv/result/evt.moon @@ -35,7 +35,10 @@ class EvtStream extends Result --- alias for `unwrap`. __call: (...) => @unwrap ... - __tostring: => "<#{@type}#{@metatype} #{@type\pp @value}>" + + __tostring: => + events = table.concat [@type\pp e for e in *@events], ' ' + "<#{@type}#{@metatype} #{events}>" --- the type of this Result's value. -- @tfield type.Type type @@ -79,7 +82,9 @@ class EvtStream extends Result -- -- @classmethod -- @tparam type.Type type the type - new: (type) => super type + new: (type) => + super type + @events = {} { :EvtStream diff --git a/alv/result/sig.moon b/alv/result/sig.moon index 73f06d1..b23afbe 100644 --- a/alv/result/sig.moon +++ b/alv/result/sig.moon @@ -3,7 +3,6 @@ -- -- @classmod SigStream import Result from require 'alv.result.base' -import Primitive from require 'alv.type' class SigStream extends Result --- Result interface @@ -79,33 +78,13 @@ class SigStream extends Result --- static functions -- @section static - --- construct a new SigStream. + --- construct a new Constant. -- -- @classmethod - -- @tparam type.Type type the type - -- @tparam any value the Lua value to be accessed through `unwrap` + -- @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/rtnode.moon b/alv/rtnode.moon index a8ebec3..61222ef 100644 --- a/alv/rtnode.moon +++ b/alv/rtnode.moon @@ -5,6 +5,9 @@ -- between `Op`s. -- -- @classmod RTNode + +import Error from require 'alv.error' + class RTNode --- members -- @section members @@ -41,15 +44,15 @@ class RTNode --- poll all IOStream instances that are effecting this (sub)tree. -- should be called once per frame on the root, right before tick. poll_io: => - for stream, input in pairs @side_inputs - stream\poll! if input.io + for result, input in pairs @side_inputs + result\poll! if input.io --- in depth-first order, tick all Ops which have dirty Inputs. -- -- short-circuits if there are no dirty Inputs in the entire subtree tick: => any_dirty = false - for stream, input in pairs @side_inputs + for result, input in pairs @side_inputs if input\dirty! any_dirty = true break @@ -70,7 +73,7 @@ class RTNode return unless self_dirty - @op\tick! + Error.wrap "ticking #{op}", @op\tick __tostring: => buf = "<RT=#{@result}" @@ -111,15 +114,15 @@ class RTNode @side_inputs, is_child = {}, {} for child in *@children - for stream, input in pairs child.side_inputs - @side_inputs[stream] = input + for result, input in pairs child.side_inputs + @side_inputs[result] = input if child.result is_child[child.result] = true if @op for input in @op\all_inputs! - if input.io or not is_child[input.stream] - @side_inputs[input.stream] = input + if input.io or not is_child[input.result] + @side_inputs[input.result] = input if @result and @result.metatype == '=' assert not (next @side_inputs), "Const result has side_inputs" diff --git a/alv/scope.moon b/alv/scope.moon index b150280..4adf07d 100644 --- a/alv/scope.moon +++ b/alv/scope.moon @@ -5,7 +5,7 @@ import Constant from require 'alv.result' import RTNode from require 'alv.rtnode' import Error from require 'alv.error' -import Primitive from require 'alv.type' +import T from require 'alv.type' class Scope --- members @@ -57,7 +57,7 @@ class Scope child = @get start if not child error Error 'reference', "undefined symbol '#{start}'" - if child\type! != Primitive.scope + if child\type! != T.scope error Error 'reference', "'#{start}' is not a scope" child.result!\get rest, while_msg diff --git a/alv/type.moon b/alv/type.moon index 8a3708b..5c76b86 100644 --- a/alv/type.moon +++ b/alv/type.moon @@ -3,6 +3,7 @@ -- -- @module type import opairs from require 'alv.util' +import result from require 'alv.cycle' shared_shape = (a, b) -> for key in pairs a @@ -20,74 +21,54 @@ same = (a, b) -> true ---- Interface for types. +--- Base class for types. -- @type Type class Type - new: => - --- pretty-print a value of this type. -- @function pp -- @tparam any value -- @treturn string + --- create a `SigStream` of this type. + -- @tparam ?any init initial value + -- @treturn SigStream + mk_sig: (init) => + result.SigStream @, init + + --- create a `EvtStream` of this type. + -- @treturn EvtStream + mk_evt: => + result.EvtStream @ + + --- create a `Constant` of this type. + -- @tparam any val value + -- @treturn Constant + mk_const: (val) => + result.Constant @, val + --- Primitive type. -- --- Implements the `Type` interface. +-- Extends `Type`. -- -- @type Primitive -class Primitive +class Primitive extends Type pp: (value) => tostring value - __eq: (other) => @type == other.type - __tostring: => @type - - --- shorthand for number type. - -- @tfield Primitive num - @num: @ 'num' - - --- shorthand for string type. - -- @tfield Primitive str - @str: @ 'str' - - --- shorthand for symbol type. - -- @tfield Primitive sym - @sym: @ 'sym' - - --- shorthand for boolean type. - -- @tfield Primitive bool - @bool: @ 'bool' - - --- shorthand for bang type. - -- @tfield Primitive bang - @bang: @ 'bang' - - --- shorthand for `Scope` type. - -- @tfield Primitive scope - @scope: @ 'scope' - - --- shorthand for `Op` type. - -- @tfield Primitive op - @op: @ 'opdef' - - --- shorthand for `FnDef` type. - -- @tfield Primitive fn - @fn: @ 'fndef' - - --- shorthand for `Builtin` type. - -- @tfield Primitive builtin - @builtin: @ 'builtin' + __eq: (other) => @name == other.name + __tostring: => @name --- instantiate a Primitive type. -- @classmethod - -- @tparam string type the typename - new: (@type) => + -- @tparam string name the typename + new: (@name) => + assert (type @name) == 'string', "Typename has to be a string: '#{@name}'" --- Struct/Hashmap type. -- --- Implements the `Type` interface. +-- Extends `Type`. -- -- @type Struct -class Struct +class Struct extends Type pp: (value) => inner = table.concat ["#{k}: #{@types[k]\pp v}" for k, v in opairs value], ', ' "{#{inner}}" @@ -111,10 +92,10 @@ class Struct --- Array type. -- --- Implements the `Type` interface. +-- Extends `Type`. -- -- @type Array -class Array +class Array extends Type pp: (value) => inner = table.concat [@type\pp v for v in *value], ' ' "[#{inner}]" @@ -128,7 +109,17 @@ class Array -- @tparam Type type new: (@size, @type) => +--- Magic table containing all `Primitive` types. +-- +-- When indexed with a string returns a (cached) instance of that type. +-- +-- @table T +T = setmetatable {}, __index: (key) => + with type = Primitive key + rawset @, key, type + { + :T :Primitive :Array :Struct |
