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
}
|