diff options
-rw-r--r-- | script/parser/guide.lua | 1 | ||||
-rw-r--r-- | script/parser/luadoc.lua | 5 | ||||
-rw-r--r-- | script/vm/compiler.lua | 37 | ||||
-rw-r--r-- | script/vm/generic-manager.lua | 33 | ||||
-rw-r--r-- | script/vm/generic.lua | 29 | ||||
-rw-r--r-- | test/definition/luadoc.lua | 2 |
6 files changed, 80 insertions, 27 deletions
diff --git a/script/parser/guide.lua b/script/parser/guide.lua index e877ddce..831534a7 100644 --- a/script/parser/guide.lua +++ b/script/parser/guide.lua @@ -28,7 +28,6 @@ local type = type ---@field extends parser.object[] ---@field types parser.object[] ---@field fields parser.object[] ----@field typeGeneric table<integer, parser.object[]> ---@field tkey parser.object ---@field tvalue parser.object ---@field tindex integer diff --git a/script/parser/luadoc.lua b/script/parser/luadoc.lua index a47ebe34..5bc566f2 100644 --- a/script/parser/luadoc.lua +++ b/script/parser/luadoc.lua @@ -1263,7 +1263,7 @@ local function bindGeneric(binded) if doc.type == 'doc.generic' then for _, obj in ipairs(doc.generics) do local name = obj.generic[1] - generics[name] = {} + generics[name] = true end elseif doc.type == 'doc.param' or doc.type == 'doc.return' @@ -1271,8 +1271,7 @@ local function bindGeneric(binded) guide.eachSourceType(doc, 'doc.type.name', function (src) local name = src[1] if generics[name] then - generics[name][#generics[name]+1] = src - src.typeGeneric = generics + src.type = 'doc.generic.name' end end) end diff --git a/script/vm/compiler.lua b/script/vm/compiler.lua index d6987295..da4ea7b4 100644 --- a/script/vm/compiler.lua +++ b/script/vm/compiler.lua @@ -172,10 +172,19 @@ local function getReturn(func, index, source, args) if node then for cnode in m.eachNode(node) do if cnode.type == 'function' then - return getReturnOfFunction(cnode, index) + local returnNode = getReturnOfFunction(cnode, index) + if returnNode and returnNode.type == 'generic' then + local argNodes = {} + for i, arg in ipairs(args) do + argNodes[i] = m.compileNode(arg) + end + returnNode = returnNode:resolve(argNodes) + end + m.setNode(source, returnNode) end end end + return nodeCache[source] end local function bindDocs(source) @@ -286,12 +295,17 @@ local function getFunctionGeneric(func) 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 + if not func._generic then + return false + end + for _, doc in ipairs(func.bindDocs) do + if doc.type == 'doc.param' then + func._generic:addSign(doc.extends) + end + end return func._generic end @@ -399,16 +413,15 @@ local compilerMap = util.switch() hasMarkDoc = true local hasGeneric if generic then - guide.eachSourceType(rtn, 'doc.type.name', function (src) - if src.typeGeneric then - hasGeneric = true - end + guide.eachSourceType(rtn, 'doc.generic.name', function (src) + hasGeneric = true end) end + local rtnNode = m.compileNode(rtn) if hasGeneric then - m.setNode(source, generic:getChild(rtn)) + m.setNode(source, generic:getChild(rtnNode)) else - m.setNode(source, m.compileNode(rtn)) + m.setNode(source, rtnNode) end end end @@ -434,6 +447,10 @@ local compilerMap = util.switch() m.setNode(source, m.compileNode(typeUnit)) end end) + : case 'doc.generic.name' + : call(function (source) + m.setNode(source, source) + end) : case 'doc.field' : call(function (source) m.setNode(source, m.compileNode(source.extends)) diff --git a/script/vm/generic-manager.lua b/script/vm/generic-manager.lua index b41b1e61..dbee5dae 100644 --- a/script/vm/generic-manager.lua +++ b/script/vm/generic-manager.lua @@ -2,28 +2,47 @@ local createGeneric = require 'vm.generic' ---@class vm.node.generic-manager ---@field parent parser.object ----@field signMap table<string, vm.node> ----@field signList string[] +---@field signList parser.object[] local mt = {} mt.__index = mt mt.type = 'generic-manager' ----@param key string +---@param key parser.object function mt:addSign(key) self.signList[#self.signList+1] = key end ----@param proto parser.object -function mt:getChild(proto) - local generic = createGeneric(self, proto) +---@param node vm.node +function mt:getChild(node) + local generic = createGeneric(self, node) return generic end +---@param argNodes vm.node[] +---@return table<string, vm.node> +function mt:resolve(argNodes) + local resolved = {} + for i, node in ipairs(argNodes) do + local sign = self.signList[i] + if not sign then + break + end + for _, typeUnit in ipairs(sign.types) do + if typeUnit.type == 'doc.generic.name' then + local key = typeUnit[1] + if not resolved[key] then + resolved[key] = node + end + end + end + end + return resolved +end + ---@return vm.node.generic-manager return function (parent) local genericMgr = setmetatable({ parent = parent, - signMap = {}, signList = {}, }, mt) return genericMgr diff --git a/script/vm/generic.lua b/script/vm/generic.lua index 8b298508..86fd193a 100644 --- a/script/vm/generic.lua +++ b/script/vm/generic.lua @@ -1,16 +1,35 @@ ---@class vm.node.generic ---@field parent vm.node.generic-manager ----@field proto parser.object +---@field node vm.node local mt = {} mt.__index = mt mt.type = 'generic' +---@param node vm.node +---@param resolved table<string, vm.node> +---@return vm.node +local function cloneObject(node, resolved) + if node.type == 'doc.generic.name' then + local key = node[1] + return resolved[key] + end + return nil +end + +---@param argNodes vm.node[] +---@return parser.object +function mt:resolve(argNodes) + local resolved = self.parent:resolve(argNodes) + local newProto = cloneObject(self.node, resolved) + return newProto +end + ---@param parent vm.node.generic-manager ----@param proto parser.object -return function (parent, proto) +---@param node vm.node +return function (parent, node) local generic = setmetatable({ - parent = parent, - proto = proto, + parent = parent, + node = node, }, mt) return generic end diff --git a/test/definition/luadoc.lua b/test/definition/luadoc.lua index 61477b0d..74770794 100644 --- a/test/definition/luadoc.lua +++ b/test/definition/luadoc.lua @@ -235,7 +235,7 @@ TEST [[ ---@return T local function f(p) end -local k = <!{}!> +local k = <!function () end!> local <?<!r!>?> = f(k) ]] |