blob: dcf600a4e0a9cf9e14e496e278953b69260d9046 (
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
|
class Op
-- common
new: =>
-- (...) => @setup ...
get: => @value
getc: =>
L\warn "stream #{@} cast to constant"
@value
-- Value interface
update: =>
destroy: =>
-- static
__tostring: => "<op: #{@@__name}>"
__inherited: (cls) => cls.__base.__tostring = @__tostring
spawn: (Opdef, ...) ->
Opdef ...
class Action
-- common
new: (head, @tag) =>
@patch head
-- AST interface
-- * eval args
-- * perform scope effects
-- * patch nested exprs
-- * return runtime-tree value
eval: (scope, tail) => error "not implemented"
-- free resources
destroy: =>
-- update this instance for :eavl() with new head
-- if :patch() returns false, this instance is :destroy'ed and recreated instead
-- must *not* return false when called after :new()
-- only considered if Action types match
patch: (head) =>
if head == @head
true
@head = head
-- static
@get_or_create: (ActionType, head, tag) ->
last = tag\last!
compatible = last and
(last.__class == ActionType) and
(last\patch head) and
last
L\trace if compatible
"reusing #{last} for #{tag} <#{ActionType.__name} #{head}>"
else if last
"replacing #{last} with new #{tag} <#{ActionType.__name} #{head}>"
else
"initializing #{tag} <#{ActionType.__name} #{head}>"
if compatible
tag\keep compatible
compatible
else
last\destroy! if last
with next = ActionType head, tag
tag\replace next
__tostring: => "<#{@@__name} #{@head}>"
__inherited: (cls) => cls.__base.__tostring = @__tostring
class FnDef
new: (@params, @body, @scope) =>
__tostring: =>
table.concat [p\stringify! for p in *@params], ' '
:Op, :Action, :FnDef
|