aboutsummaryrefslogtreecommitdiffstats
path: root/spec/rtnode_spec.moon
diff options
context:
space:
mode:
authors-ol <s-ol@users.noreply.github.com>2020-05-08 09:41:08 +0000
committers-ol <s+removethis@s-ol.nu>2025-03-02 14:23:21 +0000
commit99ca67938c0145db37182bdb709d9424a20dfee0 (patch)
tree6df4e2b5fde650aa3c7e36893eb1780f932d56bd /spec/rtnode_spec.moon
parentrelease v0.1 (diff)
downloadalive-99ca67938c0145db37182bdb709d9424a20dfee0.tar.gz
alive-99ca67938c0145db37182bdb709d9424a20dfee0.zip
wip new type system and refactoring
- Result -> RTNode - Stream -> Result - ValueStream -> SigStream - EventStream -> EvtStream
Diffstat (limited to 'spec/rtnode_spec.moon')
-rw-r--r--spec/rtnode_spec.moon184
1 files changed, 184 insertions, 0 deletions
diff --git a/spec/rtnode_spec.moon b/spec/rtnode_spec.moon
new file mode 100644
index 0000000..c4cf4e9
--- /dev/null
+++ b/spec/rtnode_spec.moon
@@ -0,0 +1,184 @@
+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'
+
+setup do_setup
+num = Primitive 'num'
+bang = Primitive 'bang'
+
+op_with_inputs = (inputs) ->
+ with Op!
+ \setup inputs if inputs
+
+result_with_sideinput = (value, input) ->
+ with RTNode :value
+ .side_inputs = { [value]: input }
+
+class DirtyIO extends IOStream
+ new: => super Primitive 'dirty-io'
+ dirty: => true
+
+describe 'RTNode', ->
+ it 'wraps value, children', ->
+ value = Constant.num 3
+
+ a = RTNode!
+ b = RTNode!
+ children = { a, b }
+
+ result = RTNode :value, :children
+
+ assert.is.equal value, result.value
+ assert.is.same children, result.children
+
+ it ':type gets type and assets value', ->
+ result = RTNode value: Constant.num 2
+ assert.is.equal num, result\type!
+
+ result = RTNode!
+ assert.has.error -> result\type!
+
+ it ':is_const', ->
+ value = Constant.num 2
+ pure = RTNode :value
+ impure = result_with_sideinput value, {}
+
+ assert.is.true pure\is_const!
+ assert.is.false impure\is_const!
+
+ assert.is.equal value, pure\const!
+ assert.has.error -> impure\const!
+ assert.has.error (-> impure\const 'test'), 'test'
+
+ it ':make_ref', ->
+ value = Constant.num 2
+ input = Input.hot value
+ op = op_with_inputs { input }
+ thick = RTNode :value, :op, children: { RTNode!, RTNode! }
+ ref = thick\make_ref!
+
+ assert ref
+ assert.is.equal thick.value, ref.value
+ assert.is.same thick.side_inputs, ref.side_inputs
+ assert.is.same {}, ref.children
+ assert.is.nil ref.op
+
+ it 'lifts up inputs from op', ->
+ event = Constant bang, false
+ event_input = Input.hot event
+
+ value = Constant num, 4
+ value_input = Input.hot value
+
+ op = op_with_inputs { event_input, value_input }
+ result = RTNode op: op, :value
+
+ assert.is.equal op, result.op
+ assert.is.same { [event]: event_input, [value]: value_input },
+ result.side_inputs
+
+ it 'does not lift up op inputs that are also child values', ->
+ event = Constant bang, false
+ event_input = Input.hot event
+
+ value = Constant num, 4
+ value_input = Input.hot value
+
+ op = op_with_inputs { event_input, value_input }
+ result = RTNode op: op, :value, children: { RTNode :value }
+
+ assert.is.same { [event]: event_input }, result.side_inputs
+
+ it 'lifts up side_inputs from children', ->
+ event_value = Constant bang, false
+ event_input = Input.hot event_value
+ event = RTNode op: op_with_inputs { event_input }
+ assert.is.same { [event_value]: event_input }, event.side_inputs
+
+ value_value = Constant num, 4
+ value_input = Input.hot value_value
+ value = RTNode op: op_with_inputs { value_input }
+ assert.is.same { [value_value]: value_input }, value.side_inputs
+
+ result = RTNode children: { event, value }
+ assert.is.same { [event_value]: event_input, [value_value]: value_input },
+ result.side_inputs
+
+ describe ':tick', ->
+ local a_value, a_child, a_input
+ local b_value, b_child, b_input
+ before_each ->
+ a_value = EvtStream num
+ a_input = Input.hot a_value
+ a_child = result_with_sideinput a_value, a_input
+
+ b_value = EvtStream num
+ b_input = Input.hot b_value
+ b_child = result_with_sideinput b_value, b_input
+
+ it 'updates children when a side_input is dirty', ->
+ a_value\add 1
+ assert.is.true a_input\dirty!
+ assert.is.false b_input\dirty!
+
+ a = spy.on a_child, 'tick'
+ b = spy.on b_child, 'tick'
+
+ result = RTNode children: { a_child, b_child }
+ result\tick!
+
+ assert.spy(a).was_called_with match.ref a_child
+ assert.spy(b).was_called_with match.ref b_child
+
+ it 'early-outs when no side_inputs are dirty', ->
+ assert.is.false a_input\dirty!
+ assert.is.false b_input\dirty!
+
+ a = spy.on a_child, 'tick'
+ b = spy.on b_child, 'tick'
+
+ result = RTNode children: { a_child, b_child }
+ result\tick!
+
+ assert.spy(a).was_not_called!
+ assert.spy(b).was_not_called!
+
+ it 'updates op when any op-inputs are dirty', ->
+ a_value\add 1
+ assert.is.true a_input\dirty!
+ assert.is.false b_input\dirty!
+
+ op = op_with_inputs a: Input.hot a_value
+ s = spy.on op, 'tick'
+
+ result = RTNode :op, children: { a_child, b_child }
+ result\tick!
+
+ assert.spy(s).was_called_with match.ref op
+
+ it 'early-outs when no op-inputs are dirty', ->
+ a_value\add 1
+ assert.is.true a_input\dirty!
+ assert.is.false b_input\dirty!
+
+ op = op_with_inputs { Input.hot b_value }
+ s = spy.on op, 'tick'
+
+ result = RTNode :op, children: { a_child, b_child }
+ result\tick!
+
+ assert.spy(s).was_not_called!
+
+ describe ':poll_io', ->
+ it 'polls IOs referenced in side_inputs', ->
+ io = DirtyIO!
+ input = Input.hot io
+ op = op_with_inputs { input }
+ result = RTNode :op
+
+ s = spy.on io, 'poll'
+ assert.is.same { [io]: input }, result.side_inputs
+ result\poll_io!
+
+ assert.spy(s).was_called_with match.ref io