diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2022-04-13 19:59:45 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2022-04-13 19:59:45 +0800 |
commit | b3b71716f689be9115cdde8d6caf0314e76ae523 (patch) | |
tree | d1859d7a80d635b6157a431c1ef6f51c8a4484f0 /script/vm/node.lua | |
parent | 43ef5d13ab20b77da3e4f7626116f0580aa1377e (diff) | |
download | lua-language-server-b3b71716f689be9115cdde8d6caf0314e76ae523.zip |
cleanup
Diffstat (limited to 'script/vm/node.lua')
-rw-r--r-- | script/vm/node.lua | 211 |
1 files changed, 141 insertions, 70 deletions
diff --git a/script/vm/node.lua b/script/vm/node.lua index 9f998181..6106d3e1 100644 --- a/script/vm/node.lua +++ b/script/vm/node.lua @@ -1,106 +1,177 @@ -local union = require 'vm.union' -local files = require 'files' - ----@alias vm.node vm.union ----@alias vm.object parser.object | vm.global | vm.generic - ----@class vm.node-manager -local m = {} - -local DUMMY_FUNCTION = function () end +local files = require 'files' +local localMgr = require 'vm.local-manager' +---@class vm +local vm = require 'vm.vm' ---@type table<vm.object, vm.node> -m.nodeCache = {} +vm.nodeCache = {} ----@param a vm.node ----@param b vm.node -function m.mergeNode(a, b) - if not b then - return a - end - if not a then - return b - end - return union(a, b) -end +---@class vm.node +local mt = {} +mt.__index = mt +mt.type = 'vm.node' +mt.optional = nil +mt.lastInfer = nil ----@param source vm.object ---@param node vm.node | vm.object ----@param cover? boolean -function m.setNode(source, node, cover) - if cover then - m.nodeCache[source] = node - return - end +function mt:merge(node) if not node then return end - local me = m.nodeCache[source] - if not me then - if node.type == 'vm.union' then - m.nodeCache[source] = node - else - m.nodeCache[source] = union(node) + if node.type == 'vm.node' then + for _, c in ipairs(node) do + if not self[c] then + self[c] = true + self[#self+1] = c + end + end + if node:isOptional() then + self.optional = true + end + else + if not self[node] then + self[node] = true + self[#self+1] = node end - return end - m.nodeCache[source] = union(me, node) end ----@return vm.node? -function m.getNode(source) - return m.nodeCache[source] +---@return vm.node +function mt:copy() + return vm.createNode(self) +end + +---@return boolean +function mt:isEmpty() + return #self == 0 +end + +---@param source parser.object +function mt:subscribeLocal(source) + -- TODO: need delete + for _, c in ipairs(self) do + localMgr.subscribeLocal(source, c) + end end ----@param node vm.node? ---@return vm.node -function m.addOptional(node) - if not node or node.type ~= 'vm.union' then - node = union(node) +function mt:addOptional() + if self:isOptional() then + return self end - node = node:addOptional() - return node + self.optional = true + return self end ----@param node vm.node? ----@return vm.union? -function m.removeOptional(node) - if not node then - return node +---@return vm.node +function mt:removeOptional() + self.optional = nil + if not self:isOptional() then + return self end - if node.type ~= 'vm.union' then - node = union(node) + local newNode = vm.createNode() + for _, n in ipairs(self) do + if n.type == 'nil' then + goto CONTINUE + end + if n.type == 'boolean' and n[1] == false then + goto CONTINUE + end + if n.type == 'doc.type.boolean' and n[1] == false then + goto CONTINUE + end + if n.type == 'false' then + goto CONTINUE + end + newNode[#newNode+1] = n + ::CONTINUE:: end - node = node:removeOptional() - return node + newNode.optional = false + return newNode +end + +---@return boolean +function mt:isOptional() + if self.optional ~= nil then + return self.optional + end + for _, c in ipairs(self) do + if c.type == 'nil' then + self.optional = true + return true + end + if c.type == 'boolean' then + if c[1] == false then + self.optional = true + return true + end + end + if c.type == 'false' then + self.optional = true + return true + end + end + self.optional = false + return false end ---@return fun():vm.object -function m.eachObject(node) +function mt:eachObject() + local i = 0 + return function () + i = i + 1 + return self[i] + end +end + +---@param source vm.object +---@param node vm.node | vm.object +---@param cover? boolean +function vm.setNode(source, node, cover) if not node then - return DUMMY_FUNCTION + error('Can not set nil node') end - if node.type == 'vm.union' then - return node:eachNode() + if cover then + vm.nodeCache[source] = node + return end - local first = true - return function () - if first then - first = false - return node + local me = vm.nodeCache[source] + if not me then + if node.type == 'vm.node' then + vm.nodeCache[source] = node + else + vm.nodeCache[source] = vm.createNode(node) end - return nil + return end + vm.nodeCache[source] = vm.createNode(me, node) +end + +---@return vm.node? +function vm.getNode(source) + return vm.nodeCache[source] end -function m.clearNodeCache() - m.nodeCache = {} +function vm.clearNodeCache() + vm.nodeCache = {} +end + +---@param a? vm.node | vm.object +---@param b? vm.node | vm.object +---@return vm.node +function vm.createNode(a, b) + local node = setmetatable({}, mt) + if a then + node:merge(a) + end + if b then + node:merge(b) + end + return node end files.watch(function (ev, uri) if ev == 'version' then - m.clearNodeCache() + vm.clearNodeCache() end end) - -return m |