aboutsummaryrefslogtreecommitdiffstats
path: root/lib/logic.moon
diff options
context:
space:
mode:
Diffstat (limited to 'lib/logic.moon')
-rw-r--r--lib/logic.moon148
1 files changed, 101 insertions, 47 deletions
diff --git a/lib/logic.moon b/lib/logic.moon
index c476033..d2144f6 100644
--- a/lib/logic.moon
+++ b/lib/logic.moon
@@ -1,75 +1,129 @@
-import Stream, Op from require 'core'
-unpack or= table.unpack
+import Op, ValueInput, match from require 'core'
-class BinOp extends Op
- new: (...) =>
- super ...
- @out = Stream 'bool'
+all_same = (first, list) ->
+ for v in *list
+ if v != first
+ return false
- setup: (...) =>
- @children = { ... }
- assert #@children >= 2, "#{@} needs at least two parameters"
- @out
+ true
-class eq extends BinOp
+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"
+(== 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!
- update: (dt) =>
equal = true
- val = @children[1]\unwrap!
- for child in *@children[2,]
- equal and= val == child\unwrap!
+ 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'
-class and_ extends BinOp
- @doc: "(and a b [c]...) - AND values"
+ 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
- update: (dt) =>
- value = true
- for child in *@children
- value and= child\unwrap!
- @out\set value
+ diff = true
+ for a=1, #@inputs-1
+ for b=a+1, #@inputs
+ print @inputs[a], @inputs[b]
+ if @inputs[a].stream == @inputs[b].stream
+ print "found a match #{a} == #{b}"
+ diff = false
+ break
-class or_ extends BinOp
- @doc: "(or a b [c]...) - OR values
+ break unless diff
-subtracts all other arguments from a"
+ @out\set diff
+
+class and_ extends ReduceOp
+ @doc: "(and a b [c]...) - AND values"
+ fn: (a, b) -> a and b
- update: (dt) =>
- value = false
- for child in *@children
- value or= child\unwrap!
- @out\set value
+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: (@a) =>
- @out = Stream 'bool'
- @out
+ setup: (inputs) =>
+ { value } = match 'any', inputs
+ super value: ValueInput value
- update: (dt) =>
- @out\set not @a\unwrap!
+ tick: => @out\set not tobool @inputs.value!
class bool extends Op
@doc: "(bool a) - convert to bool"
+ new: => super 'bool'
- setup: (@a) =>
- @out = Stream 'bool'
- @out
+ setup: (inputs) =>
+ { value } = match 'any', inputs
+ super value: ValueInput value
- update: (dt) =>
- @out\set switch @a\unwrap!
- when false, nil, 0
- false
- else
- true
+ tick: => @out\set tobool @inputs\value!
{
- '==': eq
- :eq
+ :eq, '==': eq
+ 'not-eq': not_eq, '!=': not_eq
and: and_
or: or_
not: not_