aboutsummaryrefslogtreecommitdiffstats
path: root/scope.moon
blob: bba2db46544bad56c8314546494f456bb1fe5dc1 (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
import Const, Op from require 'base'

ancestor = (klass) ->
  assert klass, "cant find the ancestor of nil"
  while klass.__parent
    klass = klass.__parent
  klass

local Scope

constify = (val, key) ->
  typ = switch type val
    when 'number'
      'num'
    when 'string'
      'str'
    when 'table'
      if base = rawget val, '__base'
        -- a class
        switch ancestor val
          when Op
            'opdef'
          else
            error "#{key}: cannot constify klass '#{val.__name}'"
      elseif klass = val.__class
        -- an instance
        switch ancestor klass
          when Op
            'op'
          when Scope
            'scope'
          when Const
            return val
          else
            error "#{key}: cannot constify '#{klass.__name}' instance"
      else
        return Const 'scope', Scope.from_table val
    else
      error "#{key}: cannot constify Lua type '#{type val}'"

  Const typ, val

class Scope
  new: (@node, @parent) =>
    @values = {}

  log: (msg) => -- print msg .. " in #{@}"

  set_raw: (key, val) => @values[key] = constify val, key
  set: (key, val) =>
    @log "setting #{key} = #{val}"
    @values[key] = val

  get: (key, prefix='') =>
    @log "checking for #{key}"
    if val = @values[key]
      @log "found #{val}"
      return val

    start, rest = key\match '^(.-)/(.*)'

    if not start
      return @parent and @parent\get key

    scope = @get start
    assert scope and scope.type == 'scope', "cant find '#{prefix}#{start}' for '#{prefix}#{key}'"
    scope\getc!\get rest, "#{prefix}#{start}/"

  use: (other) =>
    for k, v in pairs other.values
      @values[k] = v

  from_table: (tbl) ->
    with Scope!
      .values = { k, constify v, k for k,v in pairs tbl }

  __tostring: =>
    buf = "<Scope"
    buf ..= "@#{@node}" if @node

    depth = -1
    parent = @parent
    while parent
      depth += 1
      parent = parent.parent
    buf ..= " ^#{depth}" if depth != 0

    buf ..= " [#{table.concat [key for key in pairs @values], ', '}]"

    buf ..= ">"
    buf


{
  :Scope
}