diff options
-rw-r--r-- | script/core/generic.lua | 129 | ||||
-rw-r--r-- | script/core/linker.lua | 12 | ||||
-rw-r--r-- | script/core/searcher.lua | 26 |
3 files changed, 108 insertions, 59 deletions
diff --git a/script/core/generic.lua b/script/core/generic.lua index fe24bcfc..ad91b2f9 100644 --- a/script/core/generic.lua +++ b/script/core/generic.lua @@ -28,16 +28,16 @@ local function instantValue(closure, proto) end ---递归实例化对象 ----@param obj parser.guide.object +---@param proto parser.guide.object ---@return generic.value -local function createValue(closure, obj, callback, road) +local function createValue(closure, proto, callback, road) if callback then road = road or {} end - if obj.type == 'doc.type' then + if proto.type == 'doc.type' then local types = {} local hasGeneric - for i, tp in ipairs(obj.types) do + for i, tp in ipairs(proto.types) do local genericValue = createValue(closure, tp, callback, road) if genericValue then hasGeneric = true @@ -49,80 +49,129 @@ local function createValue(closure, obj, callback, road) if not hasGeneric then return nil end - local value = instantValue(closure, obj) + local value = instantValue(closure, proto) value.types = types linker.compileLink(value) return value end - if obj.type == 'doc.type.name' then - if not obj.typeGeneric then + if proto.type == 'doc.type.name' then + if not proto.typeGeneric then return nil end - local key = obj[1] - local value = instantValue(closure, obj) + local key = proto[1] + local value = instantValue(closure, proto) if callback then - callback(road, key, obj) + callback(road, key, proto) + end + linker.compileLink(value) + return value + end + if proto.type == 'doc.type.function' then + local hasGeneric + local args = {} + local returns = {} + for i, arg in ipairs(proto.args) do + local value = instantValue(closure, arg) + if value then + hasGeneric = true + end + args[i] = value or arg + end + for i, rtn in ipairs(proto.returns) do + local value = instantValue(closure, rtn) + if value then + hasGeneric = true + end + returns[i] = value or rtn + end + if not hasGeneric then + return nil end + local value = instantValue(closure, proto) + value.args = args + value.returns = returns + value.isGeneric = true linker.compileLink(value) + linker.pushSource(value) return value end end +local function buildValue(road, key, proto, param, upvalues) + local paramID + if proto.literal then + local str = param.type == 'string' and param[1] + if not str then + return + end + paramID = 'dn:' .. str + else + paramID = linker.getID(param) + end + if not paramID then + return + end + if not upvalues[key] then + upvalues[key] = {} + end + -- TODO + upvalues[key][#upvalues[key]+1] = paramID +end + -- 为所有的 param 与 return 创建副本 ---@param closure generic.closure local function buildValues(closure) local protoFunction = closure.proto local upvalues = closure.upvalues local params = closure.call.args + if protoFunction.type == 'function' then for _, doc in ipairs(protoFunction.bindDocs) do if doc.type == 'doc.param' then local extends = doc.extends local index = extends.paramIndex - closure.params[index] = createValue(closure, extends, function (road, key, proto) - local param = params[index] - if not param then - return - end - local paramID - if proto.literal then - local str = param.type == 'string' and param[1] - if not str then - return - end - paramID = 'dn:' .. str - else - paramID = linker.getID(param) - end - if not paramID then - return - end - if not upvalues[key] then - upvalues[key] = {} - end - -- TODO - upvalues[key][#upvalues[key]+1] = paramID - end) + local param = params[index] + closure.params[index] = param and createValue(closure, extends, function (road, key, proto) + buildValue(road, key, proto, param, upvalues) + end) or extends end end for _, doc in ipairs(protoFunction.bindDocs) do if doc.type == 'doc.return' then for _, rtn in ipairs(doc.returns) do - closure.returns[rtn.returnIndex] = createValue(closure, rtn) + closure.returns[rtn.returnIndex] = createValue(closure, rtn) or rtn end end end end - if protoFunction.type == 'doc.function' then - + if protoFunction.type == 'doc.type.function' then + for index, arg in ipairs(protoFunction.args) do + local extends = arg.extends + local param = params[index] + closure.params[index] = param and createValue(closure, extends, function (road, key, proto) + buildValue(road, key, proto, param, upvalues) + end) or extends + end + for index, rtn in ipairs(protoFunction.returns) do + closure.returns[index] = createValue(closure, rtn) or rtn + end end end ---创建一个闭包 ----@param protoFunction parser.guide.object # 原型函数 ----@param parentClosure? generic.closure +---@param proto parser.guide.object|generic.value # 原型函数|泛型值 ---@return generic.closure -function m.createClosure(protoFunction, call, parentClosure) +function m.createClosure(proto, call) + local protoFunction, parentClosure + if proto.type == 'function' then + if not proto.args or #proto.args == 0 then + return nil + end + protoFunction = proto + elseif proto.type == 'generic.value' then + protoFunction = proto.proto + parentClosure = proto.closure + end ---@type generic.closure local closure = { type = 'generic.closure', diff --git a/script/core/linker.lua b/script/core/linker.lua index cecdc9de..4a031abe 100644 --- a/script/core/linker.lua +++ b/script/core/linker.lua @@ -311,9 +311,12 @@ m.RETURN_INDEX_CHAR = RETURN_INDEX_CHAR m.PARAM_INDEX_CHAR = PARAM_INDEX_CHAR ---添加关联单元 ----@param id string ---@param source parser.guide.object -function m.pushSource(id, source) +function m.pushSource(source) + local id = m.getID(source) + if not id then + return + end local link = getLink(id) if not link.sources then link.sources = {} @@ -672,10 +675,7 @@ function m.compileLinks(source) Linkers = {} root._linkers = Linkers guide.eachSource(root, function (src) - local id = getID(src) - if id then - m.pushSource(id, src) - end + m.pushSource(src) m.compileLink(src) end) return Linkers diff --git a/script/core/searcher.lua b/script/core/searcher.lua index 4150759b..54d95859 100644 --- a/script/core/searcher.lua +++ b/script/core/searcher.lua @@ -176,9 +176,7 @@ function m.searchRefsByID(status, uri, expect, mode) local mark = status.mark local queueIndex = 0 - -- 缓存过程中的泛型,以泛型关联表为key - local genericStashMap = {} - local idStack = {} + local callStack = {} local function search(id, field) local fieldLen @@ -253,11 +251,12 @@ function m.searchRefsByID(status, uri, expect, mode) end local function findLastCall() - for i = #idStack, 1, -1 do - local id = idStack[i] - local link = linker.getLinkByID(root, id) - if link.call then - return link.call + for i = #callStack, 1, -1 do + local call = callStack[i] + if call then + -- 标记此处的call失效,等待在堆栈平衡时弹出 + callStack[i] = false + return call end end return nil @@ -274,9 +273,6 @@ function m.searchRefsByID(status, uri, expect, mode) if not call then return end - if not call.args or #call.args == 0 then - return - end local closure = generic.createClosure(source, call) if not closure then return @@ -293,7 +289,9 @@ function m.searchRefsByID(status, uri, expect, mode) end local link = linker.getLinkByID(root, id) if link then - idStack[#idStack+1] = id + if link.call then + callStack[#callStack+1] = link.call + end if field == nil and link.sources then for _, source in ipairs(link.sources) do m.pushResult(status, mode, source) @@ -314,7 +312,9 @@ function m.searchRefsByID(status, uri, expect, mode) checkGeneric(link.sources[1], field) end - idStack[#idStack] = nil + if link.call then + callStack[#callStack] = nil + end end checkLastID(id, field) end |