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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
import Op, ValueInput, match from require 'core.base'
all_same = (first, list) ->
for v in *list
if v != first
return false
first
tobool = (val) ->
switch val
when false, nil, 0
false
else
true
class ReduceOp extends Op
new: => super 'bool'
setup: (inputs) =>
{ first, rest } = match "any *any", inputs
super
first: ValueInput first
rest: [ValueInput v for v in *rest]
tick: =>
{ :first, :rest } = @unwrap_all!
accum = tobool first
for val in *rest
accum = @.fn accum, tobool val
@out\set accum
class eq extends Op
@doc: "(eq a b [c]...)
(== a b [c]...) - check for equality
If the value types dont match, the result is an eval-time constant 'false'."
new: => super 'bool', false
setup: (inputs) =>
{ first, rest } = match "any *any", inputs
same = all_same first\type!, [i\type! for i in *rest]
super if same
{
first: ValueInput first
rest: [ValueInput v for v in *rest]
}
else
{}
tick: =>
if not @inputs.first
@out\set false
return
{ :first, :rest } = @unwrap_all!
equal = true
for other in *rest
if first != other
equal = false
break
@out\set equal
class not_eq extends Op
@doc: "(not-eq a b [c]...)
(!= a b [c]...) - check for inequality"
new: => super 'bool'
setup: (inputs) =>
assert #inputs > 1, "neq need at least two values"
super [ValueInput v for v in *inputs]
tick: =>
if not @inputs[1]
@out\set true
return
diff = true
for a=1, #@inputs-1
for b=a+1, #@inputs
if @inputs[a].stream == @inputs[b].stream
diff = false
break
break unless diff
@out\set diff
class and_ extends ReduceOp
@doc: "(and a b [c]...) - AND values"
fn: (a, b) -> a and b
class or_ extends ReduceOp
@doc: "(or a b [c]...) - OR values"
fn: (a, b) -> a or b
class not_ extends Op
@doc: "(not a) - boolean opposite"
new: => super 'bool'
setup: (inputs) =>
{ value } = match 'any', inputs
super value: ValueInput value
tick: => @out\set not tobool @inputs.value!
class bool extends Op
@doc: "(bool a) - convert to bool"
new: => super 'bool'
setup: (inputs) =>
{ value } = match 'any', inputs
super value: ValueInput value
tick: => @out\set tobool @inputs\value!
{
:eq, '==': eq
'not-eq': not_eq, '!=': not_eq
and: and_
or: or_
not: not_
:bool
}
|