summaryrefslogtreecommitdiff
path: root/script/vm/tracer.lua
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2022-12-15 21:09:14 +0800
committer最萌小汐 <sumneko@hotmail.com>2022-12-15 21:09:14 +0800
commit6e2d3d42dba22ee9f179546b1e92d0b3313ec1f5 (patch)
tree3d32e12c94ca119167e84eb994d859d91c690785 /script/vm/tracer.lua
parenta744e3439e165be13f8f0ba5262b8f1efec0d86d (diff)
downloadlua-language-server-6e2d3d42dba22ee9f179546b1e92d0b3313ec1f5.zip
stash
Diffstat (limited to 'script/vm/tracer.lua')
-rw-r--r--script/vm/tracer.lua78
1 files changed, 71 insertions, 7 deletions
diff --git a/script/vm/tracer.lua b/script/vm/tracer.lua
index c2b7ae39..5b3b1b54 100644
--- a/script/vm/tracer.lua
+++ b/script/vm/tracer.lua
@@ -13,9 +13,11 @@ local util = require 'utility'
---@field assignMap table<parser.object, true>
---@field careMap table<parser.object, true>
---@field mark table<parser.object, true>
+---@field casts parser.object[]
---@field nodes table<parser.object, vm.node|false>
---@field main parser.object
---@field uri uri
+---@field castIndex integer?
local mt = {}
mt.__index = mt
@@ -79,25 +81,27 @@ function mt:collectLocal()
self.assigns[#self.assigns+1] = obj
self.assignMap[obj] = true
self:collectCare(obj)
+ if obj.finish > finishPos then
+ finishPos = obj.finish
+ end
end
if obj.type == 'getlocal' then
self:collectCare(obj)
+ if obj.finish > finishPos then
+ finishPos = obj.finish
+ end
end
end
local casts = self:getCasts()
for _, cast in ipairs(casts) do
if cast.loc[1] == self.source[1]
- and cast.start > startPos
+ and cast.start > startPos
and cast.finish < finishPos
and guide.getLocal(self.source, self.source[1], cast.start) == self.source then
- self.assigns[#self.assigns+1] = cast
+ self.casts[#self.casts+1] = cast
end
end
-
- table.sort(self.assigns, function (a, b)
- return a.start < b.start
- end)
end
---@param start integer
@@ -109,7 +113,7 @@ function mt:getLastAssign(start, finish)
if obj.start < start then
goto CONTINUE
end
- if obj.start >= finish then
+ if (obj.range or obj.start) >= finish then
break
end
local objBlock = guide.getParentBlock(obj)
@@ -125,6 +129,58 @@ function mt:getLastAssign(start, finish)
return assign
end
+---@param pos integer
+function mt:resetCastsIndex(pos)
+ for i = 1, #self.casts do
+ local cast = self.casts[i]
+ if cast.start > pos then
+ self.castIndex = i
+ return
+ end
+ end
+ self.castIndex = nil
+end
+
+---@param pos integer
+---@param node vm.node
+---@return vm.node
+function mt:fastWardCasts(pos, node)
+ if not self.castIndex then
+ return node
+ end
+ for i = self.castIndex, #self.casts do
+ local action = self.casts[i]
+ if action.start > pos then
+ return node
+ end
+ node = node:copy()
+ for _, cast in ipairs(action.casts) do
+ if cast.mode == '+' then
+ if cast.optional then
+ node:addOptional()
+ end
+ if cast.extends then
+ node:merge(vm.compileNode(cast.extends))
+ end
+ elseif cast.mode == '-' then
+ if cast.optional then
+ node:removeOptional()
+ end
+ if cast.extends then
+ node:removeNode(vm.compileNode(cast.extends))
+ end
+ else
+ if cast.extends then
+ node:clear()
+ node:merge(vm.compileNode(cast.extends))
+ end
+ end
+ end
+ end
+ self.castIndex = self.castIndex + 1
+ return node
+end
+
---@param action parser.object
---@param topNode vm.node
---@param outNode? vm.node
@@ -136,6 +192,7 @@ function mt:lookIntoChild(action, topNode, outNode)
return topNode, outNode or topNode
end
self.mark[action] = true
+ topNode = self:fastWardCasts(action.start, topNode)
if action.type == 'getlocal' then
if action.node == self.source then
self.nodes[action] = topNode
@@ -306,13 +363,18 @@ function mt:lookIntoChild(action, topNode, outNode)
or subBlock.hasBreak
or subBlock.hasError
if not neverReturn then
+ local ok
local lastAssign = self:getLastAssign(subBlock.start, subBlock.finish)
if lastAssign then
local node = self:getNode(lastAssign)
if node then
blockNodes[#blockNodes+1] = node
+ ok = true
end
end
+ if not ok then
+ blockNodes[#blockNodes+1] = blockNode
+ end
end
end
if not hasElse and not topNode:hasKnownType() then
@@ -367,6 +429,7 @@ end
---@param start integer
---@param node vm.node
function mt:lookIntoBlock(block, start, node)
+ self:resetCastsIndex(start)
for _, action in ipairs(block) do
if action.start < start then
goto CONTINUE
@@ -436,6 +499,7 @@ local function createTracer(source)
assignMap = {},
careMap = {},
mark = {},
+ casts = {},
nodes = {},
main = main,
uri = guide.getUri(source),