From 6afecae50e4faafafbde8dae6bf8f534b8b7f1da Mon Sep 17 00:00:00 2001 From: s-ol Date: Fri, 8 May 2020 12:23:03 +0200 Subject: add alv.type and spec --- alv/base/init.moon | 10 ++++- alv/base/match.moon | 2 +- alv/builtin.moon | 3 +- alv/cell.moon | 2 +- alv/init.moon | 3 ++ alv/invoke.moon | 2 +- alv/result/const.moon | 4 +- alv/result/sig.moon | 2 +- alv/scope.moon | 2 +- alv/type.moon | 64 ++++++++++++++++++++++++++++ alv/types.moon | 101 -------------------------------------------- alv/util.moon | 29 +++++++++++++ spec/input_spec.moon | 7 +-- spec/match_spec.moon | 3 +- spec/result/const_spec.moon | 3 +- spec/result/sig_spec.moon | 3 +- spec/rtnode_spec.moon | 3 +- spec/scope_spec.moon | 3 +- spec/type_spec.moon | 45 ++++++++++++++++++++ 19 files changed, 167 insertions(+), 124 deletions(-) create mode 100644 alv/type.moon delete mode 100644 alv/types.moon create mode 100644 alv/util.moon create mode 100644 spec/type_spec.moon diff --git a/alv/base/init.moon b/alv/base/init.moon index 71e9cea..62de2ab 100644 --- a/alv/base/init.moon +++ b/alv/base/init.moon @@ -24,6 +24,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 RTNode from require 'alv.rtnode' import Error from require 'alv.error' @@ -35,6 +36,13 @@ import Error from require 'alv.error' :val, :evt -- redundant exports, to keep anything an extension might need in one import + + -- Results :Constant, :SigStream, :EvtStream, :IOStream - :RTNode, :Error + + -- Types + :Primitive, :Array, :Struct + + :RTNode + :Error } diff --git a/alv/base/match.moon b/alv/base/match.moon index 819b0b4..3a2b3d5 100644 --- a/alv/base/match.moon +++ b/alv/base/match.moon @@ -45,7 +45,7 @@ -- -- @module base.match import Error from require 'alv.error' -import Primitive from require 'alv.types' +import Primitive from require 'alv.type' local Repeat, Sequence, Choice, Optional diff --git a/alv/builtin.moon b/alv/builtin.moon index 767d8e1..58a1ecc 100644 --- a/alv/builtin.moon +++ b/alv/builtin.moon @@ -5,7 +5,7 @@ -- documentation. -- -- @module builtin -import Builtin, Op, FnDef, Input, val, evt from require 'alv.base' +import Builtin, Op, Primitive, 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' @@ -13,7 +13,6 @@ 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 = Constant.meta diff --git a/alv/cell.moon b/alv/cell.moon index 2e00195..933d292 100644 --- a/alv/cell.moon +++ b/alv/cell.moon @@ -5,10 +5,10 @@ -- nodes), a `Tag`, and optionally the internal whitespace as parsed. -- -- @classmod Cell +import Primitive 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' -import Primitive from require 'alv.types' import Tag from require 'alv.tag' local RootCell diff --git a/alv/init.moon b/alv/init.moon index 95432f3..ec90a10 100644 --- a/alv/init.moon +++ b/alv/init.moon @@ -14,6 +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 Constant, SigStream, EvtStream, IOStream from require 'alv.result' import RTNode from require 'alv.rtnode' import Scope from require 'alv.scope' @@ -57,6 +58,8 @@ import Copilot from require 'alv.copilot' :Cell, :RootCell :RTNode, :Scope, :Error + :Primitive, :Struct, :Array + :Registry, :SimpleRegistry, :Tag :globals diff --git a/alv/invoke.moon b/alv/invoke.moon index 4d9dfc9..03cf08e 100644 --- a/alv/invoke.moon +++ b/alv/invoke.moon @@ -5,8 +5,8 @@ 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 Error from require 'alv.error' -import Primitive from require 'alv.types' opdef = Primitive 'opdef' fndef = Primitive 'fndef' diff --git a/alv/result/const.moon b/alv/result/const.moon index 10bc943..b9a7cf4 100644 --- a/alv/result/const.moon +++ b/alv/result/const.moon @@ -5,10 +5,10 @@ -- -- @classmod Constant import Stream from require 'alv.result.base' +import Primitive from require 'alv.type' 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' @@ -24,7 +24,7 @@ ancestor = (klass) -> class Constant extends Stream --- Whether this Result is dirty. -- - -- @tresult bool always `false`. + -- @treturn bool always `false`. dirty: => false --- unwrap to the Lua type. diff --git a/alv/result/sig.moon b/alv/result/sig.moon index d7c18a3..6bcba65 100644 --- a/alv/result/sig.moon +++ b/alv/result/sig.moon @@ -3,7 +3,7 @@ -- -- @classmod SigStream import Stream from require 'alv.result.base' -import Primitive from require 'alv.types' +import Primitive from require 'alv.type' class SigStream extends Stream --- members diff --git a/alv/scope.moon b/alv/scope.moon index 575c36e..c2c91e1 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.types' +import Primitive from require 'alv.type' class Scope --- members diff --git a/alv/type.moon b/alv/type.moon new file mode 100644 index 0000000..629ac50 --- /dev/null +++ b/alv/type.moon @@ -0,0 +1,64 @@ +----- +--- Type definition classes +-- +-- @module type +import opairs from require 'alv.util' + +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 Primitive + new: (@type) => + + pp: (value) => tostring value + + __eq: (other) => @type == other.type + __tostring: => @type + +class Struct + 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 opairs value], ', ' + "{#{inner}}" + + __eq: (other) => same @types, other.types + __tostring: => + inner = table.concat ["#{k}: #{v}" for k, v in opairs @types], ', ' + "{#{inner}}" + +class Array + 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}]" + +{ + :Primitive + :Array + :Struct +} diff --git a/alv/types.moon b/alv/types.moon deleted file mode 100644 index 3fcf722..0000000 --- a/alv/types.moon +++ /dev/null @@ -1,101 +0,0 @@ --- 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 -} diff --git a/alv/util.moon b/alv/util.moon new file mode 100644 index 0000000..a93fe3f --- /dev/null +++ b/alv/util.moon @@ -0,0 +1,29 @@ +----- +--- General utilities +-- +-- @module util + +sort = (t, order_fn, only_strings) -> + with index = [k for k,v in pairs t when (not only_strings) or 'string' == type k] + table.sort index, order_fn + +-- ordered next(t) +onext = (state, key) -> + state.i += 1 + { :t, :index, :i } = state + + if key = index[i] + key, t[key] + +--- ordered pairs(t). +-- +-- @tparam table t table to iterate +-- @tparam function order_fn fn for `table.sort` +-- @tparam ?boolean only_strings whether to exclude non-strings from iteration +opairs = (t, order_fn, only_strings=false) -> + state = { :t, i: 0, index: sort t, order_fn, only_strings } + onext, state, nil + +{ + :opairs +} diff --git a/spec/input_spec.moon b/spec/input_spec.moon index a8107ae..371a3ee 100644 --- a/spec/input_spec.moon +++ b/spec/input_spec.moon @@ -1,8 +1,9 @@ -import do_setup from require 'spec.test_setup' -import Input, Result, SigStream, EvtStream, IOStream from require 'alv.base' -import Primitive from require 'alv.types' +import do_setup, do_teardown from require 'spec.test_setup' +import Input, Primitive, Result, SigStream, EvtStream, IOStream + from require 'alv.base' setup do_setup +teardown do_teardown my_io = Primitive 'my-io' diff --git a/spec/match_spec.moon b/spec/match_spec.moon index 91cee02..e3483e3 100644 --- a/spec/match_spec.moon +++ b/spec/match_spec.moon @@ -1,6 +1,5 @@ import val, evt from require 'alv.base.match' -import RTNode, SigStream, EvtStream from require 'alv' -import Primitive from require 'alv.types' +import RTNode, Primitive, SigStream, EvtStream from require 'alv' mk_val = (type, const) -> value = SigStream Primitive type diff --git a/spec/result/const_spec.moon b/spec/result/const_spec.moon index 6bd7999..55d5175 100644 --- a/spec/result/const_spec.moon +++ b/spec/result/const_spec.moon @@ -1,7 +1,6 @@ import do_setup from require 'spec.test_setup' -import Constant, RTNode, Scope, SimpleRegistry from require 'alv' +import Constant, RTNode, Scope, SimpleRegistry, Primitive from require 'alv' import Op, Builtin from require 'alv.base' -import Primitive from require 'alv.types' class TestOp extends Op new: (...) => super ... diff --git a/spec/result/sig_spec.moon b/spec/result/sig_spec.moon index 4bc0a67..93a9eb4 100644 --- a/spec/result/sig_spec.moon +++ b/spec/result/sig_spec.moon @@ -1,7 +1,6 @@ import do_setup from require 'spec.test_setup' -import SigStream, RTNode, Scope, SimpleRegistry from require 'alv' +import SigStream, RTNode, Scope, SimpleRegistry, Primitive from require 'alv' import Op, Builtin from require 'alv.base' -import Primitive from require 'alv.types' class TestOp extends Op new: (...) => super ... diff --git a/spec/rtnode_spec.moon b/spec/rtnode_spec.moon index c4cf4e9..a842a74 100644 --- a/spec/rtnode_spec.moon +++ b/spec/rtnode_spec.moon @@ -1,7 +1,6 @@ import do_setup from require 'spec.test_setup' import RTNode, Scope, SimpleRegistry from require 'alv' -import Input, Op, Constant, EvtStream, IOStream from require 'alv.base' -import Primitive from require 'alv.types' +import Primitive, Input, Op, Constant, EvtStream, IOStream from require 'alv.base' setup do_setup num = Primitive 'num' diff --git a/spec/scope_spec.moon b/spec/scope_spec.moon index 405e9f8..4798391 100644 --- a/spec/scope_spec.moon +++ b/spec/scope_spec.moon @@ -1,5 +1,4 @@ -import Scope, Constant, RTNode from require 'alv' -import Primitive from require 'alv.types' +import Scope, Primitive, Constant, RTNode from require 'alv' import Op from require 'alv.base' import Logger from require 'alv.logger' Logger\init 'silent' diff --git a/spec/type_spec.moon b/spec/type_spec.moon new file mode 100644 index 0000000..14d7894 --- /dev/null +++ b/spec/type_spec.moon @@ -0,0 +1,45 @@ +require 'spec.test_setup' +import Primitive, Array, Struct from require 'alv' + +bool = Primitive 'bool' +num = Primitive 'num' +str = Primitive 'str' + +describe 'Primitive', -> + it 'stringifies well', -> + assert.is.equal 'bool', tostring bool + assert.is.equal 'num', tostring num + assert.is.equal 'str', tostring str + + it 'implements __eq sensibly', -> + assert.is.equal (Primitive 'bool'), bool + assert.is.equal (Primitive 'num'), num + assert.is.equal (Primitive 'str'), str + assert.not.equal num, bool + assert.not.equal str, num + +describe 'Array', -> + vec3 = Array 3, num + + it 'stringifies well', -> + assert.is.equal 'num[3]', tostring vec3 + assert.is.equal 'my-type[3][24]', tostring Array 24, Array 3, 'my-type' + + it 'implements __eq sensibly', -> + assert.is.equal vec3, Array 3, num + assert.not.equal vec3, Array 2, num + assert.not.equal vec3, Array 3, str + +describe 'Struct', -> + play = Struct { note: str, dur: num } + abc = Struct { c: num, b: num, a: num } + + it 'stringifies well', -> + assert.is.equal '{dur: num, note: str}', tostring play + assert.is.equal '{a: num, b: num, c: num}', tostring abc + + it 'implements __eq sensibly', -> + assert.is.equal play, Struct { note: str, dur: num } + assert.not.equal play, Struct { note: str } + assert.not.equal play, Struct { note: str, dur: str } + assert.not.equal play, Struct { note: str, dur: num, extra: num } -- cgit v1.2.3