diff options
| author | s-ol <s-ol@users.noreply.github.com> | 2020-05-12 14:20:52 +0000 |
|---|---|---|
| committer | s-ol <s+removethis@s-ol.nu> | 2025-03-02 14:23:21 +0000 |
| commit | b41a406ab7f56cc33aca594fb38b60c67d4130ce (patch) | |
| tree | faf683fef2ee2b700b3f0d688e0f4727fc64ab0e | |
| parent | make EvtStreams carry a single value (diff) | |
| download | alive-b41a406ab7f56cc33aca594fb38b60c67d4130ce.tar.gz alive-b41a406ab7f56cc33aca594fb38b60c67d4130ce.zip | |
RTNode constifies constant SigStreams
| -rw-r--r-- | alv/base/input.moon | 19 | ||||
| -rw-r--r-- | alv/rtnode.moon | 18 | ||||
| -rw-r--r-- | spec/input_spec.moon | 15 | ||||
| -rw-r--r-- | spec/match_spec.moon | 13 | ||||
| -rw-r--r-- | spec/rtnode_spec.moon | 49 |
5 files changed, 80 insertions, 34 deletions
diff --git a/alv/base/input.moon b/alv/base/input.moon index b73a476..f29bd10 100644 --- a/alv/base/input.moon +++ b/alv/base/input.moon @@ -76,8 +76,11 @@ class Input metatype: => @result.metatype --- the current value - -- - -- @tfield SigStream result + -- @tfield Result result + + --- the Input mode + -- @tfield string mode `'hot'`, `'cold'` or `'io'`. + mode: 'hot' --- members -- @section members @@ -125,17 +128,25 @@ class Input InputType value class ColdInput extends Input + mode: 'cold' dirty: => false class ValueInput extends Input - setup: (old) => @dirty_setup = not old or @result != old.result + new: (result) => + super result + @mode = if @result.metatype == '=' then 'cold' else 'hot' + + setup: (old) => + @dirty_setup = not old or @result != old.result + finish_setup: => @dirty_setup = nil + dirty: => return @dirty_setup if @dirty_setup != nil @result\dirty! class IOInput extends Input - io: true + mode: 'io' mapping = { [Constant]: ValueInput diff --git a/alv/rtnode.moon b/alv/rtnode.moon index b10f9a1..23cffa5 100644 --- a/alv/rtnode.moon +++ b/alv/rtnode.moon @@ -45,7 +45,7 @@ class RTNode -- should be called once per frame on the root, right before tick. poll_io: => for result, input in pairs @side_inputs - result\poll! if input.io + result\poll! if input.mode == 'io' --- in depth-first order, tick all Ops which have dirty Inputs. -- @@ -120,13 +120,15 @@ class RTNode is_child[child.result] = true if @op - for input in @op\all_inputs! - continue if input.result.metatype == '=' - 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" + for i in @op\all_inputs! + if i.mode == 'io' or (i.mode == 'hot' and not is_child[i.result]) + @side_inputs[i.result] = i + + if @result + if next @side_inputs + assert @result.metatype != '=', "Const result has side_inputs" + elseif @result.metatype == '~' + @result = @result.type\mk_const @result\unwrap! { :RTNode diff --git a/spec/input_spec.moon b/spec/input_spec.moon index 3a8eff9..9237fd8 100644 --- a/spec/input_spec.moon +++ b/spec/input_spec.moon @@ -28,6 +28,9 @@ describe 'Input.cold', -> basic_tests result, input + it 'is marked cold', -> + assert.is.equal 'cold', input.mode + it 'is never dirty', -> assert.is.false input\dirty! result\set 2 @@ -51,6 +54,9 @@ describe 'Input.hot', -> basic_tests result, input + it 'is marked cold', -> + assert.is.equal 'cold', input.mode + describe 'at evaltime', -> it 'is dirty when new', -> assert.is.false result\dirty! @@ -84,8 +90,8 @@ describe 'Input.hot', -> basic_tests result, input - it 'is marked for lifting', -> - assert.is.nil input.io + it 'is marked hot', -> + assert.is.equal 'hot', input.mode it 'is dirty when the EvtStream is dirty', -> assert.is.false input\dirty! @@ -115,7 +121,7 @@ describe 'Input.hot', -> basic_tests result, input it 'is marked for lifting', -> - assert.is.true input.io + assert.is.equal 'io', input.mode it 'is dirty when the IOStream is dirty', -> result.is_dirty = false @@ -172,6 +178,9 @@ describe 'Input.hot', -> assert.is.false newinput\dirty! newinput\finish_setup! + it 'is marked hot', -> + assert.is.equal 'hot', input.mode + describe 'at runtime', -> it 'is dirty when the result is dirty', -> result\set 3 diff --git a/spec/match_spec.moon b/spec/match_spec.moon index afaef56..8be64de 100644 --- a/spec/match_spec.moon +++ b/spec/match_spec.moon @@ -1,15 +1,18 @@ import val, evt from require 'alv.base.match' +import Op, Input from require 'alv.base' import RTNode, T, Error from require 'alv' +op_with_inputs = (inputs) -> + with Op! + \setup inputs if inputs + mk_val = (type, const) -> - result = T[type]\mk_sig! - with RTNode :result - .side_inputs = { 'fake' } unless const + result = T[type]\mk_sig true + RTNode :result, op: op_with_inputs { Input.hot result } mk_evt = (type, const) -> result = T[type]\mk_evt! - with RTNode :result - .side_inputs = { 'fake' } unless const + RTNode :result, op: op_with_inputs { Input.hot result } describe 'val and evt', -> describe 'type-less shorthand', -> diff --git a/spec/rtnode_spec.moon b/spec/rtnode_spec.moon index 9c62350..1719620 100644 --- a/spec/rtnode_spec.moon +++ b/spec/rtnode_spec.moon @@ -4,18 +4,23 @@ import T, Input, Op, Constant, IOStream from require 'alv.base' setup do_setup +class DirtyIO extends IOStream + new: => super T.dirty_io + dirty: => true + op_with_inputs = (inputs) -> with Op! \setup inputs if inputs +dirty_op = -> + result = DirtyIO! + input = Input.hot result + result, input, op_with_inputs { input } + node_with_sideinput = (result, input) -> with RTNode :result .side_inputs = { [result]: input } -class DirtyIO extends IOStream - new: => super T.dirty_io - dirty: => true - describe 'RTNode', -> it 'wraps result, children', -> result = Constant.num 3 @@ -69,23 +74,41 @@ describe 'RTNode', -> value_input = Input.hot value op = op_with_inputs { event_input, value_input } - node = RTNode op: op, result: value + node = RTNode :op, result: value assert.is.equal op, node.op assert.is.same { [event]: event_input, [value]: value_input }, node.side_inputs - it 'does not lift up op inputs that are also child values', -> + it 'does not lift up op inputs that are also children', -> + child_result, child_input, child_op = dirty_op! + result = T.num\mk_sig 4 + child = RTNode op: child_op, :result + event = T.bang\mk_evt! event_input = Input.hot event + input = Input.hot child - result = T.num\mk_sig 4 - value_input = Input.hot result + op = op_with_inputs { event_input, input } + node = RTNode :op, children: { child } - op = op_with_inputs { event_input, value_input } - node = RTNode op: op, :result, children: { RTNode :result } + assert.is.same { [event]: event_input, [child_result]: child_input }, + node.side_inputs + + it 'does not lift up op inputs that are cold', -> + bang = T.bang\mk_const true + bang_input = Input.hot bang + + num = T.num\mk_const 2 + num_input = Input.cold num + + sym = T.sym\mk_sig 'hello' + sym_input = Input.hot sym + + op = op_with_inputs { bang_input, num_input, sym_input } + node = RTNode :op - assert.is.same { [event]: event_input }, node.side_inputs + assert.is.same { [sym]: sym_input }, node.side_inputs it 'lifts up side_inputs from children', -> event_value = T.bang\mk_evt! @@ -169,9 +192,7 @@ describe 'RTNode', -> describe ':poll_io', -> it 'polls IOs referenced in side_inputs', -> - io = DirtyIO! - input = Input.hot io - op = op_with_inputs { input } + io, input, op = dirty_op! node = RTNode :op s = spy.on io, 'poll' |
