diff options
-rw-r--r-- | script/core/infer.lua | 14 | ||||
-rw-r--r-- | script/parser/guide.lua | 112 | ||||
-rw-r--r-- | script/parser/newparser.lua | 10 | ||||
-rw-r--r-- | script/vm/getDef.lua | 30 | ||||
-rw-r--r-- | script/vm/getDocs.lua | 2 | ||||
-rw-r--r-- | script/vm/node/compiler.lua | 71 | ||||
-rw-r--r-- | script/vm/node/global.lua | 29 | ||||
-rw-r--r-- | script/vm/state.lua | 2 |
8 files changed, 162 insertions, 108 deletions
diff --git a/script/core/infer.lua b/script/core/infer.lua index d98449d1..35a054ca 100644 --- a/script/core/infer.lua +++ b/script/core/infer.lua @@ -396,7 +396,7 @@ function m.viewDocFunction(doc) end ---显示对象的推断类型 ----@param source parser.guide.object +---@param source parser.object ---@param mark table ---@return string local function searchInfer(source, infers, mark) @@ -467,7 +467,7 @@ local function getCachedInfers(source, field) end ---搜索对象的推断类型 ----@param source parser.guide.object +---@param source parser.object ---@param field? string ---@param mark? table ---@return string[] @@ -511,7 +511,7 @@ function m.searchInfers(source, field, mark) end ---搜索对象的字面量值 ----@param source parser.guide.object +---@param source parser.object ---@param field? string ---@param mark? table ---@return table @@ -532,7 +532,7 @@ function m.searchLiterals(source, field, mark) end ---搜索并显示推断值 ----@param source parser.guide.object +---@param source parser.object ---@param field? string ---@return string function m.searchAndViewLiterals(source, field, mark) @@ -548,7 +548,7 @@ function m.searchAndViewLiterals(source, field, mark) end ---判断对象的推断值是否是 true ----@param source parser.guide.object +---@param source parser.object ---@param mark? table function m.isTrue(source, mark) if not source then @@ -594,7 +594,7 @@ function m.hasType(source, tp, mark) end ---搜索并显示推断类型 ----@param source parser.guide.object +---@param source parser.object ---@param field? string ---@return string function m.searchAndViewInfers(source, field, mark) @@ -611,7 +611,7 @@ function m.searchAndViewInfers(source, field, mark) end ---搜索并显示推断的class ----@param source parser.guide.object +---@param source parser.object ---@return string? function m.getClass(source) if not source then diff --git a/script/parser/guide.lua b/script/parser/guide.lua index 1ee6fceb..638c08bf 100644 --- a/script/parser/guide.lua +++ b/script/parser/guide.lua @@ -1,61 +1,61 @@ local error = error local type = type ----@class parser.guide.object ----@field bindDocs parser.guide.object[] ----@field bindGroup parser.guide.object[] ----@field bindSources parser.guide.object[] ----@field value parser.guide.object ----@field parent parser.guide.object +---@class parser.object +---@field bindDocs parser.object[] +---@field bindGroup parser.object[] +---@field bindSources parser.object[] +---@field value parser.object +---@field parent parser.object ---@field type string ---@field special string ---@field tag string ----@field args parser.guide.object[] ----@field locals parser.guide.object[] ----@field returns parser.guide.object[] +---@field args parser.object[] +---@field locals parser.object[] +---@field returns parser.object[] ---@field uri uri ---@field start integer ---@field finish integer ---@field effect integer ---@field attrs string[] ----@field specials parser.guide.object[] ----@field labels parser.guide.object[] ----@field node parser.guide.object +---@field specials parser.object[] +---@field labels parser.object[] +---@field node parser.object ---@field dummy boolean ----@field field parser.guide.object ----@field method parser.guide.object ----@field index parser.guide.object ----@field extends parser.guide.object[] ----@field types parser.guide.object[] ----@field fields parser.guide.object[] ----@field typeGeneric table<integer, parser.guide.object[]> ----@field tkey parser.guide.object ----@field tvalue parser.guide.object +---@field field parser.object +---@field method parser.object +---@field index parser.object +---@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 ----@field op parser.guide.object ----@field next parser.guide.object ----@field docParam parser.guide.object +---@field op parser.object +---@field next parser.object +---@field docParam parser.object ---@field sindex integer ----@field name parser.guide.object ----@field call parser.guide.object ----@field closure parser.guide.object ----@field proto parser.guide.object ----@field exp parser.guide.object +---@field name parser.object +---@field call parser.object +---@field closure parser.object +---@field proto parser.object +---@field exp parser.object ---@field isGeneric boolean ----@field alias parser.guide.object ----@field class parser.guide.object ----@field vararg parser.guide.object ----@field param parser.guide.object ----@field overload parser.guide.object +---@field alias parser.object +---@field class parser.object +---@field vararg parser.object +---@field param parser.object +---@field overload parser.object ---@field docParamMap table<string, integer> ---@field upvalues table<string, string[]> ----@field ref parser.guide.object[] +---@field ref parser.object[] ---@field returnIndex integer ----@field docs parser.guide.object[] +---@field docs parser.object[] ---@field state table ---@field comment table ---@field optional boolean ----@field _root parser.guide.object +---@field _root parser.object ---@class guide ---@field debugMode boolean @@ -142,7 +142,7 @@ local childMap = { ['doc.diagnostic'] = {'#names'}, } ----@type table<string, fun(obj: parser.guide.object, list: parser.guide.object[])> +---@type table<string, fun(obj: parser.object, list: parser.object[])> local compiledChildMap = setmetatable({}, {__index = function (self, name) local defs = childMap[name] if not defs then @@ -222,7 +222,7 @@ local function formatNumber(n) end --- 是否是字面量 ----@param obj parser.guide.object +---@param obj parser.object ---@return boolean function m.isLiteral(obj) local tp = obj.type @@ -236,7 +236,7 @@ function m.isLiteral(obj) end --- 获取字面量 ----@param obj parser.guide.object +---@param obj parser.object ---@return any function m.getLiteral(obj) local tp = obj.type @@ -253,8 +253,8 @@ function m.getLiteral(obj) end --- 寻找父函数 ----@param obj parser.guide.object ----@return parser.guide.object +---@param obj parser.object +---@return parser.object function m.getParentFunction(obj) for _ = 1, 1000 do obj = obj.parent @@ -270,8 +270,8 @@ function m.getParentFunction(obj) end --- 寻找所在区块 ----@param obj parser.guide.object ----@return parser.guide.object +---@param obj parser.object +---@return parser.object function m.getBlock(obj) for _ = 1, 1000 do if not obj then @@ -299,8 +299,8 @@ function m.getBlock(obj) end --- 寻找所在父区块 ----@param obj parser.guide.object ----@return parser.guide.object +---@param obj parser.object +---@return parser.object function m.getParentBlock(obj) for _ = 1, 1000 do obj = obj.parent @@ -316,8 +316,8 @@ function m.getParentBlock(obj) end --- 寻找所在可break的父区块 ----@param obj parser.guide.object ----@return parser.guide.object +---@param obj parser.object +---@return parser.object function m.getBreakBlock(obj) for _ = 1, 1000 do obj = obj.parent @@ -336,8 +336,8 @@ function m.getBreakBlock(obj) end --- 寻找doc的主体 ----@param obj parser.guide.object ----@return parser.guide.object +---@param obj parser.object +---@return parser.object function m.getDocState(obj) for _ = 1, 1000 do local parent = obj.parent @@ -353,8 +353,8 @@ function m.getDocState(obj) end --- 寻找所在父类型 ----@param obj parser.guide.object ----@return parser.guide.object +---@param obj parser.object +---@return parser.object function m.getParentType(obj, want) for _ = 1, 1000 do obj = obj.parent @@ -369,8 +369,8 @@ function m.getParentType(obj, want) end --- 寻找根区块 ----@param obj parser.guide.object ----@return parser.guide.object +---@param obj parser.object +---@return parser.object function m.getRoot(obj) local source = obj if source._root then @@ -394,7 +394,7 @@ function m.getRoot(obj) error('guide.getRoot overstack') end ----@param obj parser.guide.object +---@param obj parser.object ---@return uri function m.getUri(obj) if obj.uri then @@ -1101,7 +1101,7 @@ function m.getPath(a, b, sameFunction) end ---是否是全局变量(包括 _G.XXX 形式) ----@param source parser.guide.object +---@param source parser.object ---@return boolean function m.isGlobal(source) if source._isGlobal ~= nil then diff --git a/script/parser/newparser.lua b/script/parser/newparser.lua index e4884212..66df7046 100644 --- a/script/parser/newparser.lua +++ b/script/parser/newparser.lua @@ -2588,9 +2588,9 @@ local function skipSeps() end end ----@return parser.guide.object first ----@return parser.guide.object second ----@return parser.guide.object[] rest +---@return parser.object first +---@return parser.object second +---@return parser.object[] rest local function parseSetValues() skipSpace() local first = parseExp() @@ -2645,8 +2645,8 @@ local function pushActionIntoCurrentChunk(action) end end ----@return parser.guide.object second ----@return parser.guide.object[] rest +---@return parser.object second +---@return parser.object[] rest local function parseVarTails(parser, isLocal) if Tokens[Index + 1] ~= ',' then return diff --git a/script/vm/getDef.lua b/script/vm/getDef.lua index 5546617a..2ba4c379 100644 --- a/script/vm/getDef.lua +++ b/script/vm/getDef.lua @@ -49,17 +49,10 @@ local simpleMap;simpleMap = util.switch() : getMap() local noderMap = util.switch() - : case 'global' - ---@param node vm.node.global - : call(function (node, results) - for _, set in ipairs(node:getSets()) do - results[#results+1] = set - end - end) : getMap() ----@param source parser.guide.object ----@param results parser.guide.object[] +---@param source parser.object +---@param results parser.object[] local function searchBySimple(source, results) local simple = simpleMap[source.type] if simple then @@ -67,9 +60,12 @@ local function searchBySimple(source, results) end end ----@param source parser.guide.object ----@param results parser.guide.object[] +---@param source parser.object +---@param results parser.object[] local function searchByGlobal(source, results) + if source.type == 'field' then + source = source.parent + end local global = source._globalID if not global then return @@ -79,8 +75,8 @@ local function searchByGlobal(source, results) end end ----@param source parser.guide.object ----@param results parser.guide.object[] +---@param source parser.object +---@param results parser.object[] local function searchByNode(source, results) local uri = guide.getUri(source) local node = compiler.compileNode(uri, source) @@ -90,8 +86,8 @@ local function searchByNode(source, results) end end ----@param source parser.guide.object ----@return parser.guide.object[] +---@param source parser.object +---@return parser.object[] function vm.getDefs(source) local results = {} @@ -102,8 +98,8 @@ function vm.getDefs(source) return results end ----@param source parser.guide.object ----@return parser.guide.object[] +---@param source parser.object +---@return parser.object[] function vm.getAllDefs(source) return vm.getDefs(source) end diff --git a/script/vm/getDocs.lua b/script/vm/getDocs.lua index a8c5da29..d13878e6 100644 --- a/script/vm/getDocs.lua +++ b/script/vm/getDocs.lua @@ -8,7 +8,7 @@ local define = require 'proto.define' ---获取class与alias ---@param name? string ----@return parser.guide.object[] +---@return parser.object[] function vm.getDocDefines(uri, name) local cache = vm.getCache 'getDocDefines' if cache[name] then diff --git a/script/vm/node/compiler.lua b/script/vm/node/compiler.lua index db5cd486..2dfd6efd 100644 --- a/script/vm/node/compiler.lua +++ b/script/vm/node/compiler.lua @@ -2,8 +2,7 @@ local guide = require 'parser.guide' local util = require 'utility' local state = require 'vm.state' ----@class parser.guide.object ----@field _compiledGlobal boolean +---@class parser.object ---@field _compiledNodes boolean ---@field _compiled any ---@field _globalID vm.node.global @@ -13,14 +12,21 @@ local m = {} ---@class vm.node.unknown m.UNKNOWN = { type = 'unknown' } +m.GLOBAL_SPLITE = '\x1F' ---@alias vm.node vm.node.unknown | vm.node.global | vm.node.class +---@param ... string +---@return string +function m.getGlobalID(...) + return table.concat({...}, m.GLOBAL_SPLITE) +end + local compilerMap = util.switch() : getMap() ---@param uri uri ----@param source parser.guide.object +---@param source parser.object ---@return vm.node function m.compileNode(uri, source) if source._compiled then @@ -35,6 +41,17 @@ function m.compileNode(uri, source) end local compilerGlobalMap = util.switch() + : case 'local' + : call(function (uri, source) + if source.tag ~= '_ENV' then + return + end + if source.ref then + for _, ref in ipairs(source.ref) do + m.compileGlobalNode(uri, ref) + end + end + end) : case 'setglobal' : call(function (uri, source) local name = guide.getKeyName(source) @@ -46,11 +63,45 @@ local compilerGlobalMap = util.switch() local global = state.getGlobal(name) global:addGet(uri, source) source._globalID = global + + local nxt = source.next + if nxt then + m.compileGlobalNode(uri, nxt) + end + end) + : case 'setfield' + ---@param uri uri + ---@param source parser.object + : call(function (uri, source) + local parent = source.node._globalID + if not parent then + return + end + local name = m.getGlobalID(parent:getName(), guide.getKeyName(source)) + source._globalID = state.declareGlobal(name, uri, source) + end) + : case 'getfield' + ---@param uri uri + ---@param source parser.object + : call(function (uri, source) + local parent = source.node._globalID + if not parent then + return + end + local name = m.getGlobalID(parent:getName(), guide.getKeyName(source)) + local global = state.getGlobal(name) + global:addGet(uri, source) + source._globalID = global + + local nxt = source.next + if nxt then + m.compileGlobalNode(uri, nxt) + end end) : getMap() ---@param uri uri ----@param source parser.guide.object +---@param source parser.object function m.compileGlobalNode(uri, source) if source._globalID ~= nil then return @@ -63,19 +114,11 @@ function m.compileGlobalNode(uri, source) end ---编译全局变量的node ----@param root parser.guide.object +---@param root parser.object function m.compileGlobals(root) - if root._compiledGlobal then - return - end - root._compiledGlobal = true local uri = guide.getUri(root) local env = guide.getENV(root) - if env.ref then - for _, ref in ipairs(env.ref) do - m.compileGlobalNode(uri, ref) - end - end + m.compileGlobalNode(uri, env) end return m diff --git a/script/vm/node/global.lua b/script/vm/node/global.lua index 0e293ca3..499e526b 100644 --- a/script/vm/node/global.lua +++ b/script/vm/node/global.lua @@ -1,24 +1,33 @@ local util = require 'utility' +---@class vm.node.global.link +---@field gets parser.object[] +---@field sets parser.object[] + ---@class vm.node.global ----@field links table<uri, { gets: table, sets: table }> ----@field setsCache parser.guide.object[] ----@field getsCache parser.guide.object[] +---@field links table<uri, vm.node.global.link> +---@field setsCache parser.object[] +---@field getsCache parser.object[] local mt = {} mt.__index = mt mt.type = 'global' mt.name = '' +---@param uri uri +---@param source parser.object function mt:addSet(uri, source) local link = self.links[uri] link.sets[#link.sets+1] = source end +---@param uri uri +---@param source parser.object function mt:addGet(uri, source) local link = self.links[uri] link.gets[#link.gets+1] = source end +---@return parser.object[] function mt:getSets() if not self.setsCache then self.setsCache = {} @@ -31,6 +40,7 @@ function mt:getSets() return self.setsCache end +---@return parser.object[] function mt:getGets() if not self.getsCache then self.getsCache = {} @@ -43,22 +53,27 @@ function mt:getGets() return self.getsCache end +---@param uri uri function mt:dropUri(uri) self.links[uri] = nil self.setsCache = nil self.getsCache = nil end +---@return string +function mt:getName() + return self.name +end + ---@return vm.node.global return function (name) - local global = setmetatable({ + return setmetatable({ name = name, links = util.defaultTable(function () return { - sets = {}, - gets = {}, + sets = {}, + gets = {}, } end), }, mt) - return global end diff --git a/script/vm/state.lua b/script/vm/state.lua index 87376952..cec9eb6f 100644 --- a/script/vm/state.lua +++ b/script/vm/state.lua @@ -15,7 +15,7 @@ end) ---@param name string ---@param uri uri ----@param source parser.guide.object +---@param source parser.object ---@return vm.node.global function m.declareGlobal(name, uri, source) m.subscriptions[uri].globals[name] = true |