diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2022-02-23 18:10:22 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2022-02-23 18:10:22 +0800 |
commit | e3a0eea7fc75807037a24b630241bf62a0fe1299 (patch) | |
tree | 546f7267134521f00aab030b8f395bd6c8d915b7 /script/vm/global-manager.lua | |
parent | 608aebdc13ebd64ae81d81049e7bbb3cc13cb891 (diff) | |
download | lua-language-server-e3a0eea7fc75807037a24b630241bf62a0fe1299.zip |
cleanup
Diffstat (limited to 'script/vm/global-manager.lua')
-rw-r--r-- | script/vm/global-manager.lua | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/script/vm/global-manager.lua b/script/vm/global-manager.lua new file mode 100644 index 00000000..db037c32 --- /dev/null +++ b/script/vm/global-manager.lua @@ -0,0 +1,142 @@ +local util = require 'utility' +local guide = require 'parser.guide' +local globalBuilder = require 'vm.node.global' + +---@class parser.object +---@field _globalNode vm.node.global + +---@class vm.global-manager +local m = {} +---@type table<string, vm.node.global> +m.globals = util.defaultTable(globalBuilder) +---@type table<uri, table<string, boolean>> +m.globalSubs = util.defaultTable(function () + return {} +end) + +m.ID_SPLITE = '\x1F' + +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.compileNode(uri, ref) + end + end + end) + : case 'setglobal' + : call(function (uri, source) + local name = guide.getKeyName(source) + source._globalNode = m.declareGlobal(name, uri, source) + end) + : case 'getglobal' + : call(function (uri, source) + local name = guide.getKeyName(source) + local global = m.getGlobal(name) + global:addGet(uri, source) + source._globalNode = global + + local nxt = source.next + if nxt then + m.compileNode(uri, nxt) + end + end) + : case 'setfield' + : case 'setmethod' + : case 'setindex' + ---@param uri uri + ---@param source parser.object + : call(function (uri, source) + local parent = source.node._globalNode + if not parent then + return + end + local name = parent:getName() .. m.ID_SPLITE .. guide.getKeyName(source) + source._globalNode = m.declareGlobal(name, uri, source) + end) + : case 'getfield' + : case 'getmethod' + : case 'getindex' + ---@param uri uri + ---@param source parser.object + : call(function (uri, source) + local parent = source.node._globalNode + if not parent then + return + end + local name = parent:getName() .. m.ID_SPLITE .. guide.getKeyName(source) + local global = m.getGlobal(name) + global:addGet(uri, source) + source._globalNode = global + + local nxt = source.next + if nxt then + m.compileNode(uri, nxt) + end + end) + : getMap() + + +---@param name string +---@param uri uri +---@param source parser.object +---@return vm.node.global +function m.declareGlobal(name, uri, source) + m.globalSubs[uri][name] = true + local node = m.globals[name] + node:addSet(uri, source) + return node +end + +---@param name string +---@param uri? uri +---@return vm.node.global +function m.getGlobal(name, uri) + if uri then + m.globalSubs[uri][name] = true + end + return m.globals[name] +end + +---@param source parser.object +function m.compileNode(uri, source) + if source._globalNode ~= nil then + return + end + source._globalNode = false + local compiler = compilerGlobalMap[source.type] + if compiler then + compiler(uri, source) + end +end + +---@param source parser.object +function m.compileAst(source) + local uri = guide.getUri(source) + local env = guide.getENV(source) + m.compileNode(uri, env) +end + +---@return vm.node.global +function m.getNode(source) + if source.type == 'field' + or source.type == 'method' then + source = source.parent + end + return source._globalNode +end + +---@param uri uri +function m.dropUri(uri) + local globalSub = m.globalSubs[uri] + m.globalSubs[uri] = nil + for name in pairs(globalSub) do + m.globals[name]:dropUri(uri) + end +end + +return m |