summaryrefslogtreecommitdiff
path: root/script
diff options
context:
space:
mode:
Diffstat (limited to 'script')
-rw-r--r--script/core/completion/completion.lua3
-rw-r--r--script/vm/compiler.lua345
-rw-r--r--script/vm/def.lua7
-rw-r--r--script/vm/generic.lua12
-rw-r--r--script/vm/global-manager.lua7
-rw-r--r--script/vm/infer.lua19
-rw-r--r--script/vm/init.lua3
-rw-r--r--script/vm/local-manager.lua3
-rw-r--r--script/vm/manager.lua2
-rw-r--r--script/vm/node.lua211
-rw-r--r--script/vm/ref.lua3
-rw-r--r--script/vm/sign.lua13
-rw-r--r--script/vm/type.lua40
-rw-r--r--script/vm/union.lua129
-rw-r--r--script/vm/value.lua17
15 files changed, 382 insertions, 432 deletions
diff --git a/script/core/completion/completion.lua b/script/core/completion/completion.lua
index 3ec91153..3eaed85a 100644
--- a/script/core/completion/completion.lua
+++ b/script/core/completion/completion.lua
@@ -20,7 +20,6 @@ local infer = require 'vm.infer'
local await = require 'await'
local postfix = require 'core.completion.postfix'
local globalMgr = require 'vm.global-manager'
-local nodeMgr = require 'vm.node'
local diagnosticModes = {
'disable-next-line',
@@ -1405,7 +1404,7 @@ local function tryCallArg(state, position, results)
end
local node = vm.compileCallArg({ type = 'dummyarg' }, call, argIndex)
local enums = {}
- for src in nodeMgr.eachObject(node) do
+ for src in node:eachObject() do
if src.type == 'doc.type.string'
or src.type == 'doc.type.integer'
or src.type == 'doc.type.boolean' then
diff --git a/script/vm/compiler.lua b/script/vm/compiler.lua
index 2af4f61f..3c0a2dcb 100644
--- a/script/vm/compiler.lua
+++ b/script/vm/compiler.lua
@@ -2,10 +2,8 @@ local guide = require 'parser.guide'
local util = require 'utility'
local localID = require 'vm.local-id'
local globalMgr = require 'vm.global-manager'
-local nodeMgr = require 'vm.node'
local signMgr = require 'vm.sign'
local config = require 'config'
-local union = require 'vm.union'
local genericMgr = require 'vm.generic'
local rpath = require 'workspace.require-path'
local files = require 'files'
@@ -112,7 +110,7 @@ local searchFieldSwitch = util.switch()
local fieldKey = field.name
if fieldKey.type == 'doc.type' then
local fieldNode = vm.compileNode(fieldKey)
- for fn in nodeMgr.eachObject(fieldNode) do
+ for fn in fieldNode:eachObject() do
if fn.type == 'global' and fn.cate == 'type' then
if key == nil
or fn.name == 'any'
@@ -237,7 +235,7 @@ local function getObjectSign(source)
for _, arg in ipairs(source.args) do
local argNode = vm.compileNode(arg)
if arg.optional then
- argNode = nodeMgr.addOptional(argNode)
+ argNode:addOptional()
end
source._sign:addSign(argNode)
end
@@ -257,7 +255,7 @@ local function getObjectSign(source)
for _, arg in ipairs(source.args) do
local argNode = vm.compileNode(arg.extends)
if arg.optional then
- argNode = nodeMgr.addOptional(argNode)
+ argNode:addOptional()
end
source._sign:addSign(argNode)
end
@@ -296,16 +294,17 @@ function vm.getReturnOfFunction(func, index)
end
end
+---@return vm.node
local function getReturnOfSetMetaTable(args)
local tbl = args[1]
local mt = args[2]
- local node = union()
+ local node = vm.createNode()
if tbl then
node:merge(vm.compileNode(tbl))
end
if mt then
vm.compileByParentNode(mt, '__index', function (src)
- for n in nodeMgr.eachObject(vm.compileNode(src)) do
+ for n in vm.compileNode(src):eachObject() do
if n.type == 'global'
or n.type == 'local'
or n.type == 'table'
@@ -318,6 +317,7 @@ local function getReturnOfSetMetaTable(args)
return node
end
+---@return vm.node?
local function getReturn(func, index, args)
if func.special == 'setmetatable' then
if not args then
@@ -369,29 +369,27 @@ local function getReturn(func, index, args)
return vm.compileNode(ast)
end
local node = vm.compileNode(func)
- ---@type vm.union
+ ---@type vm.node?
local result
- if node then
- for cnode in nodeMgr.eachObject(node) do
- if cnode.type == 'function'
- or cnode.type == 'doc.type.function' then
- local returnObject = vm.getReturnOfFunction(cnode, index)
- local returnNode = vm.compileNode(returnObject)
- if returnNode then
- for rnode in nodeMgr.eachObject(returnNode) do
- if rnode.type == 'generic' then
- returnNode = rnode:resolve(guide.getUri(func), args)
- break
- end
+ for cnode in node:eachObject() do
+ if cnode.type == 'function'
+ or cnode.type == 'doc.type.function' then
+ local returnObject = vm.getReturnOfFunction(cnode, index)
+ local returnNode = vm.compileNode(returnObject)
+ if returnNode then
+ for rnode in returnNode:eachObject() do
+ if rnode.type == 'generic' then
+ returnNode = rnode:resolve(guide.getUri(func), args)
+ break
end
end
- if returnNode then
- for rnode in nodeMgr.eachObject(returnNode) do
- -- TODO: narrow type
- if rnode.type ~= 'doc.generic.name' then
- result = result or union()
- result:merge(rnode)
- end
+ end
+ if returnNode then
+ for rnode in returnNode:eachObject() do
+ -- TODO: narrow type
+ if rnode.type ~= 'doc.generic.name' then
+ result = result or vm.createNode()
+ result:merge(rnode)
end
end
end
@@ -408,7 +406,7 @@ local function bindDocs(source)
local doc = docs[i]
if doc.type == 'doc.type' then
if not isParam then
- nodeMgr.setNode(source, vm.compileNode(doc))
+ vm.setNode(source, vm.compileNode(doc))
return true
end
end
@@ -417,13 +415,13 @@ local function bindDocs(source)
or (source._globalNode and guide.isSet(source))
or source.type == 'tablefield'
or source.type == 'tableindex' then
- nodeMgr.setNode(source, vm.compileNode(doc))
+ vm.setNode(source, vm.compileNode(doc))
return true
end
end
if doc.type == 'doc.param' then
if isParam and source[1] == doc.param[1] then
- nodeMgr.setNode(source, vm.compileNode(doc))
+ vm.setNode(source, vm.compileNode(doc))
return true
end
end
@@ -438,7 +436,7 @@ local function bindDocs(source)
if not ast then
return nil
end
- nodeMgr.setNode(source, vm.compileNode(ast))
+ vm.setNode(source, vm.compileNode(ast))
return true
end
end
@@ -455,14 +453,14 @@ local function compileByLocalID(source)
if src.bindDocs then
if bindDocs(src) then
hasMarkDoc = true
- nodeMgr.setNode(source, vm.compileNode(src))
+ vm.setNode(source, vm.compileNode(src))
end
end
end
for _, src in ipairs(sources) do
if src.value then
if not hasMarkDoc or guide.isLiteral(src.value) then
- nodeMgr.setNode(source, vm.compileNode(src.value))
+ vm.setNode(source, vm.compileNode(src.value))
end
end
end
@@ -477,11 +475,12 @@ function vm.compileByParentNode(source, key, pushResult)
return
end
local suri = guide.getUri(source)
- for node in nodeMgr.eachObject(parentNode) do
+ for node in parentNode:eachObject() do
searchFieldSwitch(node.type, suri, node, key, pushResult)
end
end
+---@return vm.node?
local function selectNode(source, list, index)
if not list then
return nil
@@ -508,14 +507,17 @@ local function selectNode(source, list, index)
local result
if exp.type == 'call' then
result = getReturn(exp.node, index, exp.args)
+ if not result then
+ return nil
+ end
else
result = vm.compileNode(exp)
end
if source.type == 'function.return' then
-- remove any for returns
- local rtnNode = union()
+ local rtnNode = vm.createNode()
local hasKnownType
- for n in nodeMgr.eachObject(result) do
+ for n in result:eachObject() do
if guide.isLiteral(n) then
hasKnownType = true
rtnNode:merge(n)
@@ -533,9 +535,11 @@ local function selectNode(source, list, index)
if not hasKnownType then
rtnNode:merge(globalMgr.getGlobal('type', 'unknown'))
end
- return nodeMgr.setNode(source, rtnNode)
+ vm.setNode(source, rtnNode)
+ return rtnNode
end
- return nodeMgr.setNode(source, result)
+ vm.setNode(source, result)
+ return result
end
---@param source parser.object
@@ -583,6 +587,9 @@ local function compileCallArgNode(arg, call, callNode, fixIndex, myIndex)
if call.args then
for i = 1, 2 do
local eventArg = call.args[i + fixIndex]
+ if not eventArg then
+ break
+ end
eventMap = vm.getLiterals(eventArg)
if eventMap then
eventIndex = i
@@ -591,27 +598,29 @@ local function compileCallArgNode(arg, call, callNode, fixIndex, myIndex)
end
end
- for n in nodeMgr.eachObject(callNode) do
+ for n in callNode:eachObject() do
if n.type == 'function' then
local farg = getFuncArg(n, myIndex)
- for fn in nodeMgr.eachObject(vm.compileNode(farg)) do
+ for fn in vm.compileNode(farg):eachObject() do
if isValidCallArgNode(arg, fn) then
- nodeMgr.setNode(arg, fn)
+ vm.setNode(arg, fn)
end
end
end
if n.type == 'doc.type.function' then
- local argNode = vm.compileNode(n.args[eventIndex])
- local event = argNode and argNode[1]
- if not event
- or not eventMap
- or myIndex <= eventIndex
- or event.type ~= 'doc.type.string'
- or eventMap[event[1]] then
- local farg = getFuncArg(n, myIndex)
- for fn in nodeMgr.eachObject(vm.compileNode(farg)) do
- if isValidCallArgNode(arg, fn) then
- nodeMgr.setNode(arg, fn)
+ if n.args[eventIndex] then
+ local argNode = vm.compileNode(n.args[eventIndex])
+ local event = argNode and argNode[1]
+ if not event
+ or not eventMap
+ or myIndex <= eventIndex
+ or event.type ~= 'doc.type.string'
+ or eventMap[event[1]] then
+ local farg = getFuncArg(n, myIndex)
+ for fn in vm.compileNode(farg):eachObject() do
+ if isValidCallArgNode(arg, fn) then
+ vm.setNode(arg, fn)
+ end
end
end
end
@@ -641,7 +650,7 @@ function vm.compileCallArg(arg, call, index)
callNode = vm.compileNode(call.args[1])
compileCallArgNode(arg, call, callNode, fixIndex, index - fixIndex)
end
- return nodeMgr.getNode(arg)
+ return vm.getNode(arg)
end
local compilerSwitch = util.switch()
@@ -654,11 +663,11 @@ local compilerSwitch = util.switch()
: case 'doc.type.table'
: case 'doc.type.array'
: call(function (source)
- nodeMgr.setNode(source, source)
+ vm.setNode(source, source)
end)
: case 'table'
: call(function (source)
- nodeMgr.setNode(source, source)
+ vm.setNode(source, source)
if source.parent.type == 'callargs' then
local call = source.parent.parent
@@ -672,17 +681,17 @@ local compilerSwitch = util.switch()
or source.parent.type == 'tableindex'
or source.parent.type == 'setfield'
or source.parent.type == 'setindex' then
- nodeMgr.setNode(source, vm.compileNode(source.parent))
+ vm.setNode(source, vm.compileNode(source.parent))
end
end)
: case 'function'
: call(function (source)
- nodeMgr.setNode(source, source)
+ vm.setNode(source, source)
if source.bindDocs then
for _, doc in ipairs(source.bindDocs) do
if doc.type == 'doc.overload' then
- nodeMgr.setNode(source, vm.compileNode(doc))
+ vm.setNode(source, vm.compileNode(doc))
end
end
end
@@ -695,12 +704,11 @@ local compilerSwitch = util.switch()
end)
: case 'paren'
: call(function (source)
- nodeMgr.setNode(source, vm.compileNode(source.exp))
+ vm.setNode(source, vm.compileNode(source.exp))
end)
: case 'local'
: call(function (source)
- --localMgr.declareLocal(source)
- nodeMgr.setNode(source, source)
+ vm.setNode(source, source)
local hasMarkDoc
if source.bindDocs then
hasMarkDoc = bindDocs(source)
@@ -708,14 +716,14 @@ local compilerSwitch = util.switch()
local hasMarkParam
if source.dummy and not hasMarkDoc then
hasMarkParam = true
- nodeMgr.setNode(source, vm.compileNode(source.method.node))
+ vm.setNode(source, vm.compileNode(source.method.node))
end
if source.value then
if not hasMarkDoc or guide.isLiteral(source.value) then
if source.value and source.value.type == 'table' then
- nodeMgr.setNode(source, source.value)
+ vm.setNode(source, source.value)
else
- nodeMgr.setNode(source, vm.compileNode(source.value))
+ vm.setNode(source, vm.compileNode(source.value))
end
end
end
@@ -726,9 +734,9 @@ local compilerSwitch = util.switch()
for _, ref in ipairs(source.ref) do
if ref.type == 'setlocal' then
if ref.value and ref.value.type == 'table' then
- nodeMgr.setNode(source, ref.value)
+ vm.setNode(source, ref.value)
else
- nodeMgr.setNode(source, vm.compileNode(ref.value))
+ vm.setNode(source, vm.compileNode(ref.value))
end
end
end
@@ -742,25 +750,25 @@ local compilerSwitch = util.switch()
local setfield = source.parent.parent.parent
if setfield.type == 'setfield' then
hasMarkParam = true
- nodeMgr.setNode(source, vm.compileNode(setfield.node))
+ vm.setNode(source, vm.compileNode(setfield.node))
end
end
if source.parent.type == 'funcargs' and not hasMarkDoc and not hasMarkParam then
local func = source.parent.parent
local funcNode = vm.compileNode(func)
local hasDocArg
- for n in nodeMgr.eachObject(funcNode) do
+ for n in funcNode:eachObject() do
if n.type == 'doc.type.function' then
for index, arg in ipairs(n.args) do
if func.args[index] == source then
- nodeMgr.setNode(source, vm.compileNode(arg))
+ vm.setNode(source, vm.compileNode(arg))
hasDocArg = true
end
end
end
end
if not hasDocArg then
- nodeMgr.setNode(source, globalMgr.getGlobal('type', 'any'))
+ vm.setNode(source, globalMgr.getGlobal('type', 'any'))
end
end
-- for x in ... do
@@ -770,13 +778,13 @@ local compilerSwitch = util.switch()
-- for x = ... do
if source.parent.type == 'loop' then
- nodeMgr.setNode(source, globalMgr.getGlobal('type', 'integer'))
+ vm.setNode(source, globalMgr.getGlobal('type', 'integer'))
end
end)
: case 'setlocal'
: case 'getlocal'
: call(function (source)
- nodeMgr.setNode(source, vm.compileNode(source.node), true)
+ vm.setNode(source, vm.compileNode(source.node), true)
end)
: case 'setfield'
: case 'setmethod'
@@ -790,7 +798,7 @@ local compilerSwitch = util.switch()
vm.compileByParentNode(source.node, key, function (src)
if src.type == 'doc.type.field'
or src.type == 'doc.field' then
- nodeMgr.setNode(source, vm.compileNode(src))
+ vm.setNode(source, vm.compileNode(src))
end
end)
end)
@@ -809,10 +817,12 @@ local compilerSwitch = util.switch()
if type(key) == 'table' then
local uri = guide.getUri(source)
local value = vm.getTableValue(uri, vm.compileNode(source.node), key)
- nodeMgr.setNode(source, value)
+ if value then
+ vm.setNode(source, value)
+ end
else
vm.compileByParentNode(source.node, key, function (src)
- nodeMgr.setNode(source, vm.compileNode(src))
+ vm.setNode(source, vm.compileNode(src))
end)
end
end)
@@ -825,7 +835,7 @@ local compilerSwitch = util.switch()
vm.compileByParentNode(source.node, key, function (src)
if src.type == 'doc.type.field'
or src.type == 'doc.field' then
- nodeMgr.setNode(source, vm.compileNode(src))
+ vm.setNode(source, vm.compileNode(src))
end
end)
end)
@@ -836,7 +846,7 @@ local compilerSwitch = util.switch()
end
local key = guide.getKeyName(source)
vm.compileByParentNode(source.node, key, function (src)
- nodeMgr.setNode(source, vm.compileNode(src))
+ vm.setNode(source, vm.compileNode(src))
end)
end)
: case 'tablefield'
@@ -850,27 +860,27 @@ local compilerSwitch = util.switch()
if source.value then
if not hasMarkDoc or guide.isLiteral(source.value) then
if source.value and source.value.type == 'table' then
- nodeMgr.setNode(source, source.value)
+ vm.setNode(source, source.value)
else
- nodeMgr.setNode(source, vm.compileNode(source.value))
+ vm.setNode(source, vm.compileNode(source.value))
end
end
end
if not hasMarkDoc then
vm.compileByParentNode(source.parent, guide.getKeyName(source), function (src)
- nodeMgr.setNode(source, vm.compileNode(src))
+ vm.setNode(source, vm.compileNode(src))
end)
end
end)
: case 'field'
: case 'method'
: call(function (source)
- nodeMgr.setNode(source, vm.compileNode(source.parent))
+ vm.setNode(source, vm.compileNode(source.parent))
end)
: case 'tableexp'
: call(function (source)
- nodeMgr.setNode(source, vm.compileNode(source.value))
+ vm.setNode(source, vm.compileNode(source.value))
end)
: case 'function.return'
: call(function (source)
@@ -891,9 +901,9 @@ local compilerSwitch = util.switch()
end)
end
if hasGeneric then
- nodeMgr.setNode(source, genericMgr(rtn, sign))
+ vm.setNode(source, genericMgr(rtn, sign))
else
- nodeMgr.setNode(source, vm.compileNode(rtn))
+ vm.setNode(source, vm.compileNode(rtn))
end
end
end
@@ -910,7 +920,7 @@ local compilerSwitch = util.switch()
: call(function (source)
if source.returns then
for _, rtn in ipairs(source.returns) do
- nodeMgr.setNode(source, vm.compileNode(rtn[1]))
+ vm.setNode(source, vm.compileNode(rtn[1]))
end
end
end)
@@ -922,22 +932,22 @@ local compilerSwitch = util.switch()
if not node then
return
end
- for n in nodeMgr.eachObject(node) do
+ for n in node:eachObject() do
if n.type == 'global'
and n.cate == 'type'
and n.name == '...' then
return
end
end
- nodeMgr.setNode(source, node)
+ vm.setNode(source, node)
end
if vararg.type == 'varargs' then
- nodeMgr.setNode(source, vm.compileNode(vararg))
+ vm.setNode(source, vm.compileNode(vararg))
end
end)
: case 'varargs'
: call(function (source)
- nodeMgr.setNode(source, vm.compileNode(source.node))
+ vm.setNode(source, vm.compileNode(source.node))
end)
: case 'call'
: call(function (source)
@@ -945,14 +955,14 @@ local compilerSwitch = util.switch()
if not node then
return
end
- for n in nodeMgr.eachObject(node) do
+ for n in node:eachObject() do
if n.type == 'global'
and n.cate == 'type'
and n.name == '...' then
return
end
end
- nodeMgr.setNode(source, node)
+ vm.setNode(source, node)
end)
: case 'in'
: call(function (source)
@@ -972,31 +982,33 @@ local compilerSwitch = util.switch()
if source.keys then
for i, loc in ipairs(source.keys) do
local node = getReturn(source._iterator, i, source._iterArgs)
- nodeMgr.setNode(loc, node)
+ if node then
+ vm.setNode(loc, node)
+ end
end
end
end)
: case 'doc.type'
: call(function (source)
for _, typeUnit in ipairs(source.types) do
- nodeMgr.setNode(source, vm.compileNode(typeUnit))
+ vm.setNode(source, vm.compileNode(typeUnit))
end
end)
: case 'doc.type.integer'
: case 'doc.type.string'
: case 'doc.type.boolean'
: call(function (source)
- nodeMgr.setNode(source, source)
+ vm.setNode(source, source)
end)
: case 'doc.generic.name'
: call(function (source)
- nodeMgr.setNode(source, source)
+ vm.setNode(source, source)
end)
: case 'doc.type.name'
: call(function (source)
if source.signs then
local uri = guide.getUri(source)
- nodeMgr.setNode(source, source)
+ vm.setNode(source, source)
local global = globalMgr.getGlobal('type', source[1])
for _, set in ipairs(global:getSets(uri)) do
if set.type == 'doc.class' then
@@ -1005,7 +1017,7 @@ local compilerSwitch = util.switch()
if ext.type == 'doc.type.table' then
if ext._generic then
local resolved = ext._generic:resolve(uri, source.signs)
- nodeMgr.setNode(source, resolved)
+ vm.setNode(source, resolved)
end
end
end
@@ -1014,7 +1026,7 @@ local compilerSwitch = util.switch()
if set.type == 'doc.alias' then
if set.extends._generic then
local resolved = set.extends._generic:resolve(uri, source.signs)
- nodeMgr.setNode(source, resolved)
+ vm.setNode(source, resolved)
end
end
end
@@ -1022,23 +1034,23 @@ local compilerSwitch = util.switch()
end)
: case 'doc.class.name'
: call(function (source)
- nodeMgr.setNode(source, vm.compileNode(source.parent))
+ vm.setNode(source, vm.compileNode(source.parent))
end)
: case 'doc.field'
: call(function (source)
- nodeMgr.setNode(source, vm.compileNode(source.extends))
+ vm.setNode(source, vm.compileNode(source.extends))
end)
: case 'doc.type.field'
: call(function (source)
- nodeMgr.setNode(source, vm.compileNode(source.extends))
+ vm.setNode(source, vm.compileNode(source.extends))
end)
: case 'doc.param'
: call(function (source)
- nodeMgr.setNode(source, vm.compileNode(source.extends))
+ vm.setNode(source, vm.compileNode(source.extends))
end)
: case 'doc.vararg'
: call(function (source)
- nodeMgr.setNode(source, vm.compileNode(source.vararg))
+ vm.setNode(source, vm.compileNode(source.vararg))
end)
: case '...'
: call(function (source)
@@ -1051,45 +1063,45 @@ local compilerSwitch = util.switch()
end
for _, doc in ipairs(func.bindDocs) do
if doc.type == 'doc.vararg' then
- nodeMgr.setNode(source, vm.compileNode(doc))
+ vm.setNode(source, vm.compileNode(doc))
end
if doc.type == 'doc.param' and doc.param[1] == '...' then
- nodeMgr.setNode(source, vm.compileNode(doc))
+ vm.setNode(source, vm.compileNode(doc))
end
end
end)
: case 'doc.overload'
: call(function (source)
- nodeMgr.setNode(source, vm.compileNode(source.overload))
+ vm.setNode(source, vm.compileNode(source.overload))
end)
: case 'doc.see.name'
: call(function (source)
local type = globalMgr.getGlobal('type', source[1])
if type then
- nodeMgr.setNode(source, vm.compileNode(type))
+ vm.setNode(source, vm.compileNode(type))
end
end)
: case 'doc.type.arg'
: call(function (source)
if source.extends then
- nodeMgr.setNode(source, vm.compileNode(source.extends))
+ vm.setNode(source, vm.compileNode(source.extends))
else
- nodeMgr.setNode(source, globalMgr.getGlobal('type', 'any'))
+ vm.setNode(source, globalMgr.getGlobal('type', 'any'))
end
end)
: case 'generic'
: call(function (source)
- nodeMgr.setNode(source, source)
+ vm.setNode(source, source)
end)
: case 'unary'
: call(function (source)
if source.op.type == 'not' then
local result = vm.test(source[1])
if result == nil then
- nodeMgr.setNode(source, globalMgr.getGlobal('type', 'boolean'))
+ vm.setNode(source, globalMgr.getGlobal('type', 'boolean'))
return
else
- nodeMgr.setNode(source, {
+ vm.setNode(source, {
type = 'boolean',
start = source.start,
finish = source.finish,
@@ -1100,16 +1112,16 @@ local compilerSwitch = util.switch()
end
end
if source.op.type == '#' then
- nodeMgr.setNode(source, globalMgr.getGlobal('type', 'integer'))
+ vm.setNode(source, globalMgr.getGlobal('type', 'integer'))
return
end
if source.op.type == '-' then
local v = vm.getNumber(source[1])
if v == nil then
- nodeMgr.setNode(source, globalMgr.getGlobal('type', 'number'))
+ vm.setNode(source, globalMgr.getGlobal('type', 'number'))
return
else
- nodeMgr.setNode(source, {
+ vm.setNode(source, {
type = 'number',
start = source.start,
finish = source.finish,
@@ -1122,10 +1134,10 @@ local compilerSwitch = util.switch()
if source.op.type == '~' then
local v = vm.getInteger(source[1])
if v == nil then
- nodeMgr.setNode(source, globalMgr.getGlobal('type', 'integer'))
+ vm.setNode(source, globalMgr.getGlobal('type', 'integer'))
return
else
- nodeMgr.setNode(source, {
+ vm.setNode(source, {
type = 'integer',
start = source.start,
finish = source.finish,
@@ -1141,11 +1153,11 @@ local compilerSwitch = util.switch()
if source.op.type == 'and' then
local r1 = vm.test(source[1])
if r1 == true then
- nodeMgr.setNode(source, vm.compileNode(source[2]))
+ vm.setNode(source, vm.compileNode(source[2]))
return
end
if r1 == false then
- nodeMgr.setNode(source, vm.compileNode(source[1]))
+ vm.setNode(source, vm.compileNode(source[1]))
return
end
return
@@ -1153,11 +1165,11 @@ local compilerSwitch = util.switch()
if source.op.type == 'or' then
local r1 = vm.test(source[1])
if r1 == true then
- nodeMgr.setNode(source, vm.compileNode(source[1]))
+ vm.setNode(source, vm.compileNode(source[1]))
return
end
if r1 == false then
- nodeMgr.setNode(source, vm.compileNode(source[2]))
+ vm.setNode(source, vm.compileNode(source[2]))
return
end
return
@@ -1165,10 +1177,10 @@ local compilerSwitch = util.switch()
if source.op.type == '==' then
local result = vm.equal(source[1], source[2])
if result == nil then
- nodeMgr.setNode(source, globalMgr.getGlobal('type', 'boolean'))
+ vm.setNode(source, globalMgr.getGlobal('type', 'boolean'))
return
else
- nodeMgr.setNode(source, {
+ vm.setNode(source, {
type = 'boolean',
start = source.start,
finish = source.finish,
@@ -1181,10 +1193,10 @@ local compilerSwitch = util.switch()
if source.op.type == '~=' then
local result = vm.equal(source[1], source[2])
if result == nil then
- nodeMgr.setNode(source, globalMgr.getGlobal('type', 'boolean'))
+ vm.setNode(source, globalMgr.getGlobal('type', 'boolean'))
return
else
- nodeMgr.setNode(source, {
+ vm.setNode(source, {
type = 'boolean',
start = source.start,
finish = source.finish,
@@ -1198,7 +1210,7 @@ local compilerSwitch = util.switch()
local a = vm.getInteger(source[1])
local b = vm.getInteger(source[2])
if a and b then
- nodeMgr.setNode(source, {
+ vm.setNode(source, {
type = 'integer',
start = source.start,
finish = source.finish,
@@ -1207,7 +1219,7 @@ local compilerSwitch = util.switch()
})
return
else
- nodeMgr.setNode(source, globalMgr.getGlobal('type', 'integer'))
+ vm.setNode(source, globalMgr.getGlobal('type', 'integer'))
return
end
end
@@ -1215,7 +1227,7 @@ local compilerSwitch = util.switch()
local a = vm.getInteger(source[1])
local b = vm.getInteger(source[2])
if a and b then
- nodeMgr.setNode(source, {
+ vm.setNode(source, {
type = 'integer',
start = source.start,
finish = source.finish,
@@ -1224,7 +1236,7 @@ local compilerSwitch = util.switch()
})
return
else
- nodeMgr.setNode(source, globalMgr.getGlobal('type', 'integer'))
+ vm.setNode(source, globalMgr.getGlobal('type', 'integer'))
return
end
end
@@ -1232,7 +1244,7 @@ local compilerSwitch = util.switch()
local a = vm.getInteger(source[1])
local b = vm.getInteger(source[2])
if a and b then
- nodeMgr.setNode(source, {
+ vm.setNode(source, {
type = 'integer',
start = source.start,
finish = source.finish,
@@ -1241,7 +1253,7 @@ local compilerSwitch = util.switch()
})
return
else
- nodeMgr.setNode(source, globalMgr.getGlobal('type', 'integer'))
+ vm.setNode(source, globalMgr.getGlobal('type', 'integer'))
return
end
end
@@ -1249,7 +1261,7 @@ local compilerSwitch = util.switch()
local a = vm.getInteger(source[1])
local b = vm.getInteger(source[2])
if a and b then
- nodeMgr.setNode(source, {
+ vm.setNode(source, {
type = 'integer',
start = source.start,
finish = source.finish,
@@ -1258,7 +1270,7 @@ local compilerSwitch = util.switch()
})
return
else
- nodeMgr.setNode(source, globalMgr.getGlobal('type', 'integer'))
+ vm.setNode(source, globalMgr.getGlobal('type', 'integer'))
return
end
end
@@ -1266,7 +1278,7 @@ local compilerSwitch = util.switch()
local a = vm.getInteger(source[1])
local b = vm.getInteger(source[2])
if a and b then
- nodeMgr.setNode(source, {
+ vm.setNode(source, {
type = 'integer',
start = source.start,
finish = source.finish,
@@ -1275,7 +1287,7 @@ local compilerSwitch = util.switch()
})
return
else
- nodeMgr.setNode(source, globalMgr.getGlobal('type', 'integer'))
+ vm.setNode(source, globalMgr.getGlobal('type', 'integer'))
return
end
end
@@ -1284,7 +1296,7 @@ local compilerSwitch = util.switch()
local b = vm.getNumber(source[2])
if a and b then
local result = a + b
- nodeMgr.setNode(source, {
+ vm.setNode(source, {
type = math.type(result) == 'integer' and 'integer' or 'number',
start = source.start,
finish = source.finish,
@@ -1293,7 +1305,7 @@ local compilerSwitch = util.switch()
})
return
else
- nodeMgr.setNode(source, globalMgr.getGlobal('type', 'number'))
+ vm.setNode(source, globalMgr.getGlobal('type', 'number'))
return
end
end
@@ -1302,7 +1314,7 @@ local compilerSwitch = util.switch()
local b = vm.getNumber(source[2])
if a and b then
local result = a - b
- nodeMgr.setNode(source, {
+ vm.setNode(source, {
type = math.type(result) == 'integer' and 'integer' or 'number',
start = source.start,
finish = source.finish,
@@ -1311,7 +1323,7 @@ local compilerSwitch = util.switch()
})
return
else
- nodeMgr.setNode(source, globalMgr.getGlobal('type', 'number'))
+ vm.setNode(source, globalMgr.getGlobal('type', 'number'))
return
end
end
@@ -1320,7 +1332,7 @@ local compilerSwitch = util.switch()
local b = vm.getNumber(source[2])
if a and b then
local result = a * b
- nodeMgr.setNode(source, {
+ vm.setNode(source, {
type = math.type(result) == 'integer' and 'integer' or 'number',
start = source.start,
finish = source.finish,
@@ -1329,7 +1341,7 @@ local compilerSwitch = util.switch()
})
return
else
- nodeMgr.setNode(source, globalMgr.getGlobal('type', 'number'))
+ vm.setNode(source, globalMgr.getGlobal('type', 'number'))
return
end
end
@@ -1337,7 +1349,7 @@ local compilerSwitch = util.switch()
local a = vm.getNumber(source[1])
local b = vm.getNumber(source[2])
if a and b then
- nodeMgr.setNode(source, {
+ vm.setNode(source, {
type = 'number',
start = source.start,
finish = source.finish,
@@ -1346,7 +1358,7 @@ local compilerSwitch = util.switch()
})
return
else
- nodeMgr.setNode(source, globalMgr.getGlobal('type', 'number'))
+ vm.setNode(source, globalMgr.getGlobal('type', 'number'))
return
end
end
@@ -1355,7 +1367,7 @@ local compilerSwitch = util.switch()
local b = vm.getNumber(source[2])
if a and b then
local result = a % b
- nodeMgr.setNode(source, {
+ vm.setNode(source, {
type = math.type(result) == 'integer' and 'integer' or 'number',
start = source.start,
finish = source.finish,
@@ -1364,7 +1376,7 @@ local compilerSwitch = util.switch()
})
return
else
- nodeMgr.setNode(source, globalMgr.getGlobal('type', 'number'))
+ vm.setNode(source, globalMgr.getGlobal('type', 'number'))
return
end
end
@@ -1372,7 +1384,7 @@ local compilerSwitch = util.switch()
local a = vm.getNumber(source[1])
local b = vm.getNumber(source[2])
if a and b then
- nodeMgr.setNode(source, {
+ vm.setNode(source, {
type = 'number',
start = source.start,
finish = source.finish,
@@ -1381,7 +1393,7 @@ local compilerSwitch = util.switch()
})
return
else
- nodeMgr.setNode(source, globalMgr.getGlobal('type', 'number'))
+ vm.setNode(source, globalMgr.getGlobal('type', 'number'))
return
end
end
@@ -1390,7 +1402,7 @@ local compilerSwitch = util.switch()
local b = vm.getNumber(source[2])
if a and b and b ~= 0 then
local result = a // b
- nodeMgr.setNode(source, {
+ vm.setNode(source, {
type = math.type(result) == 'integer' and 'integer' or 'number',
start = source.start,
finish = source.finish,
@@ -1399,7 +1411,7 @@ local compilerSwitch = util.switch()
})
return
else
- nodeMgr.setNode(source, globalMgr.getGlobal('type', 'number'))
+ vm.setNode(source, globalMgr.getGlobal('type', 'number'))
return
end
end
@@ -1427,7 +1439,7 @@ local compilerSwitch = util.switch()
end
end
end
- nodeMgr.setNode(source, {
+ vm.setNode(source, {
type = 'string',
start = source.start,
finish = source.finish,
@@ -1436,7 +1448,7 @@ local compilerSwitch = util.switch()
})
return
else
- nodeMgr.setNode(source, globalMgr.getGlobal('type', 'string'))
+ vm.setNode(source, globalMgr.getGlobal('type', 'string'))
return
end
end
@@ -1451,13 +1463,13 @@ end
local function compileByGlobal(uri, source)
uri = uri or guide.getUri(source)
if source.type == 'global' then
- nodeMgr.setNode(source, source)
+ vm.setNode(source, source)
if source.cate == 'variable' then
local hasMarkDoc
for _, set in ipairs(source:getSets(uri)) do
if set.bindDocs then
if bindDocs(set) then
- nodeMgr.setNode(source, vm.compileNode(set))
+ vm.setNode(source, vm.compileNode(set))
hasMarkDoc = true
end
end
@@ -1465,7 +1477,7 @@ local function compileByGlobal(uri, source)
for _, set in ipairs(source:getSets(uri)) do
if set.value then
if not hasMarkDoc or guide.isLiteral(set.value) then
- nodeMgr.setNode(source, vm.compileNode(set.value))
+ vm.setNode(source, vm.compileNode(set.value))
end
end
end
@@ -1477,7 +1489,7 @@ local function compileByGlobal(uri, source)
for _, ext in ipairs(set.extends) do
if ext.type == 'doc.type.table' then
if not ext._generic then
- nodeMgr.setNode(source, vm.compileNode(ext))
+ vm.setNode(source, vm.compileNode(ext))
end
end
end
@@ -1485,7 +1497,7 @@ local function compileByGlobal(uri, source)
end
if set.type == 'doc.alias' then
if not set.extends._generic then
- nodeMgr.setNode(source, vm.compileNode(set.extends))
+ vm.setNode(source, vm.compileNode(set.extends))
end
end
end
@@ -1493,7 +1505,7 @@ local function compileByGlobal(uri, source)
return
end
if source._globalNode then
- nodeMgr.setNode(source, vm.compileNode(source._globalNode, uri))
+ vm.setNode(source, vm.compileNode(source._globalNode, uri))
return
end
end
@@ -1509,7 +1521,9 @@ function vm.resumeCache()
pauseCacheCount = pauseCacheCount - 1
if pauseCacheCount == 0 then
for source in pairs(originCacheKeys) do
- nodeMgr.nodeCache[source] = originCacheValues[source]
+ if originCacheValues[source] then
+ vm.setNode(source, originCacheValues[source], true)
+ end
originCacheKeys[source] = nil
originCacheValues[source] = nil
end
@@ -1521,23 +1535,22 @@ end
---@return vm.node
function vm.compileNode(source, uri)
if not source then
- return false
+ error('Can not compile nil node')
end
- if nodeMgr.nodeCache[source] ~= nil then
- return nodeMgr.nodeCache[source]
+ local cache = vm.getNode(source)
+ if cache ~= nil then
+ return cache
end
local pauseCache = pauseCacheCount > 0
if pauseCache and not originCacheKeys[source] then
originCacheKeys[source] = true
- originCacheValues[source] = nodeMgr.nodeCache[source]
+ originCacheValues[source] = cache
end
- nodeMgr.nodeCache[source] = false
+ vm.setNode(source, vm.createNode(), true)
compileByGlobal(uri, source)
compileByNode(source)
- --localMgr.subscribeLocal(source, source._node)
-
- return nodeMgr.nodeCache[source]
+ return vm.getNode(source)
end
diff --git a/script/vm/def.lua b/script/vm/def.lua
index 40dcc9f0..9efb3e90 100644
--- a/script/vm/def.lua
+++ b/script/vm/def.lua
@@ -4,7 +4,6 @@ local util = require 'utility'
local guide = require 'parser.guide'
local localID = require 'vm.local-id'
local globalMgr = require 'vm.global-manager'
-local nodeMgr = require 'vm.node'
local simpleSwitch
@@ -145,7 +144,7 @@ local nodeSwitch = util.switch()
end
local uri = guide.getUri(source)
local key = guide.getKeyName(source)
- for pn in nodeMgr.eachObject(parentNode) do
+ for pn in parentNode:eachObject() do
searchFieldSwitch(pn.type, uri, pn, key, pushResult)
end
end)
@@ -163,7 +162,7 @@ local nodeSwitch = util.switch()
return
end
local uri = guide.getUri(source)
- for pn in nodeMgr.eachObject(parentNode) do
+ for pn in parentNode:eachObject() do
searchFieldSwitch(pn.type, uri, pn, source[1], pushResult)
end
end)
@@ -200,7 +199,7 @@ local function searchByNode(source, pushResult)
return
end
local suri = guide.getUri(source)
- for n in nodeMgr.eachObject(node) do
+ for n in node:eachObject() do
if n.type == 'global' then
for _, set in ipairs(n:getSets(suri)) do
pushResult(set)
diff --git a/script/vm/generic.lua b/script/vm/generic.lua
index 37d2bd13..b3981ff8 100644
--- a/script/vm/generic.lua
+++ b/script/vm/generic.lua
@@ -1,5 +1,3 @@
-local nodeMgr = require 'vm.node'
-local union = require 'vm.union'
local vm = require 'vm.vm'
---@class parser.object
@@ -14,7 +12,7 @@ mt.type = 'generic'
---@param source parser.object
---@param resolved? table<string, vm.node>
----@return parser.object | vm.union
+---@return parser.object | vm.node
local function cloneObject(source, resolved)
if not resolved then
return source
@@ -28,7 +26,9 @@ local function cloneObject(source, resolved)
parent = source.parent,
[1] = source[1],
}
- nodeMgr.setNode(newName, resolved[key], true)
+ if resolved[key] then
+ vm.setNode(newName, resolved[key], true)
+ end
return newName
end
if source.type == 'doc.type' then
@@ -118,8 +118,8 @@ end
function mt:resolve(uri, args)
local resolved = self.sign:resolve(uri, args)
local protoNode = vm.compileNode(self.proto)
- local result = union()
- for nd in nodeMgr.eachObject(protoNode) do
+ local result = vm.createNode()
+ for nd in protoNode:eachObject() do
local clonedNode = vm.compileNode(cloneObject(nd, resolved))
result:merge(clonedNode)
end
diff --git a/script/vm/global-manager.lua b/script/vm/global-manager.lua
index dffc5c73..3f48197f 100644
--- a/script/vm/global-manager.lua
+++ b/script/vm/global-manager.lua
@@ -3,6 +3,8 @@ local guide = require 'parser.guide'
local globalBuilder = require 'vm.global'
local signMgr = require 'vm.sign'
local genericMgr = require 'vm.generic'
+---@class vm
+local vm = require 'vm.vm'
---@class parser.object
---@field _globalNode vm.global
@@ -145,6 +147,7 @@ local compilerGlobalSwitch = util.switch()
end
end)
: case 'doc.class'
+ ---@param source parser.object
: call(function (source)
local uri = guide.getUri(source)
local name = guide.getKeyName(source)
@@ -155,7 +158,7 @@ local compilerGlobalSwitch = util.switch()
if source.signs then
source._sign = signMgr()
for _, sign in ipairs(source.signs) do
- source._sign:addSign(sign)
+ source._sign:addSign(vm.compileNode(sign))
end
if source.extends then
for _, ext in ipairs(source.extends) do
@@ -177,7 +180,7 @@ local compilerGlobalSwitch = util.switch()
if source.signs then
source._sign = signMgr()
for _, sign in ipairs(source.signs) do
- source._sign:addSign(sign)
+ source._sign:addSign(vm.compileNode(sign))
end
source.extends._generic = genericMgr(source.extends, source._sign)
end
diff --git a/script/vm/infer.lua b/script/vm/infer.lua
index ffd6f292..71da6317 100644
--- a/script/vm/infer.lua
+++ b/script/vm/infer.lua
@@ -1,8 +1,6 @@
local util = require 'utility'
-local nodeMgr = require 'vm.node'
local config = require 'config'
local guide = require 'parser.guide'
-local union = require 'vm.union'
local vm = require 'vm.vm'
---@class vm.infer-manager
@@ -163,17 +161,14 @@ function m.getInfer(source)
if not node then
return m.NULL
end
- -- TODO: more cache?
- if node.type == 'vm.union' and node.lastInfer then
+ if node.lastInfer then
return node.lastInfer
end
local infer = setmetatable({
node = node,
uri = guide.getUri(source),
}, mt)
- if node.type == 'vm.union' then
- node.lastInfer = infer
- end
+ node.lastInfer = infer
return infer
end
@@ -203,7 +198,7 @@ end
function mt:_eraseAlias()
local expandAlias = config.get(self.uri, 'Lua.hover.expandAlias')
- for n in nodeMgr.eachObject(self.node) do
+ for n in self.node:eachObject() do
if n.type == 'global' and n.cate == 'type' then
for _, set in ipairs(n:getSets(self.uri)) do
if set.type == 'doc.alias' then
@@ -250,7 +245,7 @@ function mt:_computeViews()
self.views = {}
- for n in nodeMgr.eachObject(self.node) do
+ for n in self.node:eachObject() do
local view = viewNodeSwitch(n.type, n, self)
if view then
self.views[view] = true
@@ -329,7 +324,7 @@ function mt:merge(other)
end
local infer = setmetatable({
- node = union(self.node, other.node),
+ node = vm.createNode(self.node, other.node),
uri = self.uri,
}, mt)
@@ -343,7 +338,7 @@ function mt:viewLiterals()
end
local mark = {}
local literals = {}
- for n in nodeMgr.eachObject(self.node) do
+ for n in self.node:eachObject() do
if n.type == 'string'
or n.type == 'number'
or n.type == 'integer'
@@ -369,7 +364,7 @@ function mt:viewClass()
end
local mark = {}
local class = {}
- for n in nodeMgr.eachObject(self.node) do
+ for n in self.node:eachObject() do
if n.type == 'global' and n.cate == 'type' then
local name = n.name
if not mark[name] then
diff --git a/script/vm/init.lua b/script/vm/init.lua
index 5d32bf28..0058c698 100644
--- a/script/vm/init.lua
+++ b/script/vm/init.lua
@@ -1,11 +1,12 @@
local vm = require 'vm.vm'
-require 'vm.manager'
require 'vm.compiler'
require 'vm.value'
+require 'vm.node'
require 'vm.def'
require 'vm.ref'
require 'vm.field'
require 'vm.doc'
require 'vm.type'
require 'vm.library'
+require 'vm.manager'
return vm
diff --git a/script/vm/local-manager.lua b/script/vm/local-manager.lua
index 9ffee344..2baabed4 100644
--- a/script/vm/local-manager.lua
+++ b/script/vm/local-manager.lua
@@ -26,10 +26,11 @@ end
---@param source parser.object
---@param node vm.node
function m.subscribeLocal(source, node)
+ -- TODO: need delete
if not node then
return
end
- if node.type == 'vm.union' then
+ if node.type == 'vm.node' then
node:subscribeLocal(source)
return
end
diff --git a/script/vm/manager.lua b/script/vm/manager.lua
index 67e8cc38..c9103ff9 100644
--- a/script/vm/manager.lua
+++ b/script/vm/manager.lua
@@ -3,6 +3,8 @@ local files = require 'files'
local globalManager = require 'vm.global-manager'
local localManager = require 'vm.local-manager'
+---@alias vm.object parser.object | vm.global | vm.generic
+
---@class vm.state
local m = {}
for uri in files.eachFile() do
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
diff --git a/script/vm/ref.lua b/script/vm/ref.lua
index e8192c72..360d979e 100644
--- a/script/vm/ref.lua
+++ b/script/vm/ref.lua
@@ -4,7 +4,6 @@ local util = require 'utility'
local guide = require 'parser.guide'
local localID = require 'vm.local-id'
local globalMgr = require 'vm.global-manager'
-local nodeMgr = require 'vm.node'
local files = require 'files'
local await = require 'await'
local progress = require 'progress'
@@ -271,7 +270,7 @@ local function searchByNode(source, pushResult)
return
end
local uri = guide.getUri(source)
- for n in nodeMgr.eachObject(node) do
+ for n in node:eachObject() do
if n.type == 'global' then
for _, get in ipairs(n:getGets(uri)) do
pushResult(get)
diff --git a/script/vm/sign.lua b/script/vm/sign.lua
index 2fac9528..5b97f2b9 100644
--- a/script/vm/sign.lua
+++ b/script/vm/sign.lua
@@ -1,5 +1,4 @@
local guide = require 'parser.guide'
-local nodeMgr = require 'vm.node'
local vm = require 'vm.vm'
---@class vm.sign
@@ -31,19 +30,19 @@ function mt:resolve(uri, args)
local key = typeUnit[1]
if typeUnit.literal then
-- 'number' -> `T`
- for n in nodeMgr.eachObject(node) do
+ for n in node:eachObject() do
if n.type == 'string' then
local type = globalMgr.declareGlobal('type', n[1], guide.getUri(n))
- resolved[key] = nodeMgr.mergeNode(type, resolved[key])
+ resolved[key] = vm.createNode(type, resolved[key])
end
end
else
-- number -> T
- resolved[key] = nodeMgr.mergeNode(node, resolved[key])
+ resolved[key] = vm.createNode(node, resolved[key])
end
end
if typeUnit.type == 'doc.type.array' then
- for n in nodeMgr.eachObject(node) do
+ for n in node:eachObject() do
if n.type == 'doc.type.array' then
-- number[] -> T[]
resolve(typeUnit.node, vm.compileNode(n.node))
@@ -80,11 +79,11 @@ function mt:resolve(uri, args)
if not sign then
break
end
- for n in nodeMgr.eachObject(sign) do
+ for n in sign:eachObject() do
local argNode = vm.compileNode(arg)
if argNode then
if sign.optional then
- argNode = nodeMgr.removeOptional(argNode)
+ argNode:removeOptional()
end
resolve(n, argNode)
end
diff --git a/script/vm/type.lua b/script/vm/type.lua
index 46cc3946..5c8a8088 100644
--- a/script/vm/type.lua
+++ b/script/vm/type.lua
@@ -1,6 +1,4 @@
-local nodeMgr = require 'vm.node'
local globalMgr = require 'vm.global-manager'
-local union = require 'vm.union'
---@class vm
local vm = require 'vm.vm'
@@ -11,10 +9,10 @@ local vm = require 'vm.vm'
---@return boolean
function vm.isSubType(uri, child, parent, mark)
if type(parent) == 'string' then
- parent = globalMgr.getGlobal('type', parent)
+ parent = vm.createNode(globalMgr.getGlobal('type', parent))
end
if type(child) == 'string' then
- child = globalMgr.getGlobal('type', child)
+ child = vm.createNode(globalMgr.getGlobal('type', child))
end
if not child or not parent then
@@ -22,33 +20,33 @@ function vm.isSubType(uri, child, parent, mark)
end
mark = mark or {}
- for childNode in nodeMgr.eachObject(child) do
- if childNode.type ~= 'global'
- or childNode.cate ~= 'type' then
+ for obj in child:eachObject() do
+ if obj.type ~= 'global'
+ or obj.cate ~= 'type' then
goto CONTINUE_CHILD
end
- if mark[childNode.name] then
+ if mark[obj.name] then
return false
end
- mark[childNode.name] = true
- for parentNode in nodeMgr.eachObject(parent) do
+ mark[obj.name] = true
+ for parentNode in parent:eachObject() do
if parentNode.type ~= 'global'
or parentNode.cate ~= 'type' then
goto CONTINUE_PARENT
end
- if parentNode.name == 'any' or childNode.name == 'any' then
+ if parentNode.name == 'any' or obj.name == 'any' then
return true
end
- if parentNode.name == childNode.name then
+ if parentNode.name == obj.name then
return true
end
- for _, set in ipairs(childNode:getSets(uri)) do
+ for _, set in ipairs(obj:getSets(uri)) do
if set.type == 'doc.class' and set.extends then
for _, ext in ipairs(set.extends) do
if ext.type == 'doc.extends.name'
- and vm.isSubType(uri, ext[1], parentNode, mark) then
+ and vm.isSubType(uri, ext[1], parentNode.name, mark) then
return true
end
end
@@ -56,7 +54,7 @@ function vm.isSubType(uri, child, parent, mark)
if set.type == 'doc.alias' and set.extends then
for _, ext in ipairs(set.extends.types) do
if ext.type == 'doc.type.name'
- and vm.isSubType(uri, ext[1], parentNode, mark) then
+ and vm.isSubType(uri, ext[1], parentNode.name, mark) then
return true
end
end
@@ -73,10 +71,10 @@ end
---@param uri uri
---@param tnode vm.node
---@param knode vm.node
----@return vm.union?
+---@return vm.node?
function vm.getTableValue(uri, tnode, knode)
- local result = union()
- for tn in nodeMgr.eachObject(tnode) do
+ local result = vm.createNode()
+ for tn in tnode:eachObject() do
if tn.type == 'doc.type.table' then
for _, field in ipairs(tn.fields) do
if vm.isSubType(uri, vm.compileNode(field.name), knode) then
@@ -114,10 +112,10 @@ end
---@param uri uri
---@param tnode vm.node
---@param vnode vm.node
----@return vm.union?
+---@return vm.node?
function vm.getTableKey(uri, tnode, vnode)
- local result = union()
- for tn in nodeMgr.eachObject(tnode) do
+ local result = vm.createNode()
+ for tn in tnode:eachObject() do
if tn.type == 'doc.type.table' then
for _, field in ipairs(tn.fields) do
if vm.isSubType(uri, vm.compileNode(field.extends), vnode) then
diff --git a/script/vm/union.lua b/script/vm/union.lua
deleted file mode 100644
index f816952a..00000000
--- a/script/vm/union.lua
+++ /dev/null
@@ -1,129 +0,0 @@
-local localMgr = require 'vm.local-manager'
-
----@class vm.union
-local mt = {}
-mt.__index = mt
-mt.type = 'vm.union'
-mt.optional = nil
-mt.lastInfer = nil
-
----@param me vm.node
----@param node vm.node
----@return vm.union
-local function createUnion(me, node)
- local union = setmetatable({}, mt)
- union:merge(me)
- union:merge(node)
- return union
-end
-
----@param node vm.node
-function mt:merge(node)
- if not node then
- return
- end
- if node.type == 'vm.union' 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
- end
-end
-
----@return vm.node
-function mt:copy()
- return createUnion(self, nil)
-end
-
----@return boolean
-function mt:isEmpty()
- return #self == 0
-end
-
----@param source parser.object
-function mt:subscribeLocal(source)
- for _, c in ipairs(self) do
- localMgr.subscribeLocal(source, c)
- end
-end
-
-function mt:eachNode()
- local i = 0
- return function ()
- i = i + 1
- return self[i]
- end
-end
-
----@return vm.union
-function mt:addOptional()
- if self:isOptional() then
- return self
- end
- self.optional = true
- return self
-end
-
----@return vm.union
-function mt:removeOptional()
- self.optional = nil
- if not self:isOptional() then
- return self
- end
- -- copy union
- local newUnion = createUnion()
- for _, n in ipairs(self) do
- if n.type == 'nil' then
- goto CONTINUE
- end
- if n.type == 'boolean' then
- if n[1] == false then
- goto CONTINUE
- end
- end
- if n.type == 'false' then
- goto CONTINUE
- end
- newUnion[#newUnion+1] = n
- ::CONTINUE::
- end
- newUnion.optional = false
- return newUnion
-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 createUnion
diff --git a/script/vm/value.lua b/script/vm/value.lua
index 00912820..5810f8da 100644
--- a/script/vm/value.lua
+++ b/script/vm/value.lua
@@ -1,4 +1,3 @@
-local nodeMgr = require 'vm.node'
local guide = require 'parser.guide'
---@class vm
local vm = require 'vm.vm'
@@ -8,7 +7,7 @@ local vm = require 'vm.vm'
function vm.test(source)
local node = vm.compileNode(source)
local hasTrue, hasFalse
- for n in nodeMgr.eachObject(node) do
+ for n in node:eachObject() do
if n.type == 'boolean' then
if n[1] == true then
hasTrue = true
@@ -81,14 +80,14 @@ function vm.equal(a, b)
local nodeA = vm.compileNode(a)
local nodeB = vm.compileNode(b)
local mapA = {}
- for obj in nodeMgr.eachObject(nodeA) do
+ for obj in nodeA:eachObject() do
local unique = getUnique(obj)
if not unique then
return nil
end
mapA[unique] = true
end
- for obj in nodeMgr.eachObject(nodeB) do
+ for obj in nodeB:eachObject() do
local unique = getUnique(obj)
if not unique then
return nil
@@ -105,7 +104,7 @@ end
function vm.getInteger(v)
local node = vm.compileNode(v)
local result
- for n in nodeMgr.eachObject(node) do
+ for n in node:eachObject() do
if n.type == 'integer' then
if result then
return nil
@@ -133,7 +132,7 @@ end
function vm.getString(v)
local node = vm.compileNode(v)
local result
- for n in nodeMgr.eachObject(node) do
+ for n in node:eachObject() do
if n.type == 'string' then
if result then
return nil
@@ -153,7 +152,7 @@ end
function vm.getNumber(v)
local node = vm.compileNode(v)
local result
- for n in nodeMgr.eachObject(node) do
+ for n in node:eachObject() do
if n.type == 'number'
or n.type == 'integer' then
if result then
@@ -174,7 +173,7 @@ end
function vm.getBoolean(v)
local node = vm.compileNode(v)
local result
- for n in nodeMgr.eachObject(node) do
+ for n in node:eachObject() do
if n.type == 'boolean' then
if result then
return nil
@@ -194,7 +193,7 @@ end
function vm.getLiterals(v)
local map
local node = vm.compileNode(v)
- for n in nodeMgr.eachObject(node) do
+ for n in node:eachObject() do
local literal
if n.type == 'boolean'
or n.type == 'string'