-
Notifications
You must be signed in to change notification settings - Fork 0
/
variables.daul
114 lines (89 loc) · 2.53 KB
/
variables.daul
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// check variables: error if they do not exist or if they are declared as val
val err = require("out.error")
val traverse = require("pass.traverse")
val find = \globals, scopes, name -> {
if (globals[name])
return "global"
for (i=#scopes,1,-1)
if (scopes[i][name])
return scopes[i][name]
false
};
\ir, globals, reporter -> traverse([
"init": \[
"globals": globals,
"reporter": reporter,
"scopes": [[]]
],
"function": \ir, recurse, edit, state -> {
val scope = []
state.scopes[#state.scopes+1] = scope
for (k,v : pairs(ir[2]))
scope[v] = true
recurse(ir, 3)
state.scopes[#state.scopes] = nil;
},
"for": \ir, recurse, edit, state -> {
recurse(ir, 3)
recurse(ir, 4)
if (ir[5]) recurse(ir, 5)
state.scopes[#state.scopes+1] = [ir[2][3]: true];
recurse(ir, 6)
state.scopes[#state.scopes] = nil;
},
"forin": \ir, recurse, edit, state -> {
recurse(ir, 3)
val scope = []
state.scopes[#state.scopes+1] = scope
for (k,v : pairs(ir[2]))
scope[v[3]] = true
recurse(ir, 4)
state.scopes[#state.scopes] = nil;
},
"block": \ir, recurse, edit, state -> {
state.scopes[#state.scopes+1] = [];
for (i=2,#ir) recurse(ir, i);
state.scopes[#state.scopes] = nil;
},
"const": \ir, recurse, edit, state -> {
recurse(ir, 2)
state.scopes[#state.scopes][ir[2][2][1]] = "const"
edit(ir[2]);
},
"local": \ir, recurse, edit, state -> {
// special path for functions to allow recursion without the "var x=nil;x=" hack
if (#ir == 3 and ir[3][1] == "function") {
state.scopes[#state.scopes][ir[2][1]] = true
recurse(ir, 3)
edit(["block",
["local", ir[2]],
["assign", ["name", ir[2][1]], ir[3]]])
} else {
for (i=3,#ir) recurse(ir, i);
state.scopes[#state.scopes][ir[2][1]] = true
};
},
"name": \ir, recurse, edit, state -> {
if (ir[2] != "_G") {
val name = ir[2]
if (!find(state.globals, state.scopes, name))
state.reporter(ir[0][0], ir[0][1], nil, "Variable '", name, "' does not exist")
};
},
"assign": \ir, recurse, edit, state -> {
recurse(ir, 2)
recurse(ir, 3)
if (ir[2][1] == "name") {
val tok = ir[2][0]
val name = ir[2][2]
val v = find(state.globals, state.scopes, name)
// TODO: highlight assignment
if (!v)
state.reporter(tok[0], tok[1], nil, "Variable '", name, "' does not exist")
if (v == "global")
state.reporter(tok[0], tok[1], nil, "Variable '", name, "' is a global (assumed constant)")
if (v == "const")
state.reporter(tok[0], tok[1], nil, "Variable '", name, "' was declared as constant (val)")
};
}
])(ir)