Skip to content

Commit e601608

Browse files
committed
stash
1 parent 1a7d721 commit e601608

File tree

1 file changed

+80
-48
lines changed

1 file changed

+80
-48
lines changed

script/vm/runner.lua

Lines changed: 80 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ local guide = require 'parser.guide'
66

77
---@class vm.runner
88
---@field _loc parser.object
9-
---@field _objs parser.object[]
9+
---@field _casts parser.object[]
1010
---@field _callback vm.runner.callback
1111
---@field _mark table
1212
---@field _has table<parser.object, true>
@@ -51,34 +51,60 @@ function mt:_collect()
5151
for _, ref in ipairs(self._loc.ref) do
5252
if ref.type == 'getlocal'
5353
or ref.type == 'setlocal' then
54-
self._objs[#self._objs+1] = ref
55-
if ref.start > finishPos then
56-
finishPos = ref.start
54+
self:_markHas(ref)
55+
if ref.finish > finishPos then
56+
finishPos = ref.finish
5757
end
5858
end
5959
end
6060

61-
if #self._objs == 0 then
62-
return
63-
end
64-
6561
local casts = self:_getCasts()
6662
for _, cast in ipairs(casts) do
6763
if cast.loc[1] == self._loc[1]
6864
and cast.start > startPos
6965
and cast.finish < finishPos
7066
and guide.getLocal(self._loc, self._loc[1], cast.start) == self._loc then
71-
self._objs[#self._objs+1] = cast
67+
self._casts[#self._casts+1] = cast
68+
self:_markHas(cast)
7269
end
7370
end
71+
end
7472

75-
table.sort(self._objs, function (a, b)
76-
return a.start < b.start
77-
end)
78-
79-
for _, obj in ipairs(self._objs) do
80-
self:_markHas(obj)
73+
---@param pos integer
74+
---@param topNode vm.node
75+
---@return vm.node
76+
function mt:_fastWardCasts(pos, topNode)
77+
for i = self._index, #self._casts do
78+
local action = self._casts[i]
79+
if action.start > pos then
80+
self._index = i
81+
return topNode
82+
end
83+
topNode = topNode:copy()
84+
for _, cast in ipairs(action.casts) do
85+
if cast.mode == '+' then
86+
if cast.optional then
87+
topNode:addOptional()
88+
end
89+
if cast.extends then
90+
topNode:merge(vm.compileNode(cast.extends))
91+
end
92+
elseif cast.mode == '-' then
93+
if cast.optional then
94+
topNode:removeOptional()
95+
end
96+
if cast.extends then
97+
topNode:removeNode(vm.compileNode(cast.extends))
98+
end
99+
else
100+
if cast.extends then
101+
topNode:clear()
102+
topNode:merge(vm.compileNode(cast.extends))
103+
end
104+
end
105+
end
81106
end
107+
return topNode
82108
end
83109

84110
---@param action parser.object
@@ -93,8 +119,13 @@ function mt:_lookIntoChild(action, topNode, outNode)
93119
end
94120
self._mark[action] = true
95121
if action.type == 'getlocal' then
96-
self._callback(action, topNode)
97-
topNode = topNode:copy():setTruthy()
122+
if action.node == self._loc then
123+
self._callback(action, topNode)
124+
if outNode then
125+
topNode = topNode:copy():setTruthy()
126+
outNode = outNode:copy():setFalsy()
127+
end
128+
end
98129
elseif action.type == 'function' then
99130
self:_lookIntoBlock(action, topNode:copy())
100131
elseif action.type == 'unary' then
@@ -110,8 +141,9 @@ function mt:_lookIntoChild(action, topNode, outNode)
110141
goto RETURN
111142
end
112143
if action.op.type == 'and' then
113-
topNode = self:_lookIntoChild(action[1], topNode)
114-
topNode = self:_lookIntoChild(action[2], topNode)
144+
local dummyNode = topNode:copy()
145+
topNode = self:_lookIntoChild(action[1], topNode, dummyNode)
146+
topNode = self:_lookIntoChild(action[2], topNode, dummyNode)
115147
elseif action.op.type == 'or' then
116148
outNode = outNode or topNode:copy()
117149
local topNode1, outNode1 = self:_lookIntoChild(action[1], topNode, outNode)
@@ -133,7 +165,7 @@ function mt:_lookIntoChild(action, topNode, outNode)
133165
if handler.type == 'getlocal'
134166
and handler.node == self._loc then
135167
-- if x == y then
136-
self:_lookIntoChild(handler, topNode:copy())
168+
topNode = self:_lookIntoChild(handler, topNode, outNode)
137169
local checkerNode = vm.compileNode(checker)
138170
if action.op.type == '==' then
139171
topNode = checkerNode
@@ -202,9 +234,12 @@ function mt:_lookIntoChild(action, topNode, outNode)
202234
or action.type == 'for' then
203235
topNode = self:_lookIntoBlock(action, topNode:copy())
204236
elseif action.type == 'while' then
205-
local blockNode, mainNode = self:_lookIntoChild(action.filter, topNode:copy(), topNode:copy())
237+
local blockNode, mainNode
206238
if action.filter then
207-
self:_lookIntoChild(action.filter, topNode)
239+
blockNode, mainNode = self:_lookIntoChild(action.filter, topNode:copy(), topNode:copy())
240+
else
241+
blockNode = topNode:copy()
242+
mainNode = topNode:copy()
208243
end
209244
blockNode = self:_lookIntoBlock(action, blockNode:copy())
210245
if mainNode then
@@ -240,36 +275,34 @@ function mt:_lookIntoChild(action, topNode, outNode)
240275
topNode = mainNode
241276
elseif action.type == 'call' then
242277
if action.node.special == 'assert' and action.args and action.args[1] then
243-
topNode = self:_lookIntoChild(action.args[1], topNode)
278+
topNode = self:_lookIntoChild(action.args[1], topNode, topNode:copy())
244279
end
280+
elseif action.type == 'paren' then
281+
topNode, outNode = self:_lookIntoChild(action.exp, topNode, outNode)
245282
elseif action.type == 'setlocal' then
246283
if action.node == self._loc then
247284
if action.value then
248285
self:_lookIntoChild(action.value, topNode)
249286
end
250287
topNode = self._callback(action)
251288
end
252-
elseif action.type == 'doc.cast' then
253-
topNode = topNode:copy()
254-
for _, cast in ipairs(action.casts) do
255-
if cast.mode == '+' then
256-
if cast.optional then
257-
topNode:addOptional()
258-
end
259-
if cast.extends then
260-
topNode:merge(vm.compileNode(cast.extends))
261-
end
262-
elseif cast.mode == '-' then
263-
if cast.optional then
264-
topNode:removeOptional()
265-
end
266-
if cast.extends then
267-
topNode:removeNode(vm.compileNode(cast.extends))
268-
end
269-
else
270-
if cast.extends then
271-
topNode:clear()
272-
topNode:merge(vm.compileNode(cast.extends))
289+
elseif action.type == 'local' then
290+
if action.value
291+
and action.value.type == 'select' then
292+
local index = action.value.sindex
293+
local call = action.value.vararg
294+
if index == 1
295+
and call.type == 'call'
296+
and call.node
297+
and call.node.special == 'type'
298+
and call.args then
299+
local getLoc = call.args[1]
300+
if getLoc
301+
and getLoc.type == 'getlocal'
302+
and getLoc.node == self._loc then
303+
for _, ref in ipairs(action.ref) do
304+
self:_markHas(ref)
305+
end
273306
end
274307
end
275308
end
@@ -292,9 +325,11 @@ function mt:_lookIntoBlock(block, topNode)
292325
end
293326
for _, action in ipairs(block) do
294327
if self._has[action] then
328+
topNode = self:_fastWardCasts(action.start, topNode)
295329
topNode = self:_lookIntoChild(action, topNode)
296330
end
297331
end
332+
topNode = self:_fastWardCasts(block.finish, topNode)
298333
return topNode
299334
end
300335

@@ -307,7 +342,7 @@ function vm.launchRunner(loc, callback)
307342
end
308343
local self = setmetatable({
309344
_loc = loc,
310-
_objs = {},
345+
_casts = {},
311346
_mark = {},
312347
_has = {},
313348
_main = main,
@@ -316,8 +351,5 @@ function vm.launchRunner(loc, callback)
316351

317352
self:_collect()
318353

319-
if #self._objs == 0 then
320-
return
321-
end
322354
self:_lookIntoBlock(main, vm.getNode(loc):copy())
323355
end

0 commit comments

Comments
 (0)