aboutsummaryrefslogtreecommitdiffstats
path: root/core/base/input.moon
blob: c89337f7e7fab2f613cd99575d34023475d70495 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
----
-- Update scheduling policy for `Op` arguments.
--
-- @classmod Input
import Value from require 'core.value'
import Result from require 'core.result'

local ColdInput, ValueInput, EventInput, IOInput

class Input
--- Input interface.
--
-- Methods that have to be implemented by `Input` implementations.
-- @section interface

  --- 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}"

  --- copy state from old instance (optional).
  --
  -- called by `Op:setup` with another `Input` instance or `nil` once this instance is
  -- registered. Must prepare this instance for `dirty`.
  --
  -- May enter a 'setup state' that is exited using `finish_setup`.
  --
  -- @tparam ?Input prev previous `Input` intance or nil
  setup: (prev) =>

  --- whether this input requires processing (optional).
  --
  -- 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}.
  --
  -- @treturn bool whether processing is necessary
  dirty: => @stream\dirty!

  --- leave setup state (optional).
  --
  -- called after the `Op` has completed (or skipped) its first `Op:tick` after
  -- `Op:setup`. Must prepare this instance for dataflow operation.
  finish_setup: =>

  --- unwrap to Lua value (optional).
  --
  -- @treturn any the raw Lua value
  unwrap: => @stream\unwrap!

  --- return the type name of this `Input` (optional).
  type: => @stream.type

  --- the current value
  --
  -- @tfield Value stream

--- members
-- @section members

  --- alias for `unwrap`.
  __call: => @stream\unwrap!

  __tostring: => "#{@@__name}:#{@stream}"
  __inherited: (cls) =>
    cls.__base.__call = @__call
    cls.__base.__tostring = @__tostring

--- static functions
-- @section static

  --- Create a `cold` `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

  --- Create a `value` `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.
  --
  -- @tparam Value|Result value
  @value: (value) -> ValueInput value

  --- Create an `event` `Input`.
  --
  -- Only marked dirty if the `Value` itself is dirty. Should be used whenever
  -- an `Input` denotes a momentary event or impulse.
  --
  -- @tparam Value|Result value
  @event: (value) -> EventInput 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

class ColdInput extends Input
  dirty: => false

class ValueInput extends Input
  setup: (old) => @dirty_setup = not old or @stream != old.stream
  finish_setup: => @dirty_setup = nil
  dirty: =>
    return @dirty_setup if @dirty_setup != nil
    @stream\dirty!

class EventInput extends Input

class IOInput extends Input
  impure: true
  dirty: => @stream\unwrap!\dirty!

{
  :Input
}