diff options
| author | s-ol <s-ol@users.noreply.github.com> | 2020-03-24 11:39:25 +0000 |
|---|---|---|
| committer | s-ol <s-ol@users.noreply.github.com> | 2020-03-24 11:39:25 +0000 |
| commit | 677c0d2f01e14bbeca1583ec7878d80c71c3aa68 (patch) | |
| tree | cc20e04697da590b546de370599eeaaef647d20c /core/base | |
| parent | internals/plugin-guide: first draft (diff) | |
| download | alive-677c0d2f01e14bbeca1583ec7878d80c71c3aa68.tar.gz alive-677c0d2f01e14bbeca1583ec7878d80c71c3aa68.zip | |
Value -> Value/Event/IO-Stream
Close 12
Diffstat (limited to 'core/base')
| -rw-r--r-- | core/base/init.moon | 12 | ||||
| -rw-r--r-- | core/base/input.moon | 92 | ||||
| -rw-r--r-- | core/base/io.moon | 40 | ||||
| -rw-r--r-- | core/base/op.moon | 66 |
4 files changed, 93 insertions, 117 deletions
diff --git a/core/base/init.moon b/core/base/init.moon index bb35140..8e376fc 100644 --- a/core/base/init.moon +++ b/core/base/init.moon @@ -4,28 +4,27 @@ -- This module exports the following classes that extension modules may need: -- -- @module base --- @see IO -- @see Op -- @see Action -- @see FnDef -- @see Input -- @see match --- @see Value +-- @see ValueStream +-- @see EventStream +-- @see IOStream -- @see Result -- @see Error -import IO from require 'core.base.io' import Op from require 'core.base.op' import Action from require 'core.base.action' import FnDef from require 'core.base.fndef' import Input from require 'core.base.input' import match from require 'core.base.match' -import Value from require 'core.value' +import ValueStream, EventStream, IOStream from require 'core.stream' import Result from require 'core.result' import Error from require 'core.error' { - :IO :Op :Action :FnDef @@ -33,5 +32,6 @@ import Error from require 'core.error' :match -- redundant exports, to keep anything an extension might need in one import - :Value, :Result, :Error + :ValueStream, :EventStream, :IOStream + :Result, :Error } diff --git a/core/base/input.moon b/core/base/input.moon index c89337f..6922a4f 100644 --- a/core/base/input.moon +++ b/core/base/input.moon @@ -2,10 +2,29 @@ -- Update scheduling policy for `Op` arguments. -- -- @classmod Input -import Value from require 'core.value' +import ValueStream, EventStream, IOStream from require 'core.stream' import Result from require 'core.result' -local ColdInput, ValueInput, EventInput, IOInput +inherits = (klass, frm) -> + assert klass, "cant find the ancestor of nil" + return true if klass == frm + while klass.__parent + return true if klass.__parent == frm + klass = klass.__parent + false + +match_parent = (inst, map) -> + klass = assert inst and inst.__class, "not an instance" + if key = map[klass] + return key + + while klass.__parent + if key = map[klass.__parent] + return key + + klass = klass.__parent + +local ColdInput, ValueInput, IOInput, mapping class Input --- Input interface. @@ -15,20 +34,10 @@ class Input --- create a new Input. -- - -- `value` is either a `Value` or a `Result` instance and should be - -- unwrapped and assigned to `stream`. - -- -- @classmethod - -- @tparam Value|Result value - new: (value) => - assert value, "nil passed to Input: #{value}" - @stream = switch value.__class - when Result - assert value.value, "Input from result without value!" - when Value - value - else - error "Input from unknown value: #{value}" + -- @tparam Stream stream + new: (@stream) => + assert @stream, "nil passed to Input: #{value}" --- copy state from old instance (optional). -- @@ -44,7 +53,7 @@ class Input -- -- must return a boolean indicating whether `Op`s that refer to this instance -- should be notified (via `Op:tick`). If not overwritten, delegates to - -- `stream`:@{Value:dirty|dirty}. + -- `stream`:@{ValueStream:dirty|dirty}. -- -- @treturn bool whether processing is necessary dirty: => @stream\dirty! @@ -65,7 +74,7 @@ class Input --- the current value -- - -- @tfield Value stream + -- @tfield ValueStream stream --- members -- @section members @@ -86,33 +95,29 @@ class Input -- Never marked dirty. Use this for input streams that are only read when -- another `Input` is dirty. -- - -- @tparam Value|Result value - @cold: (value) -> ColdInput value + -- @tparam Stream|Result value + @cold: (value) -> + if value.__class == Result + value = assert value.value, "Input from result without value!" + ColdInput value - --- Create a `value` `Input`. + --- Create a `hot` `Input`. -- - -- Marked dirty for the eval-tick if old and new `Value` differ. This is the - -- most common `Input` strategy. Should be used whenever a - -- value denotes state. + -- Behaviour depends on what kind of `Stream` `value` is: -- - -- @tparam Value|Result value - @value: (value) -> ValueInput value - - --- Create an `event` `Input`. + -- - `ValueStream`: Marked dirty for the eval-tick if old and new `ValueStream` differ. + -- - `EventStream` and `IOStream`: Marked dirty only if the current `EventStream` is dirty. -- - -- Only marked dirty if the `Value` itself is dirty. Should be used whenever - -- an `Input` denotes a momentary event or impulse. + -- This is the most common `Input` strategy. -- - -- @tparam Value|Result value - @event: (value) -> EventInput value + -- @tparam Stream|Result value + @hot: (value) -> + if value.__class == Result + value = assert value.value, "Input from result without value!" - --- Create an `IO` `Input`. - -- - -- Marked dirty only when an `IO` is dirty. Must be used only for `Value`s - -- which @{Value:unwrap|unwrap} to `IO` instances. - -- - -- @tparam Value|Result value - @io: (value) -> IOInput value + InputType = match_parent value, mapping + assert InputType, "Input from unknown value: #{value}" + InputType value class ColdInput extends Input dirty: => false @@ -124,11 +129,14 @@ class ValueInput extends Input return @dirty_setup if @dirty_setup != nil @stream\dirty! -class EventInput extends Input - class IOInput extends Input - impure: true - dirty: => @stream\unwrap!\dirty! + io: true + +mapping = { + [ValueStream]: ValueInput + [EventStream]: Input + [IOStream]: IOInput +} { :Input diff --git a/core/base/io.moon b/core/base/io.moon deleted file mode 100644 index cbb5823..0000000 --- a/core/base/io.moon +++ /dev/null @@ -1,40 +0,0 @@ ----- --- Incoming side-effect adapter, creating events for the dataflow graph. --- --- Polled by the main event loop to kick of events that cause the the dataflow --- graph to ripple results. --- --- @classmod IO - -class IO ---- IO interface. --- --- methods that have to be implemented by `IO` implementations. --- @section interface - - --- construct a new instance. - -- - -- Must prepare the instance for `dirty` to be called. - -- @classmethod - new: => - - --- poll for changes. - -- - -- Called every frame by the main event loop to update internal state. - tick: => - - --- check whether this adapter requires processing. - -- - -- Must return a boolean indicating whether `Op`s that refer to this instance - -- via `Input.io` should be notified (via `Op:tick`). May be called multiple - -- times. May be called before `tick` on the first frame after construction. - -- - -- @treturn bool whether processing is required - dirty: => - - __tostring: => "<IO #{@@__name}>" - __inherited: (cls) => cls.__base.__tostring = @__tostring - -{ - :IO -} diff --git a/core/base/op.moon b/core/base/op.moon index a8da100..4880afd 100644 --- a/core/base/op.moon +++ b/core/base/op.moon @@ -2,16 +2,16 @@ -- Persistent expression Operator. -- -- @classmod Op -import Value from require 'core.value' -ident = (tbl) -> - mt = getmetatable tbl - setmetatable tbl, nil - - id = tostring tbl - - setmetatable tbl, mt - id\sub #'table: 0x' +deepcopy = (val) -> + switch type val + when 'number', 'string', 'boolean' + 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}'" class Op --- members @@ -33,23 +33,30 @@ class Op -- Used to wrap insulate eval-cycles from each other. The copy does not have -- `inputs` set, since it is expected that this is (re)set in `setup`. -- - -- @treturn Value + -- @treturn Op fork: => - with setmetatable {}, getmetatable @ - .state = {k,v for k,v in pairs @state} if @state - .out = @out\fork! if @out + out = if @out then @out\fork + state = if @state then deepcopy state + @@ out, state + + --- internal state of this Op. + -- + -- This may be any simple Lua value, including Lua tables, as long as it has + -- no metatables, multiple references/loops, userdata etc. + -- + -- @tfield table state - --- `Value` instance representing this Op's computed output value. + --- `Stream` instance representing this Op's computed output value. -- - -- Must be set to a `Value` instance once `setup` finishes. Must not change - -- type, be removed or replaced outside of `new` and `setup`. Should have a - -- value assigned via `set` or the `Value` constructor once `tick` is - -- called the first time. If `out`'s value is not initialized in `new` - -- or `setup`, the implementation must make sure `tick``(true)` is called at - -- least on the first eval-cycle the Op goes through, e.g. by using an - -- `Input.value`. + -- Must be set to a `Stream` instance once `setup` finishes. Must not change + -- type, be removed or replaced outside of `new` and `setup`. If it is a + -- `ValueStream`, it should have a value assigned via `set` or the + -- constructor once `tick` is called the first time. If `out`'s value is not + -- initialized in `new` or `setup`, the implementation must make sure + -- `tick``(true)` is called at -- least on the first eval-cycle the Op goes + -- through, e.g. by using an `Input.value`. -- - -- @tfield Value out + -- @tfield Stream out --- table containing `Input`s to this Op. -- @@ -66,10 +73,14 @@ class Op --- construct a new instance. -- - -- The super-constructor can be used to construct a `Value` instance in `out`. + -- The optional parameters `out` and `state` are used by `fork` to duplicate + -- an instance. If the constructor is overriden, these parameters must be + -- forwarded to the superconstructor unchanged. -- -- @function new -- @classmethod + -- @tparam ?Stream out `out` + -- @tparam ?table state `state` --- parse arguments and patch self. -- @@ -109,12 +120,9 @@ class Op -- type is not known at this time. -- -- @classmethod - -- @tparam[opt] string type the type-name for `out` - -- @tparam[optchain] any init the initial value for `out` - new: (type, init) => - @state = {} - if type - @out = Value type, init + -- @tparam ?Stream out `out` + -- @tparam ?table state `state` + new: (@out, @state) => do_setup = (old, cur) -> for k, cur_val in pairs cur |
