summaryrefslogtreecommitdiff
path: root/script/vm
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2022-04-15 19:10:46 +0800
committer最萌小汐 <sumneko@hotmail.com>2022-04-15 19:10:46 +0800
commitb4524f05ee0a21176cb9a0e22941b04a3eca3773 (patch)
treeb93dcbe480f103866a9ecbeddb614ac8590daacf /script/vm
parent54e6260b2ac36c4653a30ed5ab5e17d3e7f0abd9 (diff)
downloadlua-language-server-b4524f05ee0a21176cb9a0e22941b04a3eca3773.zip
improve performance
Diffstat (limited to 'script/vm')
-rw-r--r--script/vm/compiler.lua58
-rw-r--r--script/vm/def.lua45
-rw-r--r--script/vm/field.lua2
-rw-r--r--script/vm/global-manager.lua14
-rw-r--r--script/vm/local-id.lua15
-rw-r--r--script/vm/vm.lua2
6 files changed, 83 insertions, 53 deletions
diff --git a/script/vm/compiler.lua b/script/vm/compiler.lua
index 69b1ac25..3840c857 100644
--- a/script/vm/compiler.lua
+++ b/script/vm/compiler.lua
@@ -18,7 +18,7 @@ local vm = require 'vm.vm'
local searchFieldSwitch = util.switch()
: case 'table'
- : call(function (suri, source, key, pushResult)
+ : call(function (suri, source, key, ref, pushResult)
local hasFiled = false
for _, field in ipairs(source) do
if field.type == 'tablefield'
@@ -52,16 +52,16 @@ local searchFieldSwitch = util.switch()
end
end)
: case 'string'
- : call(function (suri, source, key, pushResult)
+ : call(function (suri, source, key, ref, pushResult)
-- change to `string: stringlib` ?
local stringlib = globalMgr.getGlobal('type', 'stringlib')
if stringlib then
- vm.getClassFields(suri, stringlib, key, pushResult)
+ vm.getClassFields(suri, stringlib, key, ref, pushResult)
end
end)
: case 'local'
: case 'self'
- : call(function (suri, node, key, pushResult)
+ : call(function (suri, node, key, ref, pushResult)
local fields
if key then
fields = localID.getSources(node, key)
@@ -70,12 +70,14 @@ local searchFieldSwitch = util.switch()
end
if fields then
for _, src in ipairs(fields) do
- pushResult(src)
+ if ref or guide.isSet(src) then
+ pushResult(src)
+ end
end
end
end)
: case 'doc.type.array'
- : call(function (suri, source, key, pushResult)
+ : call(function (suri, source, key, ref, pushResult)
if type(key) == 'number' then
if key < 1
or not math.tointeger(key) then
@@ -85,7 +87,7 @@ local searchFieldSwitch = util.switch()
pushResult(source.node)
end)
: case 'doc.type.table'
- : call(function (suri, source, key, pushResult)
+ : call(function (suri, source, key, ref, pushResult)
for _, field in ipairs(source.fields) do
local fieldKey = field.name
if fieldKey.type == 'doc.type' then
@@ -111,7 +113,7 @@ local searchFieldSwitch = util.switch()
end
end)
: case 'global'
- : call(function (suri, node, key, pushResult)
+ : call(function (suri, node, key, ref, pushResult)
if node.cate == 'variable' then
if key then
if type(key) ~= 'string' then
@@ -122,8 +124,10 @@ local searchFieldSwitch = util.switch()
for _, set in ipairs(global:getSets(suri)) do
pushResult(set)
end
- for _, get in ipairs(global:getGets(suri)) do
- pushResult(get)
+ if ref then
+ for _, get in ipairs(global:getGets(suri)) do
+ pushResult(get)
+ end
end
end
else
@@ -132,17 +136,19 @@ local searchFieldSwitch = util.switch()
for _, set in ipairs(global:getSets(suri)) do
pushResult(set)
end
- for _, get in ipairs(global:getGets(suri)) do
- pushResult(get)
+ if ref then
+ for _, get in ipairs(global:getGets(suri)) do
+ pushResult(get)
+ end
end
end
end
end
if node.cate == 'type' then
- vm.getClassFields(suri, node, key, pushResult)
+ vm.getClassFields(suri, node, key, ref, pushResult)
end
end)
- : default(function (suri, source, key, pushResult)
+ : default(function (suri, source, key, ref, pushResult)
local node = source._globalNode
if not node then
return
@@ -174,12 +180,12 @@ local searchFieldSwitch = util.switch()
end
end
if node.cate == 'type' then
- vm.getClassFields(suri, node, key, pushResult)
+ vm.getClassFields(suri, node, key, ref, pushResult)
end
end)
-function vm.getClassFields(suri, node, key, pushResult)
+function vm.getClassFields(suri, node, key, ref, pushResult)
local mark = {}
local function searchClass(class, searchedFields)
@@ -206,7 +212,7 @@ function vm.getClassFields(suri, node, key, pushResult)
-- check local field and global field
if set.bindSources then
for _, src in ipairs(set.bindSources) do
- searchFieldSwitch(src.type, suri, src, key, function (field)
+ searchFieldSwitch(src.type, suri, src, key, ref, function (field)
local fieldKey = guide.getKeyName(field)
if not searchedFields[fieldKey]
and guide.isSet(field) then
@@ -215,7 +221,7 @@ function vm.getClassFields(suri, node, key, pushResult)
end
end)
if src.value and src.value.type == 'table' then
- searchFieldSwitch('table', suri, src.value, key, function (field)
+ searchFieldSwitch('table', suri, src.value, key, ref, function (field)
local fieldKey = guide.getKeyName(field)
if not searchedFields[fieldKey]
and guide.isSet(field) then
@@ -361,7 +367,7 @@ local function getReturnOfSetMetaTable(args)
node:merge(vm.compileNode(tbl))
end
if mt then
- vm.compileByParentNode(mt, '__index', function (src)
+ vm.compileByParentNode(mt, '__index', false, function (src)
for n in vm.compileNode(src):eachObject() do
if n.type == 'global'
or n.type == 'local'
@@ -529,11 +535,11 @@ end
---@param source vm.node
---@param key? any
---@param pushResult fun(source: parser.object)
-function vm.compileByParentNode(source, key, pushResult)
+function vm.compileByParentNode(source, key, ref, pushResult)
local parentNode = vm.compileNode(source)
local suri = guide.getUri(source)
for node in parentNode:eachObject() do
- searchFieldSwitch(node.type, suri, node, key, pushResult)
+ searchFieldSwitch(node.type, suri, node, key, ref, pushResult)
end
end
@@ -903,7 +909,7 @@ local compilerSwitch = util.switch()
if key == nil then
return
end
- vm.compileByParentNode(source.node, key, function (src)
+ vm.compileByParentNode(source.node, key, false, function (src)
if src.type == 'doc.type.field'
or src.type == 'doc.field' then
vm.setNode(source, vm.compileNode(src))
@@ -929,7 +935,7 @@ local compilerSwitch = util.switch()
vm.setNode(source, value)
end
else
- vm.compileByParentNode(source.node, key, function (src)
+ vm.compileByParentNode(source.node, key, false, function (src)
vm.setNode(source, vm.compileNode(src))
end)
end
@@ -940,7 +946,7 @@ local compilerSwitch = util.switch()
return
end
local key = guide.getKeyName(source)
- vm.compileByParentNode(source.node, key, function (src)
+ vm.compileByParentNode(source.node, key, false, function (src)
if src.type == 'doc.type.field'
or src.type == 'doc.field' then
vm.setNode(source, vm.compileNode(src))
@@ -953,7 +959,7 @@ local compilerSwitch = util.switch()
return
end
local key = guide.getKeyName(source)
- vm.compileByParentNode(source.node, key, function (src)
+ vm.compileByParentNode(source.node, key, false, function (src)
vm.setNode(source, vm.compileNode(src))
end)
end)
@@ -976,7 +982,7 @@ local compilerSwitch = util.switch()
end
if not hasMarkDoc then
- vm.compileByParentNode(source.parent, guide.getKeyName(source), function (src)
+ vm.compileByParentNode(source.parent, guide.getKeyName(source), false, function (src)
vm.setNode(source, vm.compileNode(src))
end)
end
diff --git a/script/vm/def.lua b/script/vm/def.lua
index 40eb7b90..b66e8fda 100644
--- a/script/vm/def.lua
+++ b/script/vm/def.lua
@@ -105,7 +105,7 @@ local searchFieldSwitch = util.switch()
end
end
if obj.cate == 'type' then
- vm.getClassFields(suri, obj, key, pushResult)
+ vm.getClassFields(suri, obj, key, false, pushResult)
end
end)
: case 'local'
@@ -131,12 +131,11 @@ local searchFieldSwitch = util.switch()
end
end)
-local searchByParentNode
-local nodeSwitch = util.switch()
+local nodeSwitch;nodeSwitch = util.switch()
: case 'field'
: case 'method'
- : call(function (source, pushResult)
- searchByParentNode(source.parent, pushResult)
+ : call(function (source, lastKey, pushResult)
+ return nodeSwitch(source.parent.type, source.parent, lastKey, pushResult)
end)
: case 'getfield'
: case 'setfield'
@@ -144,23 +143,36 @@ local nodeSwitch = util.switch()
: case 'setmethod'
: case 'getindex'
: case 'setindex'
- : call(function (source, pushResult)
+ : call(function (source, lastKey, pushResult)
local parentNode = vm.compileNode(source.node)
local uri = guide.getUri(source)
local key = guide.getKeyName(source)
+ if not key then
+ return
+ end
+ if lastKey then
+ key = key .. vm.ID_SPLITE .. lastKey
+ end
for pn in parentNode:eachObject() do
searchFieldSwitch(pn.type, uri, pn, key, pushResult)
end
+ return key, source.node
end)
: case 'tableindex'
: case 'tablefield'
- : call(function (source, pushResult)
+ : call(function (source, lastKey, pushResult)
+ if lastKey then
+ return
+ end
local tbl = source.parent
local uri = guide.getUri(source)
searchFieldSwitch(tbl.type, uri, tbl, guide.getKeyName(source), pushResult)
end)
: case 'doc.see.field'
- : call(function (source, pushResult)
+ : call(function (source, lastKey, pushResult)
+ if lastKey then
+ return
+ end
local parentNode = vm.compileNode(source.parent.name)
local uri = guide.getUri(source)
for pn in parentNode:eachObject() do
@@ -190,8 +202,21 @@ end
---@param source parser.object
---@param pushResult fun(src: parser.object)
-function searchByParentNode(source, pushResult)
- nodeSwitch(source.type, source, pushResult)
+local function searchByParentNode(source, pushResult)
+ local lastKey
+ local src = source
+ while true do
+ local key, node = nodeSwitch(src.type, src, lastKey, pushResult)
+ if not key then
+ break
+ end
+ src = node
+ if lastKey then
+ lastKey = key .. vm.ID_SPLITE .. lastKey
+ else
+ lastKey = key
+ end
+ end
end
local function searchByNode(source, pushResult)
diff --git a/script/vm/field.lua b/script/vm/field.lua
index 0968df11..ba7cd4c1 100644
--- a/script/vm/field.lua
+++ b/script/vm/field.lua
@@ -17,7 +17,7 @@ local searchByNodeSwitch = util.switch()
local function searchByNode(source, pushResult)
local uri = guide.getUri(source)
- vm.compileByParentNode(source, nil, function (field)
+ vm.compileByParentNode(source, nil, true, function (field)
searchByNodeSwitch(field.type, uri, field, pushResult)
end)
end
diff --git a/script/vm/global-manager.lua b/script/vm/global-manager.lua
index 9713856e..2a3aea2f 100644
--- a/script/vm/global-manager.lua
+++ b/script/vm/global-manager.lua
@@ -16,8 +16,6 @@ m.globals = {}
---@type table<uri, table<string, boolean>>
m.globalSubs = util.multiTable(2)
-m.ID_SPLITE = '\x1F'
-
local compilerGlobalSwitch = util.switch()
: case 'local'
: call(function (source)
@@ -76,7 +74,7 @@ local compilerGlobalSwitch = util.switch()
if parentName == '_G' then
name = keyName
else
- name = ('%s%s%s'):format(parentName, m.ID_SPLITE, keyName)
+ name = ('%s%s%s'):format(parentName, vm.ID_SPLITE, keyName)
end
elseif source.node.special == '_G' then
name = keyName
@@ -104,7 +102,7 @@ local compilerGlobalSwitch = util.switch()
if parentName == '_G' then
name = keyName
else
- name = ('%s%s%s'):format(parentName, m.ID_SPLITE, keyName)
+ name = ('%s%s%s'):format(parentName, vm.ID_SPLITE, keyName)
end
elseif source.node.special == '_G' then
name = keyName
@@ -227,7 +225,7 @@ end
function m.getGlobal(cate, name, field)
local key = cate .. '|' .. name
if field then
- key = key .. m.ID_SPLITE .. field
+ key = key .. vm.ID_SPLITE .. field
end
return m.globals[key]
end
@@ -244,8 +242,8 @@ function m.getFields(cate, name)
for gid, global in pairs(m.globals) do
if gid ~= key
and util.stringStartWith(gid, key)
- and gid:sub(#key + 1, #key + 1) == m.ID_SPLITE
- and not gid:find(m.ID_SPLITE, #key + 2) then
+ 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
@@ -266,7 +264,7 @@ function m.getGlobals(cate)
local clock = os.clock()
for gid, global in pairs(m.globals) do
if util.stringStartWith(gid, cate)
- and not gid:find(m.ID_SPLITE) then
+ and not gid:find(vm.ID_SPLITE) then
globals[#globals+1] = global
end
end
diff --git a/script/vm/local-id.lua b/script/vm/local-id.lua
index aa4f3118..728de301 100644
--- a/script/vm/local-id.lua
+++ b/script/vm/local-id.lua
@@ -1,5 +1,6 @@
local util = require 'utility'
local guide = require 'parser.guide'
+local vm = require 'vm.vm'
---@class parser.object
---@field _localID string
@@ -8,8 +9,6 @@ local guide = require 'parser.guide'
---@class vm.local-id
local m = {}
-m.ID_SPLITE = '\x1F'
-
local compileSwitch = util.switch()
: case 'local'
: case 'self'
@@ -38,7 +37,7 @@ local compileSwitch = util.switch()
if type(key) ~= 'string' then
return
end
- source._localID = parentID .. m.ID_SPLITE .. key
+ source._localID = parentID .. vm.ID_SPLITE .. key
source.field._localID = source._localID
if source.type == 'getfield' then
m.compileLocalID(source.next)
@@ -55,7 +54,7 @@ local compileSwitch = util.switch()
if type(key) ~= 'string' then
return
end
- source._localID = parentID .. m.ID_SPLITE .. key
+ source._localID = parentID .. vm.ID_SPLITE .. key
source.method._localID = source._localID
if source.type == 'getmethod' then
m.compileLocalID(source.next)
@@ -72,7 +71,7 @@ local compileSwitch = util.switch()
if type(key) ~= 'string' then
return
end
- source._localID = parentID .. m.ID_SPLITE .. key
+ source._localID = parentID .. vm.ID_SPLITE .. key
source.index._localID = source._localID
if source.type == 'setindex' then
m.compileLocalID(source.next)
@@ -160,7 +159,7 @@ function m.getSources(source, key)
if type(key) ~= 'string' then
return nil
end
- id = id .. m.ID_SPLITE .. key
+ id = id .. vm.ID_SPLITE .. key
end
return root._localIDs[id]
end
@@ -182,9 +181,9 @@ function m.getFields(source)
for lid, sources in pairs(root._localIDs) do
if lid ~= id
and util.stringStartWith(lid, id)
- and lid:sub(#id + 1, #id + 1) == m.ID_SPLITE
+ and lid:sub(#id + 1, #id + 1) == vm.ID_SPLITE
-- only one field
- and not lid:find(m.ID_SPLITE, #id + 2) then
+ and not lid:find(vm.ID_SPLITE, #id + 2) then
for _, src in ipairs(sources) do
fields[#fields+1] = src
end
diff --git a/script/vm/vm.lua b/script/vm/vm.lua
index d370de0d..3c1762bf 100644
--- a/script/vm/vm.lua
+++ b/script/vm/vm.lua
@@ -14,6 +14,8 @@ _ENV = nil
---@class vm
local m = {}
+m.ID_SPLITE = '\x1F'
+
function m.getSpecial(source)
if not source then
return nil