diff options
-rw-r--r-- | server/src/matcher/diagnostics.lua | 7 | ||||
-rw-r--r-- | server/src/matcher/find_lib.lua | 157 | ||||
-rw-r--r-- | server/src/matcher/library.lua | 1 | ||||
-rw-r--r-- | server/src/matcher/vm.lua | 51 |
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) |