diff options
| author | s-ol <s-ol@users.noreply.github.com> | 2020-05-12 16:27:19 +0000 |
|---|---|---|
| committer | s-ol <s+removethis@s-ol.nu> | 2025-03-02 14:23:21 +0000 |
| commit | 8ecead9e25187e1b4dcd3c9cef2cd21b8384eaba (patch) | |
| tree | e893442b00d19fb5576df24b086fe3ad44c20809 | |
| parent | base.match: never recall by default (diff) | |
| download | alive-8ecead9e25187e1b4dcd3c9cef2cd21b8384eaba.tar.gz alive-8ecead9e25187e1b4dcd3c9cef2cd21b8384eaba.zip | |
add and use PureOp
| -rw-r--r-- | alv-lib/logic.moon | 100 | ||||
| -rw-r--r-- | alv-lib/math.moon | 59 | ||||
| -rw-r--r-- | alv-lib/string.moon | 15 | ||||
| -rw-r--r-- | alv/base/init.moon | 4 | ||||
| -rw-r--r-- | alv/base/pureop.moon | 56 |
5 files changed, 128 insertions, 106 deletions
diff --git a/alv-lib/logic.moon b/alv-lib/logic.moon index aaf255e..5ca4e68 100644 --- a/alv-lib/logic.moon +++ b/alv-lib/logic.moon @@ -1,4 +1,4 @@ -import Op, SigStream, Constant, Input, Error, T, val from require 'alv.base' +import PureOp, Constant, T, val, evt from require 'alv.base' all_same = (first, list) -> for v in *list @@ -14,19 +14,16 @@ tobool = (val) -> else true -class ReduceOp extends Op - pattern = val! + val! * 0 - setup: (inputs) => - @out or= SigStream T.bool - { first, rest } = pattern\match inputs - super - first: Input.hot first - rest: [Input.hot v for v in *rest] +any = val! / evt! + +class ReduceOp extends PureOp + pattern: any\rep 2, nil + type: T.bool tick: => - { :first, :rest } = @unwrap_all! - accum = tobool first - for val in *rest + args = @unwrap_all! + accum = tobool args[1] + for val in *args[2,] accum = @.fn accum, tobool val @out\set accum @@ -38,32 +35,22 @@ eq = Constant.meta examples: { '(== a b [c]…)', '(eq a b [c]…)' } description: "`true` if the types and values of all arguments are equal." - value: class extends Op - pattern = val! + val! * 0 + value: class extends ReduceOp setup: (inputs) => - @out or= SigStream T.bool, false - { first, rest } = pattern\match inputs - same = all_same first\type!, [i\type! for i in *rest] - - super if same - { - first: Input.hot first - rest: [Input.hot v for v in *rest] - } - else - {} + @state or= {} + @state.same_type = all_same inputs[1]\type!, [i\type! for i in *inputs[2,]] + super inputs tick: => - if not @inputs.first + if not @state.same_type @out\set false return - { :first, :rest } = @unwrap_all! - type = @inputs.first\type! - - equal = true - for other in *rest - if not type\eq first, other + typ = @inputs[1]\type! + args = @unwrap_all! + equal, first = true, args[1] + for other in *args[2,] + if not typ\eq first, other equal = false break @@ -76,25 +63,24 @@ not_eq = Constant.meta examples: { '(!= a b [c]…)', '(not-eq a b [c]…)' } description: "`true` if types or values of any two arguments are different." - value: class extends Op + value: class extends ReduceOp setup: (inputs) => - @out or= SigStream T.bool, false - assert #inputs > 1, Error 'argument', "need at least two values" - super [Input.hot v for v in *inputs] + @state or= {} + @state.same_type = all_same inputs[1]\type!, [i\type! for i in *inputs[2,]] + super inputs tick: => - if not @inputs[1] + if not @state.same_type @out\set true return - diff = true - for a=1, #@inputs-1 - for b=a+1, #@inputs - if @inputs[a].result == @inputs[b].result - diff = false - break - - break unless diff + typ = @inputs[1]\type! + args = @unwrap_all! + diff, first = true, args[1] + for other in *args[2,] + if typ\eq first, other + diff = false + break @out\set diff @@ -120,14 +106,10 @@ not_ = Constant.meta summary: "Logical NOT." examples: { '(not a)' } - value: class extends Op - setup: (inputs) => - @out or= SigStream T.bool, false - value = val!\match inputs - super value: Input.hot value - - tick: => - @out\set not tobool @inputs.value! + value: class extends PureOp + pattern: any\rep 1, 1 + type: T.bool + tick: => @out\set not tobool @inputs[1]! bool = Constant.meta meta: @@ -136,14 +118,10 @@ bool = Constant.meta examples: { '(bool a)' } description: "`false` if a is `false`, `nil` or `0`, `true` otherwise." - value: class extends Op - setup: (inputs) => - @out or= SigStream T.bool - value = val!\match inputs - super value: Input.hot value - - tick: => - @out\set tobool @inputs.value! + value: class extends PureOp + pattern: any\rep 1, 1 + type: T.bool + tick: => @out\set tobool @inputs[1]! { :eq, '==': eq diff --git a/alv-lib/math.moon b/alv-lib/math.moon index 8037e8a..b51718a 100644 --- a/alv-lib/math.moon +++ b/alv-lib/math.moon @@ -1,31 +1,23 @@ -import Op, Constant, SigStream, Error, Input, T, val from require 'alv.base' +import PureOp, Constant, T, val, evt from require 'alv.base' unpack or= table.unpack -class ReduceOp extends Op - pattern = val.num + val.num*0 - setup: (inputs) => - @out or= SigStream T.num - { first, rest } = pattern\match inputs - super - first: Input.hot first - rest: [Input.hot v for v in *rest] +num = val.num / evt.num + +class ReduceOp extends PureOp + pattern: num\rep 2, nil + type: T.num tick: => - { :first, :rest } = @unwrap_all! - accum = first - for val in *rest + args = @unwrap_all! + accum = args[1] + for val in *args[2,] accum = @.fn accum, val @out\set accum func_op = (func, pattern) -> - class extends Op - - setup: (inputs) => - @out or= SigStream T.num - - params = pattern\match inputs - super [Input.hot p for p in *params] - + class extends PureOp + pattern: pattern + type: T.num tick: => @out\set func unpack @unwrap_all! @@ -35,20 +27,15 @@ func_def = (name, args, func, summary, pattern) -> :name :summary examples: { "(#{name} #{args})" } - value: func_op func, pattern or val.num\rep 1, 1 + value: func_op func, pattern or num\rep 1, 1 evenodd_op = (remainder) -> - class extends Op - pattern = val.num + -val.num - setup: (inputs) => - @out or= SigStream T.bool - { val, div } = pattern\match inputs - super - val: Input.hot val - div: Input.hot div or SigStream.num 2 + class extends PureOp + pattern: num + -num + type: T.bool tick: => - { :val, :div } = @unwrap_all! + { val, div } = @unwrap_all! @out\set (val % div) == remainder add = Constant.meta @@ -101,7 +88,7 @@ mod = Constant.meta summary: 'Modulo operator.' examples: { '(% num div)', '(mod num div)' } description: "Calculate remainder of division by `div`." - value: func_op ((a, b) -> a % b), val.num + val.num + value: func_op ((a, b) -> a % b), num + num even = Constant.meta meta: @@ -127,7 +114,7 @@ mix = Constant.meta summary: 'Linearly interpolate.' examples: { '(mix a b i)' } description: "Interpolate between `a` and `b` using `i` in range 0-1." - value: func_op ((a, b, i) -> i*b + (1-i)*a), val.num + val.num + val.num + value: func_op ((a, b, i) -> i*b + (1-i)*a), num + num + num min = Constant.meta meta: @@ -135,7 +122,7 @@ min = Constant.meta summary: "Find the minimum." examples: { '(min a b [c…])' } description: "Return the lowest of arguments." - value: func_op math.min, val.num*0 + value: func_op math.min, num*0 max = Constant.meta meta: @@ -143,7 +130,7 @@ max = Constant.meta summary: "Find the maximum." examples: { '(max a b [c…])' } description: "Return the highest of arguments." - value: func_op math.max, val.num*0 + value: func_op math.max, num*0 cos = func_def 'cos', 'alpha', math.cos, "Cosine function (radians)." sin = func_def 'sin', 'alpha', math.sin, "Sine function (radians)." @@ -151,7 +138,7 @@ tan = func_def 'tan', 'alpha', math.tan, "Tangent function (radians)." acos = func_def 'acos', 'cos', math.acos, "Inverse cosine function (radians)." asin = func_def 'asin', 'sin', math.asin, "Inverse sine function (radians)." atan = func_def 'atan', 'tan', math.atan, "Inverse tangent function (radians)." -atan2 = func_def 'atan2', 'y x', math.atan2, "Inverse tangent function (two argument version).", val.num + val.num +atan2 = func_def 'atan2', 'y x', math.atan2, "Inverse tangent function (two argument version).", num + num cosh = func_def 'cosh', 'alpha', math.cosh, "Hyperbolic cosine function (radians)." sinh = func_def 'sinh', 'alpha', math.sinh, "Hyperbolic sine function (radians)." tanh = func_def 'tanh', 'alpha', math.tanh, "Hyperbolic tangent function (radians)." @@ -161,7 +148,7 @@ ceil = func_def 'ceil', 'val', math.ceil, "Round towards positive infinity." abs = func_def 'abs', 'val', math.abs, "Get the absolute value." exp = func_def 'exp', 'exp', math.floor, "*e* number raised to a power." -log = func_def 'log', 'val [base]', math.log, "Logarithm with given base.", val.num + -val.num +log = func_def 'log', 'val [base]', math.log, "Logarithm with optional base.", num + -num log10 = func_def 'log10', 'val', math.log10, "Logarithm with base 10." sqrt = func_def 'sqrt', 'val', math.sqrt, "Square root function." diff --git a/alv-lib/string.moon b/alv-lib/string.moon index 9f09f10..24a2a1b 100644 --- a/alv-lib/string.moon +++ b/alv-lib/string.moon @@ -1,17 +1,16 @@ -import Op, Constant, SigStream, Input, T from require 'alv.base' +import PureOp, Constant, Input, T, val, evt from require 'alv.base' + +any = val! / evt! str = Constant.meta meta: name: 'str' summary: "Concatenate/stringify values." examples: { '(.. v1 [v2…])', '(str v1 [v2…])' } - value: class extends Op - setup: (inputs) => - @out or= SigStream T.str - super [Input.hot v for v in *inputs] - - tick: => - @out\set table.concat [tostring v! for v in *@inputs] + value: class extends PureOp + pattern: any\rep 1, nil + type: T.str + tick: => @out\set table.concat [tostring i! for i in *@inputs] { :str, '..': str diff --git a/alv/base/init.moon b/alv/base/init.moon index 0cab7e3..65730a3 100644 --- a/alv/base/init.moon +++ b/alv/base/init.moon @@ -6,6 +6,7 @@ -- -- @module base -- @see Op +-- @see PureOp -- @see Builtin -- @see FnDef -- @see Input @@ -24,6 +25,7 @@ -- @see Error import Op from require 'alv.base.op' +import PureOp from require 'alv.base.pureop' import Builtin from require 'alv.base.builtin' import FnDef from require 'alv.base.fndef' import Input from require 'alv.base.input' @@ -34,7 +36,7 @@ import RTNode from require 'alv.rtnode' import Error from require 'alv.error' { - :Op + :Op, :PureOp :Builtin :FnDef :Input diff --git a/alv/base/pureop.moon b/alv/base/pureop.moon new file mode 100644 index 0000000..ea3b810 --- /dev/null +++ b/alv/base/pureop.moon @@ -0,0 +1,56 @@ +---- +-- 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 `tick`. +-- @classmod PureOp +import Op from require 'alv.base.op' +import Input from require 'alv.base.input' +import SigStream, EvtStream from require 'alv.result' +import Error from require 'alv.error' + +unpack or= table.unpack + +class PureOp extends Op +--- members. +-- @section members + + --- the argument pattern. + -- + -- Must resolve to a simple sequence-table (depth 1). + -- + -- @tfield match.Pattern pattern + @pattern: nil + + --- the result type. + -- @tfield type.Type type + @type: nil + + --- set up inputs for a range of things. + setup: (inputs) => + args = @@pattern\match inputs + + local trigger + for arg in *args + if arg.result.metatype == '!' + assert not trigger, Error 'argument', "pure op can take at most one !-stream." + trigger = arg + + if trigger + super for a in *args + if a == trigger + Input.hot trigger + else + Input.cold a + @out = EvtStream @@type + else + super [Input.hot a for a in *args] + @out or= SigStream @@type + +{ + :PureOp +} |
