aboutsummaryrefslogtreecommitdiffstats
path: root/core/registry.moon
blob: fca7e5d0fc53f84af77d25ea2a921837ea0a4a4f (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
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
}