diff options
-rw-r--r-- | script/vm/getDef.lua | 10 | ||||
-rw-r--r-- | script/vm/global-manager.lua | 59 | ||||
-rw-r--r-- | script/vm/node/compiler.lua | 1 | ||||
-rw-r--r-- | script/vm/node/global.lua | 5 |
4 files changed, 50 insertions, 25 deletions
diff --git a/script/vm/getDef.lua b/script/vm/getDef.lua index 6cc6bf85..c37c1323 100644 --- a/script/vm/getDef.lua +++ b/script/vm/getDef.lua @@ -78,6 +78,16 @@ local searchFieldMap = util.switch() end end end) + : case 'global' + : call(function (node, key, pushResult) + local newGlobal = globalMgr.getGlobal(node.name, key) + if not newGlobal then + return + end + for set in ipairs(newGlobal:getSets()) do + pushResult(set) + end + end) : getMap() local nodeMap;nodeMap = util.switch() diff --git a/script/vm/global-manager.lua b/script/vm/global-manager.lua index db037c32..86f6be9f 100644 --- a/script/vm/global-manager.lua +++ b/script/vm/global-manager.lua @@ -8,11 +8,9 @@ local globalBuilder = require 'vm.node.global' ---@class vm.global-manager local m = {} ---@type table<string, vm.node.global> -m.globals = util.defaultTable(globalBuilder) +m.globals = {} ---@type table<uri, table<string, boolean>> -m.globalSubs = util.defaultTable(function () - return {} -end) +m.globalSubs = util.multiTable(2) m.ID_SPLITE = '\x1F' @@ -24,25 +22,29 @@ local compilerGlobalMap = util.switch() end if source.ref then for _, ref in ipairs(source.ref) do - m.compileNode(uri, ref) + m.compileObject(uri, ref) end end end) : case 'setglobal' : call(function (uri, source) - local name = guide.getKeyName(source) - source._globalNode = m.declareGlobal(name, uri, source) + local name = guide.getKeyName(source) + local global = m.declareGlobal(name, uri) + global:addSet(uri, source) + m.globalSubs[uri][name] = true + source._globalNode = global end) : case 'getglobal' : call(function (uri, source) local name = guide.getKeyName(source) - local global = m.getGlobal(name) + local global = m.declareGlobal(name, uri) global:addGet(uri, source) + m.globalSubs[uri][name] = true source._globalNode = global local nxt = source.next if nxt then - m.compileNode(uri, nxt) + m.compileObject(uri, nxt) end end) : case 'setfield' @@ -55,8 +57,10 @@ local compilerGlobalMap = util.switch() if not parent then return end - local name = parent:getName() .. m.ID_SPLITE .. guide.getKeyName(source) - source._globalNode = m.declareGlobal(name, uri, source) + local name = parent:getName() .. m.ID_SPLITE .. guide.getKeyName(source) + local global = m.declareGlobal(name, uri) + global:addSet(uri, source) + m.globalSubs[uri][name] = true end) : case 'getfield' : case 'getmethod' @@ -70,12 +74,13 @@ local compilerGlobalMap = util.switch() end local name = parent:getName() .. m.ID_SPLITE .. guide.getKeyName(source) local global = m.getGlobal(name) + m.globalSubs[uri][name] = true global:addGet(uri, source) source._globalNode = global local nxt = source.next if nxt then - m.compileNode(uri, nxt) + m.compileObject(uri, nxt) end end) : getMap() @@ -83,27 +88,27 @@ local compilerGlobalMap = util.switch() ---@param name string ---@param uri uri ----@param source parser.object ---@return vm.node.global -function m.declareGlobal(name, uri, source) +function m.declareGlobal(name, uri) m.globalSubs[uri][name] = true - local node = m.globals[name] - node:addSet(uri, source) - return node + if not m.globals[name] then + m.globals[name] = globalBuilder(name) + end + return m.globals[name] end ---@param name string ----@param uri? uri ----@return vm.node.global -function m.getGlobal(name, uri) - if uri then - m.globalSubs[uri][name] = true +---@param field? string +---@return vm.node.global? +function m.getGlobal(name, field) + if field then + name = name .. m.ID_SPLITE .. field end return m.globals[name] end ---@param source parser.object -function m.compileNode(uri, source) +function m.compileObject(uri, source) if source._globalNode ~= nil then return end @@ -118,7 +123,7 @@ end function m.compileAst(source) local uri = guide.getUri(source) local env = guide.getENV(source) - m.compileNode(uri, env) + m.compileObject(uri, env) end ---@return vm.node.global @@ -135,7 +140,11 @@ function m.dropUri(uri) local globalSub = m.globalSubs[uri] m.globalSubs[uri] = nil for name in pairs(globalSub) do - m.globals[name]:dropUri(uri) + local global = m.globals[name] + global:dropUri(uri) + if not global:isAlive() then + m.globals[name] = nil + end end end diff --git a/script/vm/node/compiler.lua b/script/vm/node/compiler.lua index e642856a..33b9b05e 100644 --- a/script/vm/node/compiler.lua +++ b/script/vm/node/compiler.lua @@ -3,6 +3,7 @@ local util = require 'utility' local union = require 'vm.node.union' local localID = require 'vm.local-id' local literalMgr = require 'vm.literal-manager' +local globalMgr = require 'vm.global-manager' ---@class parser.object ---@field _compiledNodes boolean diff --git a/script/vm/node/global.lua b/script/vm/node/global.lua index 499e526b..d5974e63 100644 --- a/script/vm/node/global.lua +++ b/script/vm/node/global.lua @@ -65,6 +65,11 @@ function mt:getName() return self.name end +---@return boolean +function mt:isAlive() + return next(self.links) ~= nil +end + ---@return vm.node.global return function (name) return setmetatable({ |