summaryrefslogtreecommitdiff
path: root/script/vm/node.lua
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2022-04-13 19:59:45 +0800
committer最萌小汐 <sumneko@hotmail.com>2022-04-13 19:59:45 +0800
commitb3b71716f689be9115cdde8d6caf0314e76ae523 (patch)
treed1859d7a80d635b6157a431c1ef6f51c8a4484f0 /script/vm/node.lua
parent43ef5d13ab20b77da3e4f7626116f0580aa1377e (diff)
downloadlua-language-server-b3b71716f689be9115cdde8d6caf0314e76ae523.zip
cleanup
Diffstat (limited to 'script/vm/node.lua')
-rw-r--r--script/vm/node.lua211
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