1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
----
-- Stateless Operator base for pure functions.
--
-- All arguments can be evt- and val-capable. If one of the arguments is an
-- !-stream, it will be the only `Input.hot`. If there are no !-streams,
-- all inputs are hot. Passing more than one !-stream is an argument error.
--
-- To use `PureOp`, extend the class and set/implement only `pattern`, `type`
-- and `Op:tick`.
-- @classmod PureOp
import Op from require 'alv.base.op'
import Input from require 'alv.base.input'
import Type from require 'alv.type'
import Error from require 'alv.error'
import ancestor, deep_iter, deep_map from require 'alv.util'
unpack or= table.unpack
hot_if_trigger = (trigger) -> (a) ->
if a == trigger
return Input.hot a
Input.cold a
class PureOp extends Op
--- members.
-- @section members
--- the argument pattern.
--
-- Must resolve to a simple sequence-table (depth 1).
--
-- @tfield match.Pattern pattern
--- the result type or a method that returns it.
--
-- Can be either a method or just a fixed type.
--
-- @function type
-- @tparam table args as parsed by `pattern`
-- @treturn type.Type
--- set up inputs for a range of things.
--
-- @tparam {RTNode,...} inputs a sequence of `RTNode`s
-- @tparam Scope scope (unused)
-- @tparam[opt] table extra_inputs table of `Input`s to merge into pureop result
setup: (inputs, scope, extra_inputs={}) =>
args = @@pattern\match inputs
local trigger
for arg in coroutine.wrap -> deep_iter args
if arg.result.metatype == '!'
assert not trigger, Error 'argument', "pure op can take at most one !-stream."
trigger = arg
typ = if (type @type) == 'function' then @type args else @type
if typ
assert (ancestor typ.__class) == Type, "not a type: #{typ}"
metatype = if trigger then '!' else '~'
@setup_out metatype, typ
map_fn = if trigger then hot_if_trigger trigger else Input.hot
inputs = deep_map args, map_fn
for k,v in pairs extra_inputs
inputs[k] = v
super inputs
{
:PureOp
}
|