summaryrefslogtreecommitdiff
path: root/script
diff options
context:
space:
mode:
Diffstat (limited to 'script')
-rw-r--r--script/core/completion/completion.lua7
-rw-r--r--script/core/diagnostics/lowercase-global.lua3
-rw-r--r--script/core/diagnostics/undefined-global.lua3
-rw-r--r--script/core/rename.lua5
-rw-r--r--script/core/semantic-tokens.lua3
-rw-r--r--script/vm/compiler.lua69
-rw-r--r--script/vm/def.lua3
-rw-r--r--script/vm/doc.lua5
-rw-r--r--script/vm/global-manager.lua419
-rw-r--r--script/vm/global.lua425
-rw-r--r--script/vm/init.lua5
-rw-r--r--script/vm/manager.lua29
-rw-r--r--script/vm/ref.lua1
-rw-r--r--script/vm/runner.lua7
-rw-r--r--script/vm/sign.lua5
-rw-r--r--script/vm/type.lua11
16 files changed, 483 insertions, 517 deletions
diff --git a/script/core/completion/completion.lua b/script/core/completion/completion.lua
index 8987592d..8b50f8af 100644
--- a/script/core/completion/completion.lua
+++ b/script/core/completion/completion.lua
@@ -18,7 +18,6 @@ local lookBackward = require 'core.look-backward'
local guide = require 'parser.guide'
local await = require 'await'
local postfix = require 'core.completion.postfix'
-local globalMgr = require 'vm.global-manager'
local diagnosticModes = {
'disable-next-line',
@@ -351,7 +350,7 @@ local function checkModule(state, word, position, results)
local fileName = path:match '[^/\\]*$'
local stemName = fileName:gsub('%..+', '')
if not locals[stemName]
- and not globalMgr.hasGlobalSets(state.uri, 'variable', stemName)
+ and not vm.hasGlobalSets(state.uri, 'variable', stemName)
and not config.get(state.uri, 'Lua.diagnostics.globals')[stemName]
and stemName:match '^[%a_][%w_]*$'
and matchKey(word, stemName) then
@@ -601,14 +600,14 @@ end
---@async
local function checkGlobal(state, word, startPos, position, parent, oop, results)
local locals = guide.getVisibleLocals(state.ast, position)
- local globals = globalMgr.getGlobalSets(state.uri, 'variable')
+ local globals = vm.getGlobalSets(state.uri, 'variable')
checkFieldOfRefs(globals, state, word, startPos, position, parent, oop, results, locals, 'global')
end
---@async
local function checkField(state, word, start, position, parent, oop, results)
if parent.tag == '_ENV' or parent.special == '_G' then
- local globals = globalMgr.getGlobalSets(state.uri, 'variable')
+ local globals = vm.getGlobalSets(state.uri, 'variable')
checkFieldOfRefs(globals, state, word, start, position, parent, oop, results)
else
local refs = vm.getFields(parent)
diff --git a/script/core/diagnostics/lowercase-global.lua b/script/core/diagnostics/lowercase-global.lua
index 7c5ac720..d03e8c70 100644
--- a/script/core/diagnostics/lowercase-global.lua
+++ b/script/core/diagnostics/lowercase-global.lua
@@ -3,7 +3,6 @@ local guide = require 'parser.guide'
local lang = require 'language'
local config = require 'config'
local vm = require 'vm'
-local globalMgr = require 'vm.global-manager'
local function isDocClass(source)
if not source.bindDocs then
@@ -47,7 +46,7 @@ return function (uri, callback)
end
if definedGlobal[name] == nil then
definedGlobal[name] = false
- local global = globalMgr.getGlobal('variable', name)
+ local global = vm.getGlobal('variable', name)
if global then
for _, set in ipairs(global:getSets(uri)) do
if vm.isMetaFile(guide.getUri(set)) then
diff --git a/script/core/diagnostics/undefined-global.lua b/script/core/diagnostics/undefined-global.lua
index 139fa74f..bd0aae69 100644
--- a/script/core/diagnostics/undefined-global.lua
+++ b/script/core/diagnostics/undefined-global.lua
@@ -4,7 +4,6 @@ local lang = require 'language'
local config = require 'config'
local guide = require 'parser.guide'
local await = require 'await'
-local globalMgr = require 'vm.global-manager'
local requireLike = {
['include'] = true,
@@ -41,7 +40,7 @@ return function (uri, callback)
return
end
if cache[key] == nil then
- cache[key] = globalMgr.hasGlobalSets(uri, 'variable', key)
+ cache[key] = vm.hasGlobalSets(uri, 'variable', key)
end
if cache[key] then
return
diff --git a/script/core/rename.lua b/script/core/rename.lua
index ec21e87c..7599fad6 100644
--- a/script/core/rename.lua
+++ b/script/core/rename.lua
@@ -3,7 +3,6 @@ local vm = require 'vm'
local util = require 'utility'
local findSource = require 'core.find-source'
local guide = require 'parser.guide'
-local globalMgr = require 'vm.global-manager'
local Forcing
@@ -191,7 +190,7 @@ end
---@async
local function ofGlobal(source, newname, callback)
local key = guide.getKeyName(source)
- local global = globalMgr.getGlobal('variable', key)
+ local global = vm.getGlobal('variable', key)
if not global then
return
end
@@ -214,7 +213,7 @@ end
---@async
local function ofDocTypeName(source, newname, callback)
local oldname = source[1]
- local global = globalMgr.getGlobal('type', oldname)
+ local global = vm.getGlobal('type', oldname)
if not global then
return
end
diff --git a/script/core/semantic-tokens.lua b/script/core/semantic-tokens.lua
index bcba27a9..65c72c11 100644
--- a/script/core/semantic-tokens.lua
+++ b/script/core/semantic-tokens.lua
@@ -7,7 +7,6 @@ local guide = require 'parser.guide'
local converter = require 'proto.converter'
local config = require 'config'
local linkedTable = require 'linked-table'
-local globalMgr = require 'vm.global-manager'
local Care = util.switch()
: case 'getglobal'
@@ -21,7 +20,7 @@ local Care = util.switch()
local isLib = options.libGlobals[name]
if isLib == nil then
isLib = false
- local global = globalMgr.getGlobal('variable', name)
+ local global = vm.getGlobal('variable', name)
if global then
local uri = guide.getUri(source)
for _, set in ipairs(global:getSets(uri)) do
diff --git a/script/vm/compiler.lua b/script/vm/compiler.lua
index 4d26ce8c..cb18557b 100644
--- a/script/vm/compiler.lua
+++ b/script/vm/compiler.lua
@@ -1,7 +1,6 @@
local guide = require 'parser.guide'
local util = require 'utility'
local localID = require 'vm.local-id'
-local globalMgr = require 'vm.global-manager'
local signMgr = require 'vm.sign'
local config = require 'config'
local genericMgr = require 'vm.generic'
@@ -53,7 +52,7 @@ local searchFieldSwitch = util.switch()
: case 'string'
: call(function (suri, source, key, ref, pushResult)
-- change to `string: stringlib` ?
- local stringlib = globalMgr.getGlobal('type', 'stringlib')
+ local stringlib = vm.getGlobal('type', 'stringlib')
if stringlib then
vm.getClassFields(suri, stringlib, key, ref, pushResult)
end
@@ -118,7 +117,7 @@ local searchFieldSwitch = util.switch()
if type(key) ~= 'string' then
return
end
- local global = globalMgr.getGlobal('variable', node.name, key)
+ local global = vm.getGlobal('variable', node.name, key)
if global then
for _, set in ipairs(global:getSets(suri)) do
pushResult(set)
@@ -130,7 +129,7 @@ local searchFieldSwitch = util.switch()
end
end
else
- local globals = globalMgr.getFields('variable', node.name)
+ local globals = vm.getGlobalFields('variable', node.name)
for _, global in ipairs(globals) do
for _, set in ipairs(global:getSets(suri)) do
pushResult(set)
@@ -157,7 +156,7 @@ local searchFieldSwitch = util.switch()
if type(key) ~= 'string' then
return
end
- local global = globalMgr.getGlobal('variable', node.name, key)
+ local global = vm.getGlobal('variable', node.name, key)
if global then
for _, set in ipairs(global:getSets(suri)) do
pushResult(set)
@@ -167,7 +166,7 @@ local searchFieldSwitch = util.switch()
end
end
else
- local globals = globalMgr.getFields('variable', node.name)
+ local globals = vm.getGlobalFields('variable', node.name)
for _, global in ipairs(globals) do
for _, set in ipairs(global:getSets(suri)) do
pushResult(set)
@@ -282,7 +281,7 @@ function vm.getClassFields(suri, object, key, ref, pushResult)
end
for _, extend in ipairs(set.extends) do
if extend.type == 'doc.extends.name' then
- local extendType = globalMgr.getGlobal('type', extend[1])
+ local extendType = vm.getGlobal('type', extend[1])
if extendType then
searchClass(extendType, searchedFields)
end
@@ -296,12 +295,12 @@ function vm.getClassFields(suri, object, key, ref, pushResult)
local function searchGlobal(class)
if class.cate == 'type' and class.name == '_G' then
if key == nil then
- local sets = globalMgr.getGlobalSets(suri, 'variable')
+ local sets = vm.getGlobalSets(suri, 'variable')
for _, set in ipairs(sets) do
pushResult(set)
end
else
- local global = globalMgr.getGlobal('variable', key)
+ local global = vm.getGlobal('variable', key)
if global then
for _, set in ipairs(global:getSets(suri)) do
pushResult(set)
@@ -647,7 +646,7 @@ local function selectNode(source, list, index)
if exp.type == 'call' then
result = getReturn(exp.node, index, exp.args)
if not result then
- vm.setNode(source, globalMgr.declareGlobal('type', 'unknown'))
+ vm.setNode(source, vm.declareGlobal('type', 'unknown'))
return vm.getNode(source)
end
else
@@ -673,7 +672,7 @@ local function selectNode(source, list, index)
end
end
if not hasKnownType then
- rtnNode:merge(globalMgr.declareGlobal('type', 'unknown'))
+ rtnNode:merge(vm.declareGlobal('type', 'unknown'))
end
vm.setNode(source, rtnNode)
return rtnNode
@@ -877,7 +876,7 @@ local function compileLocal(source)
end
end
if not hasDocArg then
- vm.setNode(source, globalMgr.declareGlobal('type', 'any'))
+ vm.setNode(source, vm.declareGlobal('type', 'any'))
end
end
-- for x in ... do
@@ -1252,7 +1251,7 @@ local compilerSwitch = util.switch()
: case 'loop'
: call(function (source)
if source.loc then
- vm.setNode(source.loc, globalMgr.declareGlobal('type', 'integer'))
+ vm.setNode(source.loc, vm.declareGlobal('type', 'integer'))
end
end)
: case 'doc.type'
@@ -1281,7 +1280,7 @@ local compilerSwitch = util.switch()
if not source.node[1] then
return
end
- local global = globalMgr.getGlobal('type', source.node[1])
+ local global = vm.getGlobal('type', source.node[1])
if not global then
return
end
@@ -1370,7 +1369,7 @@ local compilerSwitch = util.switch()
end)
: case 'doc.see.name'
: call(function (source)
- local type = globalMgr.getGlobal('type', source[1])
+ local type = vm.getGlobal('type', source[1])
if type then
vm.setNode(source, vm.compileNode(type))
end
@@ -1380,7 +1379,7 @@ local compilerSwitch = util.switch()
if source.extends then
vm.setNode(source, vm.compileNode(source.extends))
else
- vm.setNode(source, globalMgr.declareGlobal('type', 'any'))
+ vm.setNode(source, vm.declareGlobal('type', 'any'))
end
if source.optional then
vm.getNode(source):addOptional()
@@ -1401,7 +1400,7 @@ local compilerSwitch = util.switch()
if source.op.type == 'not' then
local result = vm.test(source[1])
if result == nil then
- vm.setNode(source, globalMgr.declareGlobal('type', 'boolean'))
+ vm.setNode(source, vm.declareGlobal('type', 'boolean'))
return
else
vm.setNode(source, {
@@ -1415,13 +1414,13 @@ local compilerSwitch = util.switch()
end
end
if source.op.type == '#' then
- vm.setNode(source, globalMgr.declareGlobal('type', 'integer'))
+ vm.setNode(source, vm.declareGlobal('type', 'integer'))
return
end
if source.op.type == '-' then
local v = vm.getNumber(source[1])
if v == nil then
- vm.setNode(source, globalMgr.declareGlobal('type', 'number'))
+ vm.setNode(source, vm.declareGlobal('type', 'number'))
return
else
vm.setNode(source, {
@@ -1437,7 +1436,7 @@ local compilerSwitch = util.switch()
if source.op.type == '~' then
local v = vm.getInteger(source[1])
if v == nil then
- vm.setNode(source, globalMgr.declareGlobal('type', 'integer'))
+ vm.setNode(source, vm.declareGlobal('type', 'integer'))
return
else
vm.setNode(source, {
@@ -1488,7 +1487,7 @@ local compilerSwitch = util.switch()
if source.op.type == '==' then
local result = vm.equal(source[1], source[2])
if result == nil then
- vm.setNode(source, globalMgr.declareGlobal('type', 'boolean'))
+ vm.setNode(source, vm.declareGlobal('type', 'boolean'))
return
else
vm.setNode(source, {
@@ -1504,7 +1503,7 @@ local compilerSwitch = util.switch()
if source.op.type == '~=' then
local result = vm.equal(source[1], source[2])
if result == nil then
- vm.setNode(source, globalMgr.declareGlobal('type', 'boolean'))
+ vm.setNode(source, vm.declareGlobal('type', 'boolean'))
return
else
vm.setNode(source, {
@@ -1530,7 +1529,7 @@ local compilerSwitch = util.switch()
})
return
else
- vm.setNode(source, globalMgr.declareGlobal('type', 'integer'))
+ vm.setNode(source, vm.declareGlobal('type', 'integer'))
return
end
end
@@ -1547,7 +1546,7 @@ local compilerSwitch = util.switch()
})
return
else
- vm.setNode(source, globalMgr.declareGlobal('type', 'integer'))
+ vm.setNode(source, vm.declareGlobal('type', 'integer'))
return
end
end
@@ -1564,7 +1563,7 @@ local compilerSwitch = util.switch()
})
return
else
- vm.setNode(source, globalMgr.declareGlobal('type', 'integer'))
+ vm.setNode(source, vm.declareGlobal('type', 'integer'))
return
end
end
@@ -1581,7 +1580,7 @@ local compilerSwitch = util.switch()
})
return
else
- vm.setNode(source, globalMgr.declareGlobal('type', 'integer'))
+ vm.setNode(source, vm.declareGlobal('type', 'integer'))
return
end
end
@@ -1598,7 +1597,7 @@ local compilerSwitch = util.switch()
})
return
else
- vm.setNode(source, globalMgr.declareGlobal('type', 'integer'))
+ vm.setNode(source, vm.declareGlobal('type', 'integer'))
return
end
end
@@ -1616,7 +1615,7 @@ local compilerSwitch = util.switch()
})
return
else
- vm.setNode(source, globalMgr.declareGlobal('type', 'number'))
+ vm.setNode(source, vm.declareGlobal('type', 'number'))
return
end
end
@@ -1634,7 +1633,7 @@ local compilerSwitch = util.switch()
})
return
else
- vm.setNode(source, globalMgr.declareGlobal('type', 'number'))
+ vm.setNode(source, vm.declareGlobal('type', 'number'))
return
end
end
@@ -1652,7 +1651,7 @@ local compilerSwitch = util.switch()
})
return
else
- vm.setNode(source, globalMgr.declareGlobal('type', 'number'))
+ vm.setNode(source, vm.declareGlobal('type', 'number'))
return
end
end
@@ -1669,7 +1668,7 @@ local compilerSwitch = util.switch()
})
return
else
- vm.setNode(source, globalMgr.declareGlobal('type', 'number'))
+ vm.setNode(source, vm.declareGlobal('type', 'number'))
return
end
end
@@ -1687,7 +1686,7 @@ local compilerSwitch = util.switch()
})
return
else
- vm.setNode(source, globalMgr.declareGlobal('type', 'number'))
+ vm.setNode(source, vm.declareGlobal('type', 'number'))
return
end
end
@@ -1704,7 +1703,7 @@ local compilerSwitch = util.switch()
})
return
else
- vm.setNode(source, globalMgr.declareGlobal('type', 'number'))
+ vm.setNode(source, vm.declareGlobal('type', 'number'))
return
end
end
@@ -1722,7 +1721,7 @@ local compilerSwitch = util.switch()
})
return
else
- vm.setNode(source, globalMgr.declareGlobal('type', 'number'))
+ vm.setNode(source, vm.declareGlobal('type', 'number'))
return
end
end
@@ -1759,7 +1758,7 @@ local compilerSwitch = util.switch()
})
return
else
- vm.setNode(source, globalMgr.declareGlobal('type', 'string'))
+ vm.setNode(source, vm.declareGlobal('type', 'string'))
return
end
end
diff --git a/script/vm/def.lua b/script/vm/def.lua
index a0cb501e..60dcf03c 100644
--- a/script/vm/def.lua
+++ b/script/vm/def.lua
@@ -3,7 +3,6 @@ local vm = require 'vm.vm'
local util = require 'utility'
local guide = require 'parser.guide'
local localID = require 'vm.local-id'
-local globalMgr = require 'vm.global-manager'
local simpleSwitch
@@ -104,7 +103,7 @@ local searchFieldSwitch = util.switch()
---@param key string
: call(function (suri, obj, key, pushResult)
if obj.cate == 'variable' then
- local newGlobal = globalMgr.getGlobal('variable', obj.name, key)
+ local newGlobal = vm.getGlobal('variable', obj.name, key)
if newGlobal then
for _, set in ipairs(newGlobal:getSets(suri)) do
pushResult(set)
diff --git a/script/vm/doc.lua b/script/vm/doc.lua
index 055b3d49..e2b383b6 100644
--- a/script/vm/doc.lua
+++ b/script/vm/doc.lua
@@ -3,7 +3,6 @@ local guide = require 'parser.guide'
---@class vm
local vm = require 'vm.vm'
local config = require 'config'
-local globalMgr = require 'vm.global-manager'
---获取class与alias
---@param suri uri
@@ -11,13 +10,13 @@ local globalMgr = require 'vm.global-manager'
---@return parser.object[]
function vm.getDocSets(suri, name)
if name then
- local global = globalMgr.getGlobal('type', name)
+ local global = vm.getGlobal('type', name)
if not global then
return {}
end
return global:getSets(suri)
else
- return globalMgr.getGlobalSets(suri, 'type')
+ return vm.getGlobalSets(suri, 'type')
end
end
diff --git a/script/vm/global-manager.lua b/script/vm/global-manager.lua
deleted file mode 100644
index 5891ba41..00000000
--- a/script/vm/global-manager.lua
+++ /dev/null
@@ -1,419 +0,0 @@
-local util = require 'utility'
-local guide = require 'parser.guide'
-local globalBuilder = require 'vm.global'
-local signMgr = require 'vm.sign'
-local genericMgr = require 'vm.generic'
-local localID = require 'vm.local-id'
----@class vm
-local vm = require 'vm.vm'
-
----@class parser.object
----@field _globalNode? vm.global
-
----@class vm.global-manager
-local m = {}
----@type table<string, vm.global>
-m.globals = {}
----@type table<uri, table<string, boolean>>
-m.globalSubs = util.multiTable(2)
-
-local compilerGlobalSwitch = util.switch()
- : case 'local'
- : call(function (source)
- if source.special ~= '_G' then
- return
- end
- if source.ref then
- for _, ref in ipairs(source.ref) do
- m.compileObject(ref)
- end
- end
- end)
- : case 'getlocal'
- : call(function (source)
- if source.special ~= '_G' then
- return
- end
- if not source.next then
- return
- end
- m.compileObject(source.next)
- end)
- : case 'setglobal'
- : call(function (source)
- local uri = guide.getUri(source)
- local name = guide.getKeyName(source)
- local global = m.declareGlobal('variable', name, uri)
- global:addSet(uri, source)
- source._globalNode = global
- end)
- : case 'getglobal'
- : call(function (source)
- local uri = guide.getUri(source)
- local name = guide.getKeyName(source)
- local global = m.declareGlobal('variable', name, uri)
- global:addGet(uri, source)
- source._globalNode = global
-
- local nxt = source.next
- if nxt then
- m.compileObject(nxt)
- end
- end)
- : case 'setfield'
- : case 'setmethod'
- : case 'setindex'
- ---@param source parser.object
- : call(function (source)
- local name
- local keyName = guide.getKeyName(source)
- if not keyName then
- return
- end
- if source.node._globalNode then
- local parentName = source.node._globalNode:getName()
- if parentName == '_G' then
- name = keyName
- else
- name = ('%s%s%s'):format(parentName, vm.ID_SPLITE, keyName)
- end
- elseif source.node.special == '_G' then
- name = keyName
- end
- if not name then
- return
- end
- local uri = guide.getUri(source)
- local global = m.declareGlobal('variable', name, uri)
- global:addSet(uri, source)
- source._globalNode = global
- end)
- : case 'getfield'
- : case 'getmethod'
- : case 'getindex'
- ---@param source parser.object
- : call(function (source)
- local name
- local keyName = guide.getKeyName(source)
- if not keyName then
- return
- end
- if source.node._globalNode then
- local parentName = source.node._globalNode:getName()
- if parentName == '_G' then
- name = keyName
- else
- name = ('%s%s%s'):format(parentName, vm.ID_SPLITE, keyName)
- end
- elseif source.node.special == '_G' then
- name = keyName
- end
- local uri = guide.getUri(source)
- local global = m.declareGlobal('variable', name, uri)
- global:addGet(uri, source)
- source._globalNode = global
-
- local nxt = source.next
- if nxt then
- m.compileObject(nxt)
- end
- end)
- : case 'call'
- : call(function (source)
- if source.node.special == 'rawset'
- or source.node.special == 'rawget' then
- if not source.args then
- return
- end
- local g = source.args[1]
- local key = source.args[2]
- if g and key and g.special == '_G' then
- local name = guide.getKeyName(key)
- if name then
- local uri = guide.getUri(source)
- local global = m.declareGlobal('variable', name, uri)
- if source.node.special == 'rawset' then
- global:addSet(uri, source)
- source.value = source.args[3]
- else
- global:addGet(uri, source)
- end
- source._globalNode = global
-
- local nxt = source.next
- if nxt then
- m.compileObject(nxt)
- end
- end
- end
- end
- end)
- : case 'doc.class'
- ---@param source parser.object
- : call(function (source)
- local uri = guide.getUri(source)
- local name = guide.getKeyName(source)
- local class = m.declareGlobal('type', name, uri)
- class:addSet(uri, source)
- source._globalNode = class
-
- if source.signs then
- source._sign = signMgr()
- for _, sign in ipairs(source.signs) do
- source._sign:addSign(vm.compileNode(sign))
- end
- if source.extends then
- for _, ext in ipairs(source.extends) do
- if ext.type == 'doc.type.table' then
- ext._generic = genericMgr(ext, source._sign)
- end
- end
- end
- end
- end)
- : case 'doc.alias'
- : call(function (source)
- local uri = guide.getUri(source)
- local name = guide.getKeyName(source)
- local alias = m.declareGlobal('type', name, uri)
- alias:addSet(uri, source)
- source._globalNode = alias
-
- if source.signs then
- source._sign = signMgr()
- for _, sign in ipairs(source.signs) do
- source._sign:addSign(vm.compileNode(sign))
- end
- source.extends._generic = genericMgr(source.extends, source._sign)
- end
- end)
- : case 'doc.type.name'
- : call(function (source)
- local uri = guide.getUri(source)
- local name = source[1]
- local type = m.declareGlobal('type', name, uri)
- type:addGet(uri, source)
- source._globalNode = type
- end)
- : case 'doc.extends.name'
- : call(function (source)
- local uri = guide.getUri(source)
- local name = source[1]
- local class = m.declareGlobal('type', name, uri)
- class:addGet(uri, source)
- source._globalNode = class
- end)
-
-
----@alias vm.global.cate '"variable"' | '"type"'
-
----@param cate vm.global.cate
----@param name string
----@param uri? uri
----@return vm.global
-function m.declareGlobal(cate, name, uri)
- local key = cate .. '|' .. name
- if uri then
- m.globalSubs[uri][key] = true
- end
- if not m.globals[key] then
- m.globals[key] = globalBuilder(name, cate)
- end
- return m.globals[key]
-end
-
----@param cate vm.global.cate
----@param name string
----@param field? string
----@return vm.global?
-function m.getGlobal(cate, name, field)
- local key = cate .. '|' .. name
- if field then
- key = key .. vm.ID_SPLITE .. field
- end
- return m.globals[key]
-end
-
----@param cate vm.global.cate
----@param name string
----@return vm.global[]
-function m.getFields(cate, name)
- local globals = {}
- local key = cate .. '|' .. name
-
- -- TODO: optimize
- local clock = os.clock()
- for gid, global in pairs(m.globals) do
- if gid ~= key
- and util.stringStartWith(gid, key)
- and gid:sub(#key + 1, #key + 1) == vm.ID_SPLITE
- and not gid:find(vm.ID_SPLITE, #key + 2) then
- globals[#globals+1] = global
- end
- end
- local cost = os.clock() - clock
- if cost > 0.1 then
- log.warn('global-manager getFields cost %.3f', cost)
- end
-
- return globals
-end
-
----@param cate vm.global.cate
----@return vm.global[]
-function m.getGlobals(cate)
- local globals = {}
-
- -- TODO: optimize
- local clock = os.clock()
- for gid, global in pairs(m.globals) do
- if util.stringStartWith(gid, cate)
- and not gid:find(vm.ID_SPLITE) then
- globals[#globals+1] = global
- end
- end
- local cost = os.clock() - clock
- if cost > 0.1 then
- log.warn('global-manager getGlobals cost %.3f', cost)
- end
-
- return globals
-end
-
----@param suri uri
----@param cate vm.global.cate
----@return parser.object[]
-function m.getGlobalSets(suri, cate)
- local globals = m.getGlobals(cate)
- local result = {}
- for _, global in ipairs(globals) do
- local sets = global:getSets(suri)
- for _, set in ipairs(sets) do
- result[#result+1] = set
- end
- end
- return result
-end
-
----@param suri uri
----@param cate vm.global.cate
----@param name string
----@return boolean
-function m.hasGlobalSets(suri, cate, name)
- local global = m.getGlobal(cate, name)
- if not global then
- return false
- end
- local sets = global:getSets(suri)
- if #sets == 0 then
- return false
- end
- return true
-end
-
----@param source parser.object
-function m.compileObject(source)
- if source._globalNode ~= nil then
- return
- end
- source._globalNode = false
- compilerGlobalSwitch(source.type, source)
-end
-
----@param source parser.object
-function m.compileSelf(source)
- if source.parent.type ~= 'funcargs' then
- return
- end
- ---@type parser.object
- local node = source.parent.parent and source.parent.parent.parent and source.parent.parent.parent.node
- if not node then
- return
- end
- local fields = localID.getFields(source)
- if not fields then
- return
- end
- local nodeLocalID = localID.getID(node)
- local globalNode = node._globalNode
- if not nodeLocalID and not globalNode then
- return
- end
- for _, field in ipairs(fields) do
- if field.type == 'setfield' then
- local key = guide.getKeyName(field)
- if key then
- if nodeLocalID then
- local myID = nodeLocalID .. vm.ID_SPLITE .. key
- localID.insertLocalID(myID, field)
- end
- if globalNode then
- local myID = globalNode:getName() .. vm.ID_SPLITE .. key
- local myGlobal = m.declareGlobal('variable', myID, guide.getUri(node))
- myGlobal:addSet(guide.getUri(node), field)
- end
- end
- end
- end
-end
-
----@param source parser.object
-function m.compileAst(source)
- local env = guide.getENV(source)
- if not env then
- return
- end
- m.compileObject(env)
- guide.eachSpecialOf(source, 'rawset', function (src)
- m.compileObject(src.parent)
- end)
- guide.eachSpecialOf(source, 'rawget', function (src)
- m.compileObject(src.parent)
- end)
- guide.eachSourceTypes(source.docs, {
- 'doc.class',
- 'doc.alias',
- 'doc.type.name',
- 'doc.extends.name',
- }, function (src)
- m.compileObject(src)
- end)
-
- --[[
- local mt
- function mt:xxx()
- self.a = 1
- end
-
- mt.a --> find this definition
- ]]
- guide.eachSourceType(source, 'self', function (src)
- m.compileSelf(src)
- end)
-end
-
----@return vm.global
-function m.getNode(source)
- if source.type == 'field'
- or source.type == 'method' then
- source = source.parent
- end
- return source._globalNode
-end
-
----@param uri uri
-function m.dropUri(uri)
- local globalSub = m.globalSubs[uri]
- m.globalSubs[uri] = nil
- for key in pairs(globalSub) do
- local global = m.globals[key]
- if global then
- global:dropUri(uri)
- if not global:isAlive() then
- m.globals[key] = nil
- end
- end
- end
-end
-
-return m
diff --git a/script/vm/global.lua b/script/vm/global.lua
index f8327843..eea398dc 100644
--- a/script/vm/global.lua
+++ b/script/vm/global.lua
@@ -1,5 +1,11 @@
local util = require 'utility'
local scope = require 'workspace.scope'
+local guide = require 'parser.guide'
+local files = require 'files'
+local signMgr = require 'vm.sign'
+local genericMgr = require 'vm.generic'
+local localID = require 'vm.local-id'
+---@class vm
local vm = require 'vm.vm'
---@class vm.global.link
@@ -115,10 +121,427 @@ end
---@param cate vm.global.cate
---@return vm.global
-return function (name, cate)
+local function createGlobal(name, cate)
return setmetatable({
name = name,
cate = cate,
links = util.multiTable(2),
}, mt)
end
+
+---@class parser.object
+---@field _globalNode vm.global
+
+---@type table<string, vm.global>
+local allGlobals = {}
+---@type table<uri, table<string, boolean>>
+local globalSubs = util.multiTable(2)
+
+local compileObject
+local compilerGlobalSwitch = util.switch()
+ : case 'local'
+ : call(function (source)
+ if source.special ~= '_G' then
+ return
+ end
+ if source.ref then
+ for _, ref in ipairs(source.ref) do
+ compileObject(ref)
+ end
+ end
+ end)
+ : case 'getlocal'
+ : call(function (source)
+ if source.special ~= '_G' then
+ return
+ end
+ if not source.next then
+ return
+ end
+ compileObject(source.next)
+ end)
+ : case 'setglobal'
+ : call(function (source)
+ local uri = guide.getUri(source)
+ local name = guide.getKeyName(source)
+ local global = vm.declareGlobal('variable', name, uri)
+ global:addSet(uri, source)
+ source._globalNode = global
+ end)
+ : case 'getglobal'
+ : call(function (source)
+ local uri = guide.getUri(source)
+ local name = guide.getKeyName(source)
+ local global = vm.declareGlobal('variable', name, uri)
+ global:addGet(uri, source)
+ source._globalNode = global
+
+ local nxt = source.next
+ if nxt then
+ compileObject(nxt)
+ end
+ end)
+ : case 'setfield'
+ : case 'setmethod'
+ : case 'setindex'
+ ---@param source parser.object
+ : call(function (source)
+ local name
+ local keyName = guide.getKeyName(source)
+ if not keyName then
+ return
+ end
+ if source.node._globalNode then
+ local parentName = source.node._globalNode:getName()
+ if parentName == '_G' then
+ name = keyName
+ else
+ name = ('%s%s%s'):format(parentName, vm.ID_SPLITE, keyName)
+ end
+ elseif source.node.special == '_G' then
+ name = keyName
+ end
+ if not name then
+ return
+ end
+ local uri = guide.getUri(source)
+ local global = vm.declareGlobal('variable', name, uri)
+ global:addSet(uri, source)
+ source._globalNode = global
+ end)
+ : case 'getfield'
+ : case 'getmethod'
+ : case 'getindex'
+ ---@param source parser.object
+ : call(function (source)
+ local name
+ local keyName = guide.getKeyName(source)
+ if not keyName then
+ return
+ end
+ if source.node._globalNode then
+ local parentName = source.node._globalNode:getName()
+ if parentName == '_G' then
+ name = keyName
+ else
+ name = ('%s%s%s'):format(parentName, vm.ID_SPLITE, keyName)
+ end
+ elseif source.node.special == '_G' then
+ name = keyName
+ end
+ local uri = guide.getUri(source)
+ local global = vm.declareGlobal('variable', name, uri)
+ global:addGet(uri, source)
+ source._globalNode = global
+
+ local nxt = source.next
+ if nxt then
+ compileObject(nxt)
+ end
+ end)
+ : case 'call'
+ : call(function (source)
+ if source.node.special == 'rawset'
+ or source.node.special == 'rawget' then
+ if not source.args then
+ return
+ end
+ local g = source.args[1]
+ local key = source.args[2]
+ if g and key and g.special == '_G' then
+ local name = guide.getKeyName(key)
+ if name then
+ local uri = guide.getUri(source)
+ local global = vm.declareGlobal('variable', name, uri)
+ if source.node.special == 'rawset' then
+ global:addSet(uri, source)
+ source.value = source.args[3]
+ else
+ global:addGet(uri, source)
+ end
+ source._globalNode = global
+
+ local nxt = source.next
+ if nxt then
+ compileObject(nxt)
+ end
+ end
+ end
+ end
+ end)
+ : case 'doc.class'
+ ---@param source parser.object
+ : call(function (source)
+ local uri = guide.getUri(source)
+ local name = guide.getKeyName(source)
+ local class = vm.declareGlobal('type', name, uri)
+ class:addSet(uri, source)
+ source._globalNode = class
+
+ if source.signs then
+ source._sign = signMgr()
+ for _, sign in ipairs(source.signs) do
+ source._sign:addSign(vm.compileNode(sign))
+ end
+ if source.extends then
+ for _, ext in ipairs(source.extends) do
+ if ext.type == 'doc.type.table' then
+ ext._generic = genericMgr(ext, source._sign)
+ end
+ end
+ end
+ end
+ end)
+ : case 'doc.alias'
+ : call(function (source)
+ local uri = guide.getUri(source)
+ local name = guide.getKeyName(source)
+ local alias = vm.declareGlobal('type', name, uri)
+ alias:addSet(uri, source)
+ source._globalNode = alias
+
+ if source.signs then
+ source._sign = signMgr()
+ for _, sign in ipairs(source.signs) do
+ source._sign:addSign(vm.compileNode(sign))
+ end
+ source.extends._generic = genericMgr(source.extends, source._sign)
+ end
+ end)
+ : case 'doc.type.name'
+ : call(function (source)
+ local uri = guide.getUri(source)
+ local name = source[1]
+ local type = vm.declareGlobal('type', name, uri)
+ type:addGet(uri, source)
+ source._globalNode = type
+ end)
+ : case 'doc.extends.name'
+ : call(function (source)
+ local uri = guide.getUri(source)
+ local name = source[1]
+ local class = vm.declareGlobal('type', name, uri)
+ class:addGet(uri, source)
+ source._globalNode = class
+ end)
+
+
+---@alias vm.global.cate '"variable"' | '"type"'
+
+---@param cate vm.global.cate
+---@param name string
+---@param uri? uri
+---@return vm.global
+function vm.declareGlobal(cate, name, uri)
+ local key = cate .. '|' .. name
+ if uri then
+ globalSubs[uri][key] = true
+ end
+ if not allGlobals[key] then
+ allGlobals[key] = createGlobal(name, cate)
+ end
+ return allGlobals[key]
+end
+
+---@param cate vm.global.cate
+---@param name string
+---@param field? string
+---@return vm.global?
+function vm.getGlobal(cate, name, field)
+ local key = cate .. '|' .. name
+ if field then
+ key = key .. vm.ID_SPLITE .. field
+ end
+ return allGlobals[key]
+end
+
+---@param cate vm.global.cate
+---@param name string
+---@return vm.global[]
+function vm.getGlobalFields(cate, name)
+ local globals = {}
+ local key = cate .. '|' .. name
+
+ local clock = os.clock()
+ for gid, global in pairs(allGlobals) do
+ if gid ~= key
+ and util.stringStartWith(gid, key)
+ and gid:sub(#key + 1, #key + 1) == vm.ID_SPLITE
+ and not gid:find(vm.ID_SPLITE, #key + 2) then
+ globals[#globals+1] = global
+ end
+ end
+ local cost = os.clock() - clock
+ if cost > 0.1 then
+ log.warn('global-manager getFields cost %.3f', cost)
+ end
+
+ return globals
+end
+
+---@param cate vm.global.cate
+---@return vm.global[]
+function vm.getGlobals(cate)
+ local globals = {}
+
+ local clock = os.clock()
+ for gid, global in pairs(allGlobals) do
+ if util.stringStartWith(gid, cate)
+ and not gid:find(vm.ID_SPLITE) then
+ globals[#globals+1] = global
+ end
+ end
+ local cost = os.clock() - clock
+ if cost > 0.1 then
+ log.warn('global-manager getGlobals cost %.3f', cost)
+ end
+
+ return globals
+end
+
+---@param suri uri
+---@param cate vm.global.cate
+---@return parser.object[]
+function vm.getGlobalSets(suri, cate)
+ local globals = vm.getGlobals(cate)
+ local result = {}
+ for _, global in ipairs(globals) do
+ local sets = global:getSets(suri)
+ for _, set in ipairs(sets) do
+ result[#result+1] = set
+ end
+ end
+ return result
+end
+
+---@param suri uri
+---@param cate vm.global.cate
+---@param name string
+---@return boolean
+function vm.hasGlobalSets(suri, cate, name)
+ local global = vm.getGlobal(cate, name)
+ if not global then
+ return false
+ end
+ local sets = global:getSets(suri)
+ if #sets == 0 then
+ return false
+ end
+ return true
+end
+
+---@param source parser.object
+function compileObject(source)
+ if source._globalNode ~= nil then
+ return
+ end
+ source._globalNode = false
+ compilerGlobalSwitch(source.type, source)
+end
+
+---@param source parser.object
+local function compileSelf(source)
+ if source.parent.type ~= 'funcargs' then
+ return
+ end
+ ---@type parser.object
+ local node = source.parent.parent and source.parent.parent.parent and source.parent.parent.parent.node
+ if not node then
+ return
+ end
+ local fields = localID.getFields(source)
+ if not fields then
+ return
+ end
+ local nodeLocalID = localID.getID(node)
+ local globalNode = node._globalNode
+ if not nodeLocalID and not globalNode then
+ return
+ end
+ for _, field in ipairs(fields) do
+ if field.type == 'setfield' then
+ local key = guide.getKeyName(field)
+ if key then
+ if nodeLocalID then
+ local myID = nodeLocalID .. vm.ID_SPLITE .. key
+ localID.insertLocalID(myID, field)
+ end
+ if globalNode then
+ local myID = globalNode:getName() .. vm.ID_SPLITE .. key
+ local myGlobal = vm.declareGlobal('variable', myID, guide.getUri(node))
+ myGlobal:addSet(guide.getUri(node), field)
+ end
+ end
+ end
+ end
+end
+
+---@param source parser.object
+local function compileAst(source)
+ local env = guide.getENV(source)
+ if not env then
+ return
+ end
+ compileObject(env)
+ guide.eachSpecialOf(source, 'rawset', function (src)
+ compileObject(src.parent)
+ end)
+ guide.eachSpecialOf(source, 'rawget', function (src)
+ compileObject(src.parent)
+ end)
+ guide.eachSourceTypes(source.docs, {
+ 'doc.class',
+ 'doc.alias',
+ 'doc.type.name',
+ 'doc.extends.name',
+ }, function (src)
+ compileObject(src)
+ end)
+
+ --[[
+ local mt
+ function mt:xxx()
+ self.a = 1
+ end
+
+ mt.a --> find this definition
+ ]]
+ guide.eachSourceType(source, 'self', function (src)
+ compileSelf(src)
+ end)
+end
+
+---@param uri uri
+local function dropUri(uri)
+ local globalSub = globalSubs[uri]
+ globalSubs[uri] = nil
+ for key in pairs(globalSub) do
+ local global = allGlobals[key]
+ if global then
+ global:dropUri(uri)
+ if not global:isAlive() then
+ allGlobals[key] = nil
+ end
+ end
+ end
+end
+
+for uri in files.eachFile() do
+ local state = files.getState(uri)
+ if state then
+ compileAst(state.ast)
+ end
+end
+
+files.watch(function (ev, uri)
+ if ev == 'update' then
+ dropUri(uri)
+ local state = files.getState(uri)
+ if state then
+ compileAst(state.ast)
+ end
+ end
+ if ev == 'remove' then
+ dropUri(uri)
+ end
+end)
diff --git a/script/vm/init.lua b/script/vm/init.lua
index 61541c5f..23dd0d54 100644
--- a/script/vm/init.lua
+++ b/script/vm/init.lua
@@ -1,4 +1,7 @@
local vm = require 'vm.vm'
+
+---@alias vm.object parser.object | vm.global | vm.generic
+
require 'vm.compiler'
require 'vm.value'
require 'vm.node'
@@ -9,6 +12,6 @@ require 'vm.doc'
require 'vm.type'
require 'vm.library'
require 'vm.runner'
-require 'vm.manager'
require 'vm.infer'
+require 'vm.global'
return vm
diff --git a/script/vm/manager.lua b/script/vm/manager.lua
deleted file mode 100644
index c75b777f..00000000
--- a/script/vm/manager.lua
+++ /dev/null
@@ -1,29 +0,0 @@
-
-local files = require 'files'
-local globalManager = require 'vm.global-manager'
-
----@alias vm.object parser.object | vm.global | vm.generic
-
----@class vm.state
-local m = {}
-for uri in files.eachFile() do
- local state = files.getState(uri)
- if state then
- globalManager.compileAst(state.ast)
- end
-end
-
-files.watch(function (ev, uri)
- if ev == 'update' then
- globalManager.dropUri(uri)
- local state = files.getState(uri)
- if state then
- globalManager.compileAst(state.ast)
- end
- end
- if ev == 'remove' then
- globalManager.dropUri(uri)
- end
-end)
-
-return m
diff --git a/script/vm/ref.lua b/script/vm/ref.lua
index 29ea27c5..714d3ccd 100644
--- a/script/vm/ref.lua
+++ b/script/vm/ref.lua
@@ -3,7 +3,6 @@ local vm = require 'vm.vm'
local util = require 'utility'
local guide = require 'parser.guide'
local localID = require 'vm.local-id'
-local globalMgr = require 'vm.global-manager'
local files = require 'files'
local await = require 'await'
local progress = require 'progress'
diff --git a/script/vm/runner.lua b/script/vm/runner.lua
index 7fbde208..9fe0f172 100644
--- a/script/vm/runner.lua
+++ b/script/vm/runner.lua
@@ -1,7 +1,6 @@
---@class vm
local vm = require 'vm.vm'
local guide = require 'parser.guide'
-local globalMgr = require 'vm.global-manager'
---@class vm.runner
---@field loc parser.object
@@ -367,17 +366,17 @@ function mt:launch(callback)
node:setFalsy()
elseif step.type == 'as' then
if step.new then
- topNode = vm.createNode(globalMgr.getGlobal('type', step.name))
+ topNode = vm.createNode(vm.getGlobal('type', step.name))
else
node:clear()
- node:merge(globalMgr.getGlobal('type', step.name))
+ node:merge(vm.getGlobal('type', step.name))
end
elseif step.type == 'add' then
if step.new then
node = node:copy()
topNode = node
end
- node:merge(globalMgr.getGlobal('type', step.name))
+ node:merge(vm.getGlobal('type', step.name))
elseif step.type == 'remove' then
if step.new then
node = node:copy()
diff --git a/script/vm/sign.lua b/script/vm/sign.lua
index ded094d0..c19f72d4 100644
--- a/script/vm/sign.lua
+++ b/script/vm/sign.lua
@@ -21,7 +21,6 @@ function mt:resolve(uri, args, removeGeneric)
if not args then
return nil
end
- local globalMgr = require 'vm.global-manager'
local resolved = {}
---@param object parser.object
@@ -33,7 +32,7 @@ function mt:resolve(uri, args, removeGeneric)
-- 'number' -> `T`
for n in node:eachObject() do
if n.type == 'string' then
- local type = globalMgr.declareGlobal('type', n[1], guide.getUri(n))
+ local type = vm.declareGlobal('type', n[1], guide.getUri(n))
resolved[key] = vm.createNode(type, resolved[key])
end
end
@@ -57,7 +56,7 @@ function mt:resolve(uri, args, removeGeneric)
end
if n.type == 'global' and n.cate == 'type' then
-- ---@field [integer]: number -> T[]
- vm.getClassFields(uri, n, globalMgr.declareGlobal('type', 'integer'), false, function (field)
+ vm.getClassFields(uri, n, vm.declareGlobal('type', 'integer'), false, function (field)
resolve(object.node, vm.compileNode(field.extends))
end)
end
diff --git a/script/vm/type.lua b/script/vm/type.lua
index 691490ec..c3264993 100644
--- a/script/vm/type.lua
+++ b/script/vm/type.lua
@@ -1,4 +1,3 @@
-local globalMgr = require 'vm.global-manager'
---@class vm
local vm = require 'vm.vm'
@@ -9,10 +8,10 @@ local vm = require 'vm.vm'
---@return boolean
function vm.isSubType(uri, child, parent, mark)
if type(parent) == 'string' then
- parent = vm.createNode(globalMgr.getGlobal('type', parent))
+ parent = vm.createNode(vm.getGlobal('type', parent))
end
if type(child) == 'string' then
- child = vm.createNode(globalMgr.getGlobal('type', child))
+ child = vm.createNode(vm.getGlobal('type', child))
end
if not child or not parent then
@@ -134,7 +133,7 @@ function vm.getTableKey(uri, tnode, vnode)
end
end
if tn.type == 'doc.type.array' then
- result:merge(globalMgr.declareGlobal('type', 'integer'))
+ result:merge(vm.declareGlobal('type', 'integer'))
end
if tn.type == 'table' then
for _, field in ipairs(tn) do
@@ -144,10 +143,10 @@ function vm.getTableKey(uri, tnode, vnode)
end
end
if field.type == 'tablefield' then
- result:merge(globalMgr.declareGlobal('type', 'string'))
+ result:merge(vm.declareGlobal('type', 'string'))
end
if field.type == 'tableexp' then
- result:merge(globalMgr.declareGlobal('type', 'integer'))
+ result:merge(vm.declareGlobal('type', 'integer'))
end
end
end