summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--server/src/matcher/diagnostics.lua7
-rw-r--r--server/src/matcher/find_lib.lua157
-rw-r--r--server/src/matcher/library.lua1
-rw-r--r--server/src/matcher/vm.lua51
4 files changed, 55 insertions, 161 deletions
diff --git a/server/src/matcher/diagnostics.lua b/server/src/matcher/diagnostics.lua
index e896e4b5..bb9367fc 100644
--- a/server/src/matcher/diagnostics.lua
+++ b/server/src/matcher/diagnostics.lua
@@ -1,5 +1,3 @@
-local findLib = require 'matcher.find_lib'
-
local function searchUnusedLocals(results, callback)
for _, var in ipairs(results.locals) do
if var.key == 'self'
@@ -12,6 +10,11 @@ local function searchUnusedLocals(results, callback)
if info.type == 'get' then
goto NEXT_VAR
end
+ if info.type == 'local' then
+ if info.source.start == 0 then
+ goto NEXT_VAR
+ end
+ end
end
callback(var.source.start, var.source.finish, var.key)
::NEXT_VAR::
diff --git a/server/src/matcher/find_lib.lua b/server/src/matcher/find_lib.lua
index f6c453b4..d2b5d6a8 100644
--- a/server/src/matcher/find_lib.lua
+++ b/server/src/matcher/find_lib.lua
@@ -1,150 +1,29 @@
-local library = require 'matcher.library'
-
-local function isGlobal(var)
- if var.type ~= 'field' then
- return false
- end
- if not var.parent then
- return false
- end
- return var.parent.key == '_ENV' or var.parent.key == '_G'
-end
-
-local function checkSourceAsGlobal(value, name, showname)
- if value.key == name and isGlobal(value) then
- return showname or name
- end
- return nil
-end
-
-local function checkSourceAsLibrary(value, name, showname)
- if value.type ~= 'lib' then
- return nil
- end
- if value.name == name then
- return showname or name
- end
- return nil
-end
-
-local function checkSource(value, libname, lib)
- if not lib then
- return
- end
- if not lib.source then
- return checkSourceAsGlobal(value, libname)
- end
- for _, source in ipairs(lib.source) do
- if source.type == 'global' then
- local fullKey = checkSourceAsGlobal(value, source.name or libname, source.nick or libname)
- if fullKey then
- return fullKey
- end
- elseif source.type == 'library' then
- local fullKey = checkSourceAsLibrary(value, source.name or libname, source.nick or libname)
- if fullKey then
- return fullKey
- end
- end
- end
- return nil
-end
-
-local function checkParentAsGlobal(parentValue, name, parent)
- local parentName = checkSourceAsGlobal(parentValue, parent.name, parent.nick)
- if not parentName then
- return nil
- end
- return ('%s.%s'):format(parentName, name)
-end
-
-local function checkParentAsLibrary(parentValue, name, parent)
- local parentName = checkSourceAsLibrary(parentValue, parent.name, parent.nick)
- if not parentName then
- return nil
- end
- return ('%s.%s'):format(parentName, name)
-end
-
-local function checkParentAsObject(parentValue, name, parent)
- if parentValue.type ~= parent.name then
- return nil
- end
- return ('*%s:%s'):format(parent.name, name)
-end
-
-local function checkParent(value, name, lib)
- if name ~= value.key then
- return nil
- end
- local parentValue = value.parent
- if not parentValue then
- return nil
- end
- parentValue = parentValue.value or parentValue
- for _, parent in ipairs(lib.parent) do
- if parent.type == 'global' then
- local fullKey = checkParentAsGlobal(parentValue, name, parent)
- if fullKey then
- return fullKey, false
- end
- elseif parent.type == 'library' then
- local fullKey = checkParentAsLibrary(parentValue, name, parent)
- if fullKey then
- return fullKey, false
- end
- elseif parent.type == 'object' then
- local fullKey = checkParentAsObject(parentValue, name, parent)
- if fullKey then
- return fullKey, true
- end
- end
- end
- return nil
-end
-
local function findLib(var)
local value = var.value
- if value.lib then
- return value.lib, value.lib.name, false
- end
- for libname, info in pairs(library.global) do
- local fullKey = checkSource(value, libname, info.lib)
- if fullKey then
- return info.lib, fullKey, false
- end
- for libname, lib in pairs(info.child) do
- local fullKey, oo = checkParent(value, libname, lib)
- if fullKey then
- return lib, fullKey, oo
- end
- end
+ local lib = value.lib
+ if not lib then
+ return nil
end
- for libname, info in pairs(library.library) do
- local fullKey = checkSource(value, libname, info.lib)
- if fullKey then
- return info.lib, fullKey, false
- end
- for libname, lib in pairs(info.child) do
- local fullKey, oo = checkParent(value, libname, lib)
- if fullKey then
- return lib, fullKey, oo
+ if lib.parent then
+ local res
+ for _, parent in ipairs(lib.parent) do
+ if parent.type == value.parentType then
+ res = parent
end
end
- end
- for libname, info in pairs(library.object) do
- local fullKey = checkSource(value, libname, info.lib)
- if fullKey then
- return info.lib, fullKey, false
+ if not res then
+ res = lib.parent[1]
end
- for libname, lib in pairs(info.child) do
- local fullKey, oo = checkParent(value, libname, lib)
- if fullKey then
- return lib, fullKey, oo
- end
+ if res.type == 'object' then
+ local fullKey = ('*%s:%s'):format(res.nick or res.name, lib.name)
+ return lib, fullKey, true
+ else
+ local fullKey = ('%s.%s'):format(res.nick or res.name, lib.name)
+ return lib, fullKey, false
end
+ else
+ return lib, lib.name, false
end
- return nil, nil, nil
end
return function (var)
diff --git a/server/src/matcher/library.lua b/server/src/matcher/library.lua
index f940544a..90fda3cd 100644
--- a/server/src/matcher/library.lua
+++ b/server/src/matcher/library.lua
@@ -71,6 +71,7 @@ local function insert(tbl, name, key, value)
end
if not tbl[name] then
tbl[name] = {
+ type = name,
name = name,
child = {},
}
diff --git a/server/src/matcher/vm.lua b/server/src/matcher/vm.lua
index 7c3124fb..16d5fe20 100644
--- a/server/src/matcher/vm.lua
+++ b/server/src/matcher/vm.lua
@@ -217,9 +217,6 @@ end
function mt:buildFunction(exp, object)
local func = self:createValue('function')
- func.returns = {
- type = 'list',
- }
func.args = {}
if not exp then
@@ -336,7 +333,7 @@ function mt:callRequire(func, values)
if type(str) == 'string' then
local lib = library.library[str]
if lib then
- local value = self:getLibValue(lib)
+ local value = self:getLibValue(lib, 'library')
self:setFunctionReturn(func, 1, value)
return
end
@@ -364,6 +361,12 @@ function mt:getCurrentFunction()
end
function mt:setFunctionReturn(func, index, value)
+ if not func.returns then
+ func.returns = {
+ type = 'list',
+ [1] = self:createValue('nil'),
+ }
+ end
func.returns[index] = value or self:createValue('nil')
end
@@ -386,36 +389,41 @@ function mt:createValue(type, source, v)
return value
end
-function mt:getLibValue(lib)
+function mt:getLibValue(lib, parentType, v)
if self.libraryValue[lib] then
return self.libraryValue[lib]
end
local tp = lib.type
local value
if tp == 'table' then
- value = self:buildTable()
+ value = self:createValue('table')
elseif tp == 'function' then
- value = self:buildFunction()
+ value = self:createValue('function')
if lib.returns then
for i, rtn in ipairs(lib.returns) do
- self:setFunctionReturn(value, i, self:getLibValue(rtn))
+ self:setFunctionReturn(value, i, self:getLibValue(rtn, parentType))
end
end
if lib.args then
+ value.args = {}
local values = {}
+ self.scope:push()
for i, arg in ipairs(lib.args) do
- values[i] = self:getLibValue(arg) or self:createValue('nil')
+ value.args[#value.args+1] = self:createLocal(arg.name)
+
+ values[i] = self:getLibValue(arg, parentType) or self:createValue('nil')
end
+ self.scope:pop()
self:setFunctionArgs(value, values)
end
elseif tp == 'string' then
- value = self:createValue('string', nil, lib.value)
+ value = self:createValue('string', nil, v or lib.value)
elseif tp == 'boolean' then
- value = self:createValue('boolean', nil, lib.value)
+ value = self:createValue('boolean', nil, v or lib.value)
elseif tp == 'number' then
- value = self:createValue('number', nil, lib.value)
+ value = self:createValue('number', nil, v or lib.value)
elseif tp == 'integer' then
- value = self:createValue('integer', nil, lib.value)
+ value = self:createValue('integer', nil, v or lib.value)
elseif tp == 'nil' then
value = self:createValue('nil')
else
@@ -423,11 +431,12 @@ function mt:getLibValue(lib)
end
self.libraryValue[lib] = value
value.lib = lib
+ value.parentType = parentType
if lib.child then
for fName, fLib in pairs(lib.child) do
local fField = self:createField(value, fName)
- local fValue = self:getLibValue(fLib)
+ local fValue = self:getLibValue(fLib, parentType)
self:setValue(fField, fValue)
end
end
@@ -739,7 +748,7 @@ function mt:doIn(action)
local values = self:call(func, args)
self:forList(action.arg, function (arg)
local value = table.remove(values, 1)
- local var = self:createLocal(arg[1], arg, value)
+ self:createLocal(arg[1], arg, value)
end)
self:doActions(action)
@@ -832,20 +841,22 @@ function mt:createEnvironment()
self.chunk.func = self:buildFunction()
-- 隐藏的上值`_ENV`
local parent = self:createLocal('_ENV')
+ local envValue = self:setValue(parent, self:buildTable())
+ -- _ENV 有个特殊标记
+ envValue.ENV = true
-- 隐藏的参数`...`
self:createDots()
- local pValue = self:setValue(parent, self:buildTable())
-- 设置全局变量
for name, lib in pairs(library.global) do
- local field = self:createField(pValue, name)
- local value = self:getLibValue(lib)
+ local field = self:createField(envValue, name)
+ local value = self:getLibValue(lib, 'global')
value = self:setValue(field, value)
end
-- 设置 _G 等于 _ENV
- local g = self:getField(pValue, '_G')
- self:setValue(g, pValue)
+ local g = self:getField(envValue, '_G')
+ self:setValue(g, envValue)
end
local function compile(ast)