aboutsummaryrefslogtreecommitdiffstats
path: root/alv/base/builtin.moon
blob: 558a65a1c23fde9c6198495862fdf2bbb8329f8c (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
----
-- Builtin / Special Form evaluation Strategy (`builtin`).
--
-- Responsible for quoting/evaluating subexpressions, instantiating and setting
-- up `Op`s, updating the current `Scope`, etc.
-- See `builtin` and `invoke` for examples.
--
-- @classmod Builtin

class Builtin
--- Builtin interface.
--
-- methods that have to be implemented by `Builtin` implementations.
-- @section interface

  --- create a new instance.
  --
  -- @tparam Cell cell the Cell to evaluate
  -- @tparam Value head the (`AST:eval`d) `head` of the Cell to evaluate
  new: (@cell, @head) =>
    @tag = @cell.tag
    @tag\register @

  --- perform the actual evaluation.
  --
  -- Implementations should:
  --
  -- - eval or quote `tail` values
  -- - perform scope effects
  -- - wrap all child-results
  --
  -- @function eval
  -- @tparam Scope scope the active scope
  -- @tparam {AST,...} tail the arguments to this expression
  -- @treturn RTNode the result of this evaluation

  --- store the evaluation result for access by editor and return it.
  --
  -- This should always be called via `super` as the last statement in all
  -- overriden `eval` methods.
  --
  -- @tparam RTNode node the evaluation result
  eval: (@node) => @node

  --- free resources
  destroy: =>

  --- setup or copy state from previous instance of same type.
  --
  -- `prev` is only passed if Builtin types of prev and current expression match.
  -- Otherwise, or when no previous expression exists, `nil` is passed.
  --
  -- @tparam ?Builtin prev the previous Builtin instance
  setup: (prev) =>

  --- collect visualisation data (optional).
  --
  -- This may return any simple Lua value, including Lua tables, as long as it
  -- has no metatables, multiple references/loops, userdata etc.
  --
  -- This value is exposed to alv editors in order to render realtime
  -- visualisations overlaid onto the program text.
  --
  -- @treturn table vis
  vis: => {}

  --- the `Cell` this Builtin was created for.
  -- @tfield Cell cell

  --- the evaluated head of `cell`.
  -- @tfield AST head

  --- the identity of `cell`.
  -- @tfield Tag tag

  --- the last result of `eval`.
  -- @tfield RTNode node

--- static functions
-- @section static

  --- create and setup a `Builtin` for a given tag, then evaluate it.
  --
  -- Create a new instance using `tag` and `head` and call `setup` on it.
  -- If a previous instance with the same `tag` exists and has the same `head`,
  -- it pass it to `setup`. Register the `Builtin` with `tag`, evaluate it
  -- and return the `RTNode`.
  --
  -- @tparam Cell cell the `Cell` being evaluated
  -- @tparam Scope scope the active scope
  -- @tparam Value head the (`AST:eval`d) head of the `Cell` being evaluated
  -- @treturn RTNode the result of evaluation
  @eval_cell: (cell, scope, head) =>
    last = cell.tag\last!
    compatible = last and (last.__class == @) and last.head == head

    L\trace if compatible
      "reusing #{last} for #{cell.tag} <#{@__name} #{head}>"
    else if last
      "replacing #{last} with new #{cell.tag} <#{@__name} #{head}>"
    else
      "initializing #{cell.tag} <#{@__name} #{head}>"

    builtin = @ cell, head
    if compatible
      builtin\setup last
    else
      builtin\setup nil

    builtin\eval scope, cell\tail!

  __tostring: => "<#{@@__name}[#{@tag}] #{@head}>"
  __inherited: (cls) => cls.__base.__tostring = @__tostring

{
  :Builtin
}