summaryrefslogtreecommitdiff
path: root/script
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2022-04-14 15:04:16 +0800
committer最萌小汐 <sumneko@hotmail.com>2022-04-14 15:04:16 +0800
commitbae265094084e3b1887b92402de0cf2be14abb5d (patch)
tree842ee6ba352885a0a4478dfb52922580dc0e2367 /script
parent73a4780aa866737851040239eee52a013b5401d0 (diff)
downloadlua-language-server-bae265094084e3b1887b92402de0cf2be14abb5d.zip
update
Diffstat (limited to 'script')
-rw-r--r--script/vm/compiler.lua41
-rw-r--r--script/vm/node.lua117
-rw-r--r--script/vm/sign.lua14
3 files changed, 117 insertions, 55 deletions
diff --git a/script/vm/compiler.lua b/script/vm/compiler.lua
index 8ad26f63..ed8db18a 100644
--- a/script/vm/compiler.lua
+++ b/script/vm/compiler.lua
@@ -612,7 +612,7 @@ local function compileCallArgNode(arg, call, callNode, fixIndex, myIndex)
local myEvent
if n.args[eventIndex] then
local argNode = vm.compileNode(n.args[eventIndex])
- myEvent = argNode[1]
+ myEvent = argNode:get(1)
end
if not myEvent
or not eventMap
@@ -633,7 +633,7 @@ local function compileCallArgNode(arg, call, callNode, fixIndex, myIndex)
end
---@param arg parser.object
----@param call parser.position
+---@param call parser.object
---@param index? integer
function vm.compileCallArg(arg, call, index)
if not index then
@@ -738,7 +738,6 @@ local compilerSwitch = util.switch()
if not source.value
and source.ref
and not hasMarkDoc then
- vm.pauseCache()
for _, ref in ipairs(source.ref) do
if ref.type == 'setlocal' and ref.value then
if ref.value.type == 'table' then
@@ -748,7 +747,6 @@ local compilerSwitch = util.switch()
end
end
end
- vm.resumeCache()
end
-- function x.y(self, ...) --> function x:y(...)
if source[1] == 'self'
@@ -792,7 +790,7 @@ local compilerSwitch = util.switch()
: case 'setlocal'
: case 'getlocal'
: call(function (source)
- vm.setNode(source, vm.compileNode(source.node), true)
+ vm.setNode(source, vm.compileNode(source.node))
end)
: case 'setfield'
: case 'setmethod'
@@ -1522,26 +1520,6 @@ local function compileByGlobal(uri, source)
end
end
-local pauseCacheCount = 0
-local originCacheKeys = {}
-local originCacheValues = {}
-function vm.pauseCache()
- pauseCacheCount = pauseCacheCount + 1
-end
-
-function vm.resumeCache()
- pauseCacheCount = pauseCacheCount - 1
- if pauseCacheCount == 0 then
- for source in pairs(originCacheKeys) do
- if originCacheValues[source] then
- vm.setNode(source, originCacheValues[source], true)
- end
- originCacheKeys[source] = nil
- originCacheValues[source] = nil
- end
- end
-end
-
---@param source vm.object
---@param uri? uri
---@return vm.node
@@ -1554,15 +1532,12 @@ function vm.compileNode(source, uri)
return cache
end
- local pauseCache = pauseCacheCount > 0
- if pauseCache and not originCacheKeys[source] then
- originCacheKeys[source] = true
- originCacheValues[source] = cache
- end
-
- vm.setNode(source, vm.createNode(), true)
+ local node = vm.createNode()
+ vm.setNode(source, node, true)
compileByGlobal(uri, source)
compileByNode(source)
- return vm.getNode(source)
+ node = vm.getNode(source)
+
+ return node
end
diff --git a/script/vm/node.lua b/script/vm/node.lua
index 941f2b09..1486ac47 100644
--- a/script/vm/node.lua
+++ b/script/vm/node.lua
@@ -8,10 +8,13 @@ vm.nodeCache = {}
---@class vm.node
local mt = {}
-mt.__index = mt
-mt.type = 'vm.node'
-mt.optional = nil
-mt.lastInfer = nil
+mt.__index = mt
+mt.type = 'vm.node'
+mt.optional = nil
+mt.lastInfer = nil
+---@type vm.node[]
+mt._childs = nil
+mt._locked = false
---@param node vm.node | vm.object
function mt:merge(node)
@@ -19,15 +22,28 @@ function mt:merge(node)
return
end
if node.type == 'vm.node' then
- for _, c in ipairs(node) do
- if not self[c] then
- self[c] = true
- self[#self+1] = c
- end
+ if node == self then
+ return
end
if node:isOptional() then
self.optional = true
end
+ if node._locked then
+ if not self._childs then
+ self._childs = {}
+ end
+ if not self._childs[node] then
+ self._childs[#self._childs+1] = node
+ self._childs[node] = true
+ end
+ else
+ for _, obj in ipairs(node) do
+ if not self[obj] then
+ self[obj] = true
+ self[#self+1] = obj
+ end
+ end
+ end
else
if not self[node] then
self[node] = true
@@ -36,16 +52,84 @@ function mt:merge(node)
end
end
----@return vm.node
-function mt:copy()
- return vm.createNode(self)
+function mt:_each(mark, callback)
+ if mark[self] then
+ return
+ end
+ mark[self] = true
+ for i = 1, #self do
+ callback(self[i])
+ end
+ local childs = self._childs
+ if not childs then
+ return
+ end
+ for i = 1, #childs do
+ local child = childs[i]
+ if not child:isLocked() then
+ child:_each(mark, callback)
+ end
+ end
+end
+
+function mt:_expand()
+ local childs = self._childs
+ if not childs then
+ return
+ end
+ self._childs = nil
+
+ local mark = {}
+ mark[self] = true
+
+ local function insert(obj)
+ if not self[obj] then
+ self[obj] = true
+ self[#self+1] = obj
+ end
+ end
+
+ for i = 1, #childs do
+ local child = childs[i]
+ if child:isLocked() then
+ if not self._childs then
+ self._childs = {}
+ end
+ if not self._childs[child] then
+ self._childs[#self._childs+1] = child
+ self._childs[child] = true
+ end
+ else
+ child:_each(mark, insert)
+ end
+ end
end
---@return boolean
function mt:isEmpty()
+ self:_expand()
return #self == 0
end
+---@param n integer
+---@return vm.object?
+function mt:get(n)
+ self:_expand()
+ return self[n]
+end
+
+function mt:lock()
+ self._locked = true
+end
+
+function mt:unlock()
+ self._locked = false
+end
+
+function mt:isLocked()
+ return self._locked == true
+end
+
function mt:addOptional()
if self:isOptional() then
return self
@@ -57,6 +141,7 @@ function mt:removeOptional()
if not self:isOptional() then
return self
end
+ self:_expand()
for i = #self, 1, -1 do
local n = self[i]
if n.type == 'nil'
@@ -73,6 +158,7 @@ function mt:isOptional()
if self.optional ~= nil then
return self.optional
end
+ self:_expand()
for _, c in ipairs(self) do
if c.type == 'nil'
or (c.type == 'boolean' and c[1] == false)
@@ -87,6 +173,7 @@ end
---@return fun():vm.object
function mt:eachObject()
+ self:_expand()
local i = 0
return function ()
i = i + 1
@@ -106,15 +193,15 @@ function vm.setNode(source, node, cover)
return
end
local me = vm.nodeCache[source]
- if not me then
+ if me then
+ me:merge(node)
+ else
if node.type == 'vm.node' then
vm.nodeCache[source] = node
else
vm.nodeCache[source] = vm.createNode(node)
end
- return
end
- vm.nodeCache[source] = vm.createNode(me, node)
end
---@return vm.node?
diff --git a/script/vm/sign.lua b/script/vm/sign.lua
index ca326965..2d45a5a7 100644
--- a/script/vm/sign.lua
+++ b/script/vm/sign.lua
@@ -54,21 +54,21 @@ function mt:resolve(uri, args)
for _, ufield in ipairs(object.fields) do
local ufieldNode = vm.compileNode(ufield.name)
local uvalueNode = vm.compileNode(ufield.extends)
- if ufieldNode[1].type == 'doc.generic.name' and uvalueNode[1].type == 'doc.generic.name' then
+ if ufieldNode:get(1).type == 'doc.generic.name' and uvalueNode:get(1).type == 'doc.generic.name' then
-- { [number]: number} -> { [K]: V }
local tfieldNode = vm.getTableKey(uri, node, 'any')
local tvalueNode = vm.getTableValue(uri, node, 'any')
- resolve(ufieldNode[1], tfieldNode)
- resolve(uvalueNode[1], tvalueNode)
+ resolve(ufieldNode:get(1), tfieldNode)
+ resolve(uvalueNode:get(1), tvalueNode)
else
- if ufieldNode[1].type == 'doc.generic.name' then
+ if ufieldNode:get(1).type == 'doc.generic.name' then
-- { [number]: number}|number[] -> { [K]: number }
local tnode = vm.getTableKey(uri, node, uvalueNode)
- resolve(ufieldNode[1], tnode)
- elseif uvalueNode[1].type == 'doc.generic.name' then
+ resolve(ufieldNode:get(1), tnode)
+ elseif uvalueNode:get(1).type == 'doc.generic.name' then
-- { [number]: number}|number[] -> { [number]: V }
local tnode = vm.getTableValue(uri, node, ufieldNode)
- resolve(uvalueNode[1], tnode)
+ resolve(uvalueNode:get(1), tnode)
end
end
end