forked from ceu-lang/ceu
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtmps.lua
More file actions
164 lines (142 loc) · 4.69 KB
/
Copy pathtmps.lua
File metadata and controls
164 lines (142 loc) · 4.69 KB
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
local VARS = {}
if not _ANA then
return -- isTmp=false for all vars
end
F = {
Dcl_var_pre = function (me)
local var = me.var
if var.pre~='var' or var.cls or var.inTop then
return -- only normal vars can be tmp
end
VARS[var] = true
var.isTmp = true
end,
Var = function (me)
local var = me.var
if _AST.iter'Thread'() then
return -- all threads vars are "tmp"
end
if _AST.iter'Dcl_fun'() then
return -- all function vars are "tmp"
end
if var.pre~='var' or var.cls then
var.isTmp = false
return -- only normal vars can be tmp
end
--[[
-- var int i;
-- var T[2] t with
-- i = i + 1; // "i" cannot be tmp
-- end;
--]]
local constr = _AST.par(me, 'Dcl_constr')
if constr and (var.blk.__depth < constr.__depth) then
local org = _AST.par(me, 'Dcl_var')
if org then
local _, _, arr = unpack(org)
if arr then
var.isTmp = false
end
end
end
local glb = _ENV.clss.Global
if var.inTop or
(var.blk==_ENV.clss.Main.blk_ifc and glb and glb.is_ifc and
glb.blk_ifc.vars[var.id])
then
var.isTmp = false
return -- vars in interfaces cannot be tmp
end
local dcl = _AST.iter'Dcl_var'()
if dcl and dcl[1]==var.id then
return -- my declaration is not an access
end
if me.__par.tag == 'SetBlock' then
return -- set is performed on respective `return´
end
local v = VARS[var]
local op = _AST.iter'Op1_&'()
local isRef = op and (op.ref == me)
if _AST.iter'Finally'() or -- finally executes through "call"
_AST.iter'AwaitInt'() or -- await ptr:a (ptr is tested on awake)
isRef or -- reference may escape
var.arr -- array may escape: TODO conservative
-- (arrays as parameters)
then
var.isTmp = false
VARS[var] = nil
return
end
if v == true then
VARS[var] = me.ana.pre
return -- first access
end
if not (v and _ANA.CMP(v,me.ana.pre)) then
var.isTmp = false -- found a Par or Await in the path
return
end
end,
EmitInt = function (me)
VARS = {} -- NO: run in different ceu_call
end,
New = function (me)
VARS = {} -- NO: start organism
end,
Spawn = 'New',
Loop_pre = function (me)
local awaits = false
_AST.visit(
{
AwaitT = function (me)
awaits = true
end,
AwaitInt = 'AwaitT',
AwaitExt = 'AwaitT',
AwaitN = 'AwaitT',
AwaitS = 'AwaitT',
EmitInt = 'AwaitT',
Async = 'AwaitT',
Thread = 'AwaitT',
New = 'AwaitT',
Spawn = 'AwaitT',
},
me)
if ((not awaits) and (not _AST.iter(_AST.pred_async)())) or
me.isAwaitUntil then
return -- OK: (tight loop outside Async) or (await ... until)
end
VARS = {} -- NO: loop in between Dcl/Accs is dangerous
--[[
-- x is on the stack but may be written in two diff reactions
-- a non-ceu code can reuse the stack in between
input int E;
var int x;
loop do
var int tmp = await E;
if tmp == 0 then
break;
end
x = tmp;
end
return x;
]]
end,
--[[
]]
ParOr_pre = function (me)
for var, v in pairs(VARS) do
if v ~= true then
VARS[var] = nil -- remove previously accessed vars
end
end
end,
ParAnd_pre = 'ParOr_pre',
ParEver_pre = 'ParOr_pre',
ParOr = 'ParOr_pre',
ParAnd = 'ParOr_pre',
ParEver = 'ParOr_pre',
-- TODO: should pre's be already different?
Async_pre = 'ParOr_pre',
Async = 'ParOr_pre',
}
_AST.visit(F)