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 | |
parent | 43ef5d13ab20b77da3e4f7626116f0580aa1377e (diff) | |
download | lua-language-server-b3b71716f689be9115cdde8d6caf0314e76ae523.zip |
cleanup
Diffstat (limited to 'script/vm')
-rw-r--r-- | script/vm/compiler.lua | 345 | ||||
-rw-r--r-- | script/vm/def.lua | 7 | ||||
-rw-r--r-- | script/vm/generic.lua | 12 | ||||
-rw-r--r-- | script/vm/global-manager.lua | 7 | ||||
-rw-r--r-- | script/vm/infer.lua | 19 | ||||
-rw-r--r-- | script/vm/init.lua | 3 | ||||
-rw-r--r-- | script/vm/local-manager.lua | 3 | ||||
-rw-r--r-- | script/vm/manager.lua | 2 | ||||
-rw-r--r-- | script/vm/node.lua | 211 | ||||
-rw-r--r-- | script/vm/ref.lua | 3 | ||||
-rw-r--r-- | script/vm/sign.lua | 13 | ||||
-rw-r--r-- | script/vm/type.lua | 40 | ||||
-rw-r--r-- | script/vm/union.lua | 129 | ||||
-rw-r--r-- | script/vm/value.lua | 17 |
14 files changed, 381 insertions, 430 deletions
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' |