Skip to content

Commit f835c0a

Browse files
committed
Merge branch 'fix-3.4.0'
2 parents 7c315e9 + 09b57f6 commit f835c0a

File tree

2 files changed

+156
-129
lines changed

2 files changed

+156
-129
lines changed

script/vm/runner.lua

Lines changed: 145 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ function mt:_collect()
5757
end
5858

5959
table.sort(self._objs, function (a, b)
60-
return (a.range or a.start) < (b.range or b.start)
60+
return a.start < b.start
6161
end)
6262
end
6363

@@ -69,17 +69,12 @@ end
6969
function mt:_fastWard(pos, node)
7070
for i = self._index, #self._objs do
7171
local obj = self._objs[i]
72-
if (obj.range or obj.finish) > pos then
72+
if obj.finish > pos then
7373
self._index = i
7474
return node, obj
7575
end
7676
if obj.type == 'getlocal' then
7777
self._callback(obj, node)
78-
elseif obj.type == 'setlocal' then
79-
local newNode = self._callback(obj, node)
80-
if newNode then
81-
node = newNode:copy()
82-
end
8378
elseif obj.type == 'doc.cast' then
8479
node = node:copy()
8580
for _, cast in ipairs(obj.casts) do
@@ -110,126 +105,64 @@ function mt:_fastWard(pos, node)
110105
return node, nil
111106
end
112107

113-
---@param action parser.object
108+
---@param exp parser.object
114109
---@param topNode vm.node
115110
---@param outNode? vm.node
116111
---@return vm.node topNode
117112
---@return vm.node outNode
118-
function mt:_lookInto(action, topNode, outNode)
119-
if not action then
113+
function mt:_lookIntoExp(exp, topNode, outNode)
114+
if not exp then
120115
return topNode, outNode or topNode
121116
end
122-
if self._mark[action] then
117+
if self._mark[exp] then
123118
return topNode, outNode or topNode
124119
end
125-
self._mark[action] = true
120+
self._mark[exp] = true
126121
local top = self._objs[self._index]
127122
if not top then
128123
return topNode, outNode or topNode
129124
end
130-
if not guide.isInRange(action, top.finish)
131-
-- trick for `local tp = type(x);if tp == 'string' then`
132-
and action.type ~= 'binary' then
133-
return topNode, outNode or topNode
134-
end
135-
local set
136-
local value = vm.getObjectValue(action)
137-
if value then
138-
set = action
139-
action = value
140-
end
141-
if action.type == 'function' then
142-
self:_launchBlock(action, topNode:copy())
143-
elseif action.type == 'loop'
144-
or action.type == 'in'
145-
or action.type == 'repeat'
146-
or action.type == 'for' then
147-
topNode = self:_launchBlock(action, topNode:copy())
148-
elseif action.type == 'while' then
149-
local blockNode, mainNode = self:_lookInto(action.filter, topNode:copy(), topNode:copy())
150-
if action.filter then
151-
self:_fastWard(action.filter.finish, blockNode)
152-
end
153-
blockNode = self:_launchBlock(action, blockNode:copy())
154-
if mainNode then
155-
topNode = mainNode:merge(blockNode)
156-
end
157-
elseif action.type == 'if' then
158-
local hasElse
159-
local mainNode = topNode:copy()
160-
local blockNodes = {}
161-
for _, subBlock in ipairs(action) do
162-
local blockNode = mainNode:copy()
163-
if subBlock.filter then
164-
blockNode, mainNode = self:_lookInto(subBlock.filter, blockNode, mainNode)
165-
self:_fastWard(subBlock.filter.finish, blockNode)
166-
else
167-
hasElse = true
168-
mainNode:clear()
169-
end
170-
blockNode = self:_launchBlock(subBlock, blockNode:copy())
171-
local neverReturn = subBlock.hasReturn
172-
or subBlock.hasGoTo
173-
or subBlock.hasBreak
174-
or subBlock.hasError
175-
if not neverReturn then
176-
blockNodes[#blockNodes+1] = blockNode
177-
end
178-
end
179-
if not hasElse and not topNode:hasKnownType() then
180-
mainNode:merge(vm.declareGlobal('type', 'unknown'))
181-
end
182-
for _, blockNode in ipairs(blockNodes) do
183-
mainNode:merge(blockNode)
184-
end
185-
topNode = mainNode
186-
elseif action.type == 'getlocal' then
187-
if action.node == self._loc then
188-
topNode = self:_fastWard(action.finish, topNode)
189-
topNode = topNode:copy():setTruthy()
190-
if outNode then
191-
outNode:setFalsy()
192-
end
193-
end
194-
elseif action.type == 'unary' then
195-
if not action[1] then
125+
if exp.type == 'function' then
126+
self:_launchBlock(exp, topNode:copy())
127+
elseif exp.type == 'unary' then
128+
if not exp[1] then
196129
goto RETURN
197130
end
198-
if action.op.type == 'not' then
131+
if exp.op.type == 'not' then
199132
outNode = outNode or topNode:copy()
200-
outNode, topNode = self:_lookInto(action[1], topNode, outNode)
133+
outNode, topNode = self:_lookIntoExp(exp[1], topNode, outNode)
201134
end
202-
elseif action.type == 'binary' then
203-
if not action[1] or not action[2] then
135+
elseif exp.type == 'binary' then
136+
if not exp[1] or not exp[2] then
204137
goto RETURN
205138
end
206-
if action.op.type == 'and' then
207-
topNode = self:_lookInto(action[1], topNode)
208-
topNode = self:_lookInto(action[2], topNode)
209-
elseif action.op.type == 'or' then
139+
if exp.op.type == 'and' then
140+
topNode = self:_lookIntoExp(exp[1], topNode)
141+
topNode = self:_lookIntoExp(exp[2], topNode)
142+
elseif exp.op.type == 'or' then
210143
outNode = outNode or topNode:copy()
211-
local topNode1, outNode1 = self:_lookInto(action[1], topNode, outNode)
212-
local topNode2, outNode2 = self:_lookInto(action[2], outNode1, outNode1:copy())
144+
local topNode1, outNode1 = self:_lookIntoExp(exp[1], topNode, outNode)
145+
local topNode2, outNode2 = self:_lookIntoExp(exp[2], outNode1, outNode1:copy())
213146
topNode = vm.createNode(topNode1, topNode2)
214147
outNode = outNode2:copy()
215-
elseif action.op.type == '=='
216-
or action.op.type == '~=' then
217-
local exp, checker
148+
elseif exp.op.type == '=='
149+
or exp.op.type == '~=' then
150+
local handler, checker
218151
for i = 1, 2 do
219-
if guide.isLiteral(action[i]) then
220-
checker = action[i]
221-
exp = action[3-i] -- Copilot tells me use `3-i` instead of `i%2+1`
152+
if guide.isLiteral(exp[i]) then
153+
checker = exp[i]
154+
handler = exp[3-i] -- Copilot tells me use `3-i` instead of `i%2+1`
222155
end
223156
end
224-
if not exp then
157+
if not handler then
225158
goto RETURN
226159
end
227-
if exp.type == 'getlocal'
228-
and exp.node == self._loc then
160+
if handler.type == 'getlocal'
161+
and handler.node == self._loc then
229162
-- if x == y then
230163
self:_fastWard(exp.finish, topNode:copy())
231164
local checkerNode = vm.compileNode(checker)
232-
if action.op.type == '==' then
165+
if exp.op.type == '==' then
233166
topNode = checkerNode
234167
if outNode then
235168
outNode:removeNode(topNode)
@@ -240,16 +173,16 @@ function mt:_lookInto(action, topNode, outNode)
240173
outNode = checkerNode
241174
end
242175
end
243-
elseif exp.type == 'call'
176+
elseif handler.type == 'call'
244177
and checker.type == 'string'
245-
and exp.node.special == 'type'
246-
and exp.args
247-
and exp.args[1]
248-
and exp.args[1].type == 'getlocal'
249-
and exp.args[1].node == self._loc then
178+
and handler.node.special == 'type'
179+
and handler.args
180+
and handler.args[1]
181+
and handler.args[1].type == 'getlocal'
182+
and handler.args[1].node == self._loc then
250183
-- if type(x) == 'string' then
251184
self:_fastWard(exp.finish, topNode:copy())
252-
if action.op.type == '==' then
185+
if exp.op.type == '==' then
253186
topNode:narrow(checker[1])
254187
if outNode then
255188
outNode:remove(checker[1])
@@ -260,9 +193,9 @@ function mt:_lookInto(action, topNode, outNode)
260193
outNode:narrow(checker[1])
261194
end
262195
end
263-
elseif exp.type == 'getlocal'
196+
elseif handler.type == 'getlocal'
264197
and checker.type == 'string' then
265-
local nodeValue = vm.getObjectValue(exp.node)
198+
local nodeValue = vm.getObjectValue(handler.node)
266199
if nodeValue
267200
and nodeValue.type == 'select'
268201
and nodeValue.sindex == 1 then
@@ -275,7 +208,7 @@ function mt:_lookInto(action, topNode, outNode)
275208
and call.args[1].type == 'getlocal'
276209
and call.args[1].node == self._loc then
277210
-- `local tp = type(x);if tp == 'string' then`
278-
if action.op.type == '==' then
211+
if exp.op.type == '==' then
279212
topNode:narrow(checker[1])
280213
if outNode then
281214
outNode:remove(checker[1])
@@ -290,33 +223,117 @@ function mt:_lookInto(action, topNode, outNode)
290223
end
291224
end
292225
end
226+
elseif exp.type == 'getlocal' then
227+
if exp.node == self._loc then
228+
topNode = self:_fastWard(exp.finish, topNode)
229+
topNode = topNode:copy():setTruthy()
230+
if outNode then
231+
outNode:setFalsy()
232+
end
233+
end
234+
elseif exp.type == 'paren' then
235+
topNode, outNode = self:_lookIntoExp(exp.exp, topNode, outNode)
236+
elseif exp.type == 'getindex' then
237+
self:_lookIntoExp(exp.index, topNode)
238+
elseif exp.type == 'table' then
239+
for _, field in ipairs(exp) do
240+
self:_lookIntoAction(field, topNode)
241+
end
242+
end
243+
::RETURN::
244+
topNode = self:_fastWard(exp.finish, topNode)
245+
return topNode, outNode or topNode
246+
end
247+
248+
---@param action parser.object
249+
---@param topNode vm.node
250+
---@return vm.node topNode
251+
function mt:_lookIntoAction(action, topNode)
252+
if not action then
253+
return topNode
254+
end
255+
if self._mark[action] then
256+
return topNode
257+
end
258+
self._mark[action] = true
259+
local top = self._objs[self._index]
260+
if not top then
261+
return topNode
262+
end
263+
if not guide.isInRange(action, top.finish)
264+
-- trick for `local tp = type(x);if tp == 'string' then`
265+
and action.type ~= 'binary' then
266+
return topNode
267+
end
268+
local value = vm.getObjectValue(action)
269+
if value then
270+
self:_lookIntoExp(value, topNode:copy())
271+
end
272+
if action.type == 'setlocal' then
273+
local newTopNode = self._callback(action, topNode)
274+
if newTopNode then
275+
topNode = newTopNode
276+
end
277+
elseif action.type == 'function' then
278+
self:_launchBlock(action, topNode:copy())
279+
elseif action.type == 'loop'
280+
or action.type == 'in'
281+
or action.type == 'repeat'
282+
or action.type == 'for' then
283+
topNode = self:_launchBlock(action, topNode:copy())
284+
elseif action.type == 'while' then
285+
local blockNode, mainNode = self:_lookIntoExp(action.filter, topNode:copy(), topNode:copy())
286+
if action.filter then
287+
self:_fastWard(action.filter.finish, blockNode)
288+
end
289+
blockNode = self:_launchBlock(action, blockNode:copy())
290+
if mainNode then
291+
topNode = mainNode:merge(blockNode)
292+
end
293+
elseif action.type == 'if' then
294+
local hasElse
295+
local mainNode = topNode:copy()
296+
local blockNodes = {}
297+
for _, subBlock in ipairs(action) do
298+
local blockNode = mainNode:copy()
299+
if subBlock.filter then
300+
blockNode, mainNode = self:_lookIntoExp(subBlock.filter, blockNode, mainNode)
301+
self:_fastWard(subBlock.filter.finish, blockNode)
302+
else
303+
hasElse = true
304+
mainNode:clear()
305+
end
306+
blockNode = self:_launchBlock(subBlock, blockNode:copy())
307+
local neverReturn = subBlock.hasReturn
308+
or subBlock.hasGoTo
309+
or subBlock.hasBreak
310+
or subBlock.hasError
311+
if not neverReturn then
312+
blockNodes[#blockNodes+1] = blockNode
313+
end
314+
end
315+
if not hasElse and not topNode:hasKnownType() then
316+
mainNode:merge(vm.declareGlobal('type', 'unknown'))
317+
end
318+
for _, blockNode in ipairs(blockNodes) do
319+
mainNode:merge(blockNode)
320+
end
321+
topNode = mainNode
293322
elseif action.type == 'call' then
294323
if action.node.special == 'assert' and action.args and action.args[1] then
295-
topNode = self:_lookInto(action.args[1], topNode)
324+
topNode = self:_lookIntoExp(action.args[1], topNode)
296325
elseif action.args then
297326
for _, arg in ipairs(action.args) do
298-
self:_lookInto(arg, topNode)
327+
self:_lookIntoExp(arg, topNode)
299328
end
300329
end
301-
elseif action.type == 'paren' then
302-
topNode, outNode = self:_lookInto(action.exp, topNode, outNode)
303330
elseif action.type == 'return' then
304331
for _, rtn in ipairs(action) do
305-
self:_lookInto(rtn, topNode)
306-
end
307-
elseif action.type == 'getindex' then
308-
self:_lookInto(action.index, topNode)
309-
elseif action.type == 'table' then
310-
for _, field in ipairs(action) do
311-
self:_lookInto(field, topNode)
332+
self:_lookIntoExp(rtn, topNode)
312333
end
313334
end
314-
::RETURN::
315335
topNode = self:_fastWard(action.finish, topNode)
316-
if set then
317-
topNode = self:_fastWard(set.range or set.finish, topNode)
318-
end
319-
return topNode, outNode or topNode
336+
return topNode
320337
end
321338

322339
---@param block parser.object
@@ -328,18 +345,17 @@ function mt:_launchBlock(block, node)
328345
return topNode
329346
end
330347
for _, action in ipairs(block) do
331-
if (action.range or action.finish) < (top.range or top.finish) then
348+
if (action.range or action.finish) < top.finish then
332349
goto CONTINUE
333350
end
334-
topNode = self:_lookInto(action, topNode)
335-
topNode, top = self:_fastWard(action.range or action.finish, topNode)
351+
topNode = self:_lookIntoAction(action, topNode)
352+
topNode, top = self:_fastWard(action.finish, topNode)
336353
if not top then
337354
return topNode
338355
end
339356
::CONTINUE::
340357
end
341-
-- `x = function () end`: don't touch `x` in the end of function
342-
topNode = self:_fastWard(block.finish - 1, topNode)
358+
topNode = self:_fastWard(block.finish, topNode)
343359
return topNode
344360
end
345361

0 commit comments

Comments
 (0)