aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authors-ol <s-ol@users.noreply.github.com>2020-03-02 13:16:21 +0000
committers-ol <s-ol@users.noreply.github.com>2020-03-02 13:16:21 +0000
commitdf91fee4a7bb17f8822a0a5637533257d30e0743 (patch)
tree54f1a3a7bc7b850cc4b0a87296670612274ca518
parentconvert lib.time to IO (diff)
downloadalive-df91fee4a7bb17f8822a0a5637533257d30e0743.tar.gz
alive-df91fee4a7bb17f8822a0a5637533257d30e0743.zip
update lib.math and lib.logic to new op interface
-rw-r--r--copilot.moon4
-rw-r--r--core/base.moon2
-rw-r--r--core/parsing.moon2
-rw-r--r--core/value.moon5
-rw-r--r--lib/logic.moon148
-rw-r--r--lib/math.moon86
6 files changed, 152 insertions, 95 deletions
diff --git a/copilot.moon b/copilot.moon
index 1791174..6d8d977 100644
--- a/copilot.moon
+++ b/copilot.moon
@@ -23,7 +23,9 @@ class Copilot
patch: =>
ast = L\try "error parsing:", parse, slurp @file
- return unless ast
+ if not ast
+ L\error "error parsing"
+ return
scope = Scope ast, globals
root = L\try "error evaluating:", ast\eval, scope, @registry
diff --git a/core/base.moon b/core/base.moon
index cf3d146..c6ea694 100644
--- a/core/base.moon
+++ b/core/base.moon
@@ -31,7 +31,7 @@ class Input
--
-- during setup, only marked dirty if old and new stream differ in value
class ValueInput extends Input
- merge: (old) => @dirty_setup = not old or @stream\unwrap! != old\unwrap!
+ merge: (old) => @dirty_setup = not old or @stream != old.stream
finish_setup: => @dirty_setup = false
dirty: => @dirty_setup or @stream\dirty!
diff --git a/core/parsing.moon b/core/parsing.moon
index ac4f878..e919c41 100644
--- a/core/parsing.moon
+++ b/core/parsing.moon
@@ -15,7 +15,7 @@ mspace = (comment + wc)^0 / 1 -- optional whitespace
-- atoms
digit = R '09'
-first = (R 'az', 'AZ') + S '-_+*/.!?='
+first = (R 'az', 'AZ') + S '-_+*/.!?=%'
sym = first * (first + digit)^0 / Value\parse 'sym'
strd = '"' * (C ((P '\\"') + (P '\\\\') + (1 - P '"'))^0) * '"' / Value\parse 'str', '\"'
diff --git a/core/value.moon b/core/value.moon
index d4a0de3..b882507 100644
--- a/core/value.moon
+++ b/core/value.moon
@@ -46,6 +46,11 @@ class Result
assert not (next @side_inputs), msg or "eval-time const expected"
@value
+ -- asserts a value exists and returns its type
+ type: =>
+ assert @value, "Result with value expected"
+ @value.type
+
-- create a value-copy of this result that has the same impulses but without
-- affecting the original's update logic
make_ref: =>
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_
diff --git a/lib/math.moon b/lib/math.moon
index ca965be..4d01741 100644
--- a/lib/math.moon
+++ b/lib/math.moon
@@ -1,67 +1,63 @@
-import Op, Value from require 'core'
+import Op, Value, ValueInput, match from require 'core'
unpack or= table.unpack
-class BinOp extends Op
- new: =>
- super 'num', 0
+class ReduceOp extends Op
+ new: => super 'num'
- setup: (params) =>
- super params
- assert #@inputs >= 2, "#{@} needs at least two parameters"
+ setup: (inputs) =>
+ { first, rest } = match 'num *num', inputs
+ super
+ first: ValueInput first
+ rest: [ValueInput v for v in *rest]
-class add extends BinOp
+ tick: =>
+ { :first, :rest } = @unwrap_all!
+ accum = first
+ for val in *rest
+ accum = @.fn accum, val
+ @out\set accum
+
+class add extends ReduceOp
@doc: "(+ a b [c]...)
(add a b [c]...) - add values"
- tick: =>
- value = 0
- for child in *@inputs
- value += child\unwrap 'num'
- @out\set value
+ fn: (a, b) -> a + b
-class sub extends BinOp
+class sub extends ReduceOp
@doc: "(- a b [c]...)
(sub a b [c]...) - subtract values
subtracts all other arguments from a"
- tick: =>
- value = @inputs[1]\unwrap 'num'
- for child in *@inputs[2,]
- value -= child\unwrap 'num'
- @out\set value
+ fn: (a, b) -> a - b
-class mul extends BinOp
+class mul extends ReduceOp
@doc: "(* a b [c]...)
(mul a b [c]...) - multiply values"
- tick: =>
- value = 1
- for child in *@inputs
- value *= child\unwrap 'num'
- @out\set value
+ fn: (a, b) -> a * b
-class div extends BinOp
+class div extends ReduceOp
@doc: "(/ a b [c]...)
(div a b [c]...) - divide values
divides a by all other arguments"
- tick: =>
- value = @inputs[1]\unwrap 'num'
- for child in *@inputs[2,]
- value /= child\unwrap 'num'
- @out\set value
+ fn: (a, b) -> a / b
evenodd_op = (name, remainder) ->
class k extends Op
- setup: (@a, @div=Const.num 2) =>
- @out = Stream 'bool'
- @out
+ new: => super 'bool'
+
+ setup: (inputs) =>
+ { val, div } = match 'num num?', inputs
+ super
+ val: ValueInput val
+ div: ValueInput div or Value.num 2
tick: =>
- a, divi = (@a\unwrap 'num'), @div\unwrap 'num'
- @out\set (a % divi) == remainder
+ { :val, :div } = @unwrap_all!
+ @out\set (val % div) == remainder
k.__name = name
k.doc = "(#{name} a [div]) - check for #{name} divison
@@ -71,16 +67,14 @@ div defaults to 2"
func_op = (name, arity, func) ->
k = class extends Op
- new: =>
- super 'num'
+ new: => super 'num'
- setup: (...) =>
- @params = { ... }
- if arity != '*'
- assert #@params == arity, "#{@} needs exactly #{arity} parameters"
+ setup: (inputs) =>
+ { params } = match '*num', inputs
+ assert #params == arity, "#{@} needs exactly #{arity} parameters" if arity != '*'
+ super [ValueInput p for p in *params]
- tick: =>
- @out\set func unpack [p\unwrap 'num' for p in *@params]
+ tick: => @out\set func unpack @unwrap_all!
k.__name = name
k
@@ -98,7 +92,9 @@ module = {
even: evenodd_op 'even', 0
odd: evenodd_op 'odd', 1
- pi: math.pi, huge: math.huge
+ pi: math.pi
+ tau: math.pi*2
+ huge: math.huge
}
for name, arity in pairs {