summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsumneko <sumneko@hotmail.com>2022-03-05 04:24:39 +0800
committersumneko <sumneko@hotmail.com>2022-03-05 04:24:39 +0800
commitba84c67f8ebdf42d429eec829067233db13a0f0b (patch)
tree32e9b91bf9ac0d110d631c278824a47c333e775f
parent513023b9ee1d4af55e43d530fe5ed1092beb79ce (diff)
downloadlua-language-server-ba84c67f8ebdf42d429eec829067233db13a0f0b.zip
update
-rw-r--r--script/parser/guide.lua9
-rw-r--r--script/vm/compiler.lua85
-rw-r--r--script/vm/generic-manager.lua30
-rw-r--r--script/vm/generic.lua16
-rw-r--r--script/vm/local-manager.lua5
-rw-r--r--script/vm/union.lua3
6 files changed, 115 insertions, 33 deletions
diff --git a/script/parser/guide.lua b/script/parser/guide.lua
index 730a099d..e877ddce 100644
--- a/script/parser/guide.lua
+++ b/script/parser/guide.lua
@@ -41,7 +41,6 @@ local type = type
---@field closure parser.object
---@field proto parser.object
---@field exp parser.object
----@field isGeneric boolean
---@field alias parser.object
---@field class parser.object
---@field vararg parser.object
@@ -648,10 +647,10 @@ function m.eachSourceBetween(ast, start, finish, callback)
end
local function getSourceTypeCache(ast)
- local cache = ast.typeCache
+ local cache = ast._typeCache
if not cache then
cache = {}
- ast.typeCache = cache
+ ast._typeCache = cache
m.eachSource(ast, function (source)
local tp = source.type
if not tp then
@@ -694,10 +693,10 @@ end
--- 遍历所有的source
function m.eachSource(ast, callback)
- local cache = ast.eachCache
+ local cache = ast._eachCache
if not cache then
cache = { ast }
- ast.eachCache = cache
+ ast._eachCache = cache
local mark = {}
local index = 1
while true do
diff --git a/script/vm/compiler.lua b/script/vm/compiler.lua
index b814cdbc..d6987295 100644
--- a/script/vm/compiler.lua
+++ b/script/vm/compiler.lua
@@ -1,9 +1,10 @@
-local guide = require 'parser.guide'
-local util = require 'utility'
-local union = require 'vm.union'
-local localID = require 'vm.local-id'
-local localMgr = require 'vm.local-manager'
-local globalMgr = require 'vm.global-manager'
+local guide = require 'parser.guide'
+local util = require 'utility'
+local union = require 'vm.union'
+local localID = require 'vm.local-id'
+local localMgr = require 'vm.local-manager'
+local globalMgr = require 'vm.global-manager'
+local genericMgr = require 'vm.generic-manager'
---@class parser.object
---@field _compiledNodes boolean
@@ -12,28 +13,27 @@ local globalMgr = require 'vm.global-manager'
---@class vm.node.compiler
local m = {}
----@class vm.node.cross
+local nodeCache = {}
----@alias vm.node parser.object | vm.node.union | vm.node.cross | vm.node.global
+---@alias vm.node parser.object | vm.node.union | vm.node.global | vm.node.generic
function m.setNode(source, node)
if not node then
return
end
- local me = source._node
+ local me = nodeCache[source]
if not me then
- source._node = node
+ nodeCache[source] = node
return
end
if me == node then
return
end
- if me.type == 'union'
- or me.type == 'cross' then
+ if me.type == 'union' then
me:merge(node)
return
end
- source._node = union(me, node)
+ nodeCache[source] = union(me, node)
end
function m.eachNode(node)
@@ -161,7 +161,7 @@ local function getReturnOfSetMetaTable(source, args)
m.setNode(source, m.compileNode(src))
end)
end
- return source._node
+ return nodeCache[source]
end
local function getReturn(func, index, source, args)
@@ -272,6 +272,29 @@ local function selectNode(source, list, index)
return m.compileNode(exp)
end
+---@class parser.object
+---@field _generic? vm.node.generic-manager
+
+---@param func parser.object
+---@return vm.node.generic-manager?
+local function getFunctionGeneric(func)
+ if func._generic ~= nil then
+ return func._generic
+ end
+ func._generic = false
+ for _, doc in ipairs(func.bindDocs) do
+ if doc.type == 'doc.generic' then
+ if not func._generic then
+ func._generic = genericMgr(func)
+ for _, obj in ipairs(doc) do
+ func._generic:addSign(obj[1])
+ end
+ end
+ end
+ end
+ return func._generic
+end
+
local compilerMap = util.switch()
: case 'boolean'
: case 'table'
@@ -281,12 +304,12 @@ local compilerMap = util.switch()
: case 'doc.type.function'
: case 'doc.type.table'
: call(function (source)
- localMgr.declareLocal(source)
+ --localMgr.declareLocal(source)
m.setNode(source, source)
end)
: case 'function'
: call(function (source)
- localMgr.declareLocal(source)
+ --localMgr.declareLocal(source)
m.setNode(source, source)
if source.bindDocs then
@@ -299,6 +322,7 @@ local compilerMap = util.switch()
end)
: case 'local'
: call(function (source)
+ --localMgr.declareLocal(source)
m.setNode(source, source)
local hasMarkDoc
if source.bindDocs then
@@ -367,12 +391,25 @@ local compilerMap = util.switch()
local index = source.index
local hasMarkDoc
if func.bindDocs then
+ local generic = getFunctionGeneric(func)
for _, doc in ipairs(func.bindDocs) do
if doc.type == 'doc.return' then
for _, rtn in ipairs(doc.returns) do
if rtn.returnIndex == index then
hasMarkDoc = true
- m.setNode(source, m.compileNode(rtn))
+ local hasGeneric
+ if generic then
+ guide.eachSourceType(rtn, 'doc.type.name', function (src)
+ if src.typeGeneric then
+ hasGeneric = true
+ end
+ end)
+ end
+ if hasGeneric then
+ m.setNode(source, generic:getChild(rtn))
+ else
+ m.setNode(source, m.compileNode(rtn))
+ end
end
end
end
@@ -481,16 +518,20 @@ end
---@param source parser.object
---@return vm.node
function m.compileNode(source)
- if source._node ~= nil then
- return source._node
+ if nodeCache[source] ~= nil then
+ return nodeCache[source]
end
- source._node = false
+ nodeCache[source] = false
compileByGlobal(source)
compileByNode(source)
- localMgr.subscribeLocal(source, source._node)
+ --localMgr.subscribeLocal(source, source._node)
+
+ return nodeCache[source]
+end
- return source._node
+function m.clearNodeCache()
+ nodeCache = {}
end
return m
diff --git a/script/vm/generic-manager.lua b/script/vm/generic-manager.lua
new file mode 100644
index 00000000..b41b1e61
--- /dev/null
+++ b/script/vm/generic-manager.lua
@@ -0,0 +1,30 @@
+local createGeneric = require 'vm.generic'
+
+---@class vm.node.generic-manager
+---@field parent parser.object
+---@field signMap table<string, vm.node>
+---@field signList string[]
+local mt = {}
+mt.__index = mt
+mt.type = 'generic-manager'
+
+---@param key string
+function mt:addSign(key)
+ self.signList[#self.signList+1] = key
+end
+
+---@param proto parser.object
+function mt:getChild(proto)
+ local generic = createGeneric(self, proto)
+ return generic
+end
+
+---@return vm.node.generic-manager
+return function (parent)
+ local genericMgr = setmetatable({
+ parent = parent,
+ signMap = {},
+ signList = {},
+ }, mt)
+ return genericMgr
+end
diff --git a/script/vm/generic.lua b/script/vm/generic.lua
new file mode 100644
index 00000000..8b298508
--- /dev/null
+++ b/script/vm/generic.lua
@@ -0,0 +1,16 @@
+---@class vm.node.generic
+---@field parent vm.node.generic-manager
+---@field proto parser.object
+local mt = {}
+mt.__index = mt
+mt.type = 'generic'
+
+---@param parent vm.node.generic-manager
+---@param proto parser.object
+return function (parent, proto)
+ local generic = setmetatable({
+ parent = parent,
+ proto = proto,
+ }, mt)
+ return generic
+end
diff --git a/script/vm/local-manager.lua b/script/vm/local-manager.lua
index bae22318..318dd4bc 100644
--- a/script/vm/local-manager.lua
+++ b/script/vm/local-manager.lua
@@ -29,12 +29,11 @@ function m.subscribeLocal(source, node)
if not node then
return
end
- if node.type == 'union'
- or node.type == 'cross' then
+ if node.type == 'union' then
node:subscribeLocal(source)
return
end
- if not m.allLocals[source] then
+ if not m.allLocals[node] then
return
end
m.localSubs[node][source] = true
diff --git a/script/vm/union.lua b/script/vm/union.lua
index f0c259df..97ab333f 100644
--- a/script/vm/union.lua
+++ b/script/vm/union.lua
@@ -29,9 +29,6 @@ end
function mt:subscribeLocal(source)
for _, c in ipairs(self) do
localMgr.subscribeLocal(source, c)
- if c.type == 'cross' then
- c:subscribeLocal(source)
- end
end
end