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
|
import Value from require 'core.value'
import Result from require 'core.result'
class Registry
new: () =>
@map = {}
@io = {}
@tick = 0
@kr = Result value: Value.bool true
-- methods for Tag
last: (index) => @last_map[index]
replace: (index, expr, ignore_dup=false) =>
L\trace "reg: setting #{index} to #{expr}"
assert not @map[index] or ignore_dup, "duplicate tags with index #{index}!"
@map[index] = expr
init: (tag, expr) =>
L\trace "reg: init pending to #{expr}"
table.insert @pending, { :tag, :expr }
active: -> assert Registry.active_registry, "no active Registry!"
-- public methods
wrap_eval: (fn) => (...) ->
@grab!
@last_map, @map, @pending = @map, {}, {}
with fn ...
for tag, val in pairs @last_map
if not @map[tag]
val\destroy!
for { :tag, :expr } in *@pending
-- tag was solved by another pending registration
-- (e.g. first [A] is solved, then [5.A] is solved)
continue if tag\index!
next_tag = @next_tag!
L\trace "assigned new tag #{next_tag} to #{tag} #{expr}"
tag\set next_tag
@map[tag\index!] = expr
@release!
wrap_tick: (fn) => (...) ->
@grab!
@tick += 1
@kr.value\set true
for io in pairs @io
io\tick!
with fn ...
@release!
grab: =>
assert not @prev, "already have a previous registry? #{@prev}"
@prev, @@active_registry = @@active_registry, @
release: =>
assert @ == @@active_registry, "not the active registry!"
@@active_registry, @prev = @prev, nil
next_tag: => #@map + 1
class SimpleRegistry extends Registry
new: =>
@cnt = 1
init: (tag, expr) =>
tag\set @cnt
@cnt += 1
last: (index) =>
replace: (index, expr) =>
{
:Registry
:SimpleRegistry
}
|