aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authors-ol <s-ol@users.noreply.github.com>2020-05-14 15:18:40 +0000
committers-ol <s+removethis@s-ol.nu>2025-03-02 14:24:49 +0000
commit6255ff9d6fcc36c752f9a0229db4eaecb5a9e466 (patch)
tree1cebf8b34b98970910b18fc164f32e208ec68f0a
parentfix osc/sync (diff)
downloadalive-6255ff9d6fcc36c752f9a0229db4eaecb5a9e466.tar.gz
alive-6255ff9d6fcc36c752f9a0229db4eaecb5a9e466.zip
pureops with arbitrary pattern
-rw-r--r--alv/base/op.moon21
-rw-r--r--alv/base/pureop.moon32
-rw-r--r--alv/util.moon28
3 files changed, 53 insertions, 28 deletions
diff --git a/alv/base/op.moon b/alv/base/op.moon
index da90288..a88bbe5 100644
--- a/alv/base/op.moon
+++ b/alv/base/op.moon
@@ -2,31 +2,16 @@
-- Persistent expression Operator.
--
-- @classmod Op
-
-deepcopy = (val) ->
- switch type val
- when 'number', 'string', 'boolean', 'nil'
- val
- when 'table'
- assert (not getmetatable {}), "state should only contain simple tables!"
- {(deepcopy k), (deepcopy v) for k,v in pairs val}
- else
- error "state cannot contain values of type '#{type val}'"
+import deep_copy, deep_iter from require 'alv.util'
class Op
--- members
-- @section members
- do_yield = (table) ->
- for k, v in pairs table
- if v.__class
- coroutine.yield v
- else
- do_yield v
--- yield all `Input`s from the (potentially nested) `inputs` table
--
-- @treturn iterator iterator over `inputs`
- all_inputs: => coroutine.wrap -> do_yield @inputs
+ all_inputs: => coroutine.wrap -> deep_iter @inputs
--- create a mutable copy of this Op.
--
@@ -36,7 +21,7 @@ class Op
-- @treturn Op
fork: =>
out = if @out then @out\fork!
- state = if @state then deepcopy @state
+ state = if @state then deep_copy @state
@@ out, state
--- internal state of this Op.
diff --git a/alv/base/pureop.moon b/alv/base/pureop.moon
index ea3b810..6a058f6 100644
--- a/alv/base/pureop.moon
+++ b/alv/base/pureop.moon
@@ -10,8 +10,9 @@
-- @classmod PureOp
import Op from require 'alv.base.op'
import Input from require 'alv.base.input'
-import SigStream, EvtStream from require 'alv.result'
+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
@@ -24,32 +25,43 @@ class PureOp extends Op
-- Must resolve to a simple sequence-table (depth 1).
--
-- @tfield match.Pattern pattern
- @pattern: nil
- --- the result type.
- -- @tfield type.Type type
- @type: nil
+ --- the result type or a method that returns it.
+ --
+ -- Can be either a method or just a fixed type.
+ --
+ -- @tparam table args as parsed by `pattern`
+ -- @treturn type.Type
--- set up inputs for a range of things.
setup: (inputs) =>
args = @@pattern\match inputs
local trigger
- for arg in *args
+ 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) == 'table' then @type else @type args
+ assert (ancestor typ.__class) == Type, "not a type: #{typ}"
+
if trigger
- super for a in *args
+ super deep_map args, (a) ->
if a == trigger
Input.hot trigger
else
Input.cold a
- @out = EvtStream @@type
+ -- super for a in *args
+ -- if a == trigger
+ -- Input.hot trigger
+ -- else
+ -- Input.cold a
+ @out = typ\mk_evt!
else
- super [Input.hot a for a in *args]
- @out or= SigStream @@type
+ -- super [Input.hot a for a in *args]
+ super deep_map args, (a) -> Input.hot a
+ @out or= typ\mk_sig!
{
:PureOp
diff --git a/alv/util.moon b/alv/util.moon
index 316233b..e175600 100644
--- a/alv/util.moon
+++ b/alv/util.moon
@@ -31,7 +31,35 @@ ancestor = (klass) ->
klass = klass.__parent
klass
+--- check whether a table is a 'plain' table
+is_plain_table = (val) -> (type val) == 'table' and not val.__class
+
+--- recursively copy a value
+deep_copy = (val) ->
+ if is_plain_table val
+ {(deep_copy k), (deep_copy v) for k,v in pairs val}
+ else
+ val
+
+--- map leaf values in a table
+deep_map = (val, fn) ->
+ if is_plain_table val
+ {k, (deep_map v, fn) for k,v in pairs val}
+ else
+ fn val
+
+--- yield all leaf values in a table
+deep_iter = (table) ->
+ for k, v in pairs table
+ if is_plain_table v
+ deep_iter v
+ else
+ coroutine.yield v
+
{
:opairs
:ancestor
+ :deep_copy
+ :deep_map
+ :deep_iter
}