diff options
author | sumneko <sumneko@hotmail.com> | 2019-04-09 11:21:52 +0800 |
---|---|---|
committer | sumneko <sumneko@hotmail.com> | 2019-04-09 11:21:52 +0800 |
commit | 41aec953bfa0f584ceb8de7c2f6203cb2075a215 (patch) | |
tree | 1148d9f97833966f855118f3895aa73f4b11deba | |
parent | b9ef666714e03e2108f4b1f8c245e721dc4fb2fb (diff) | |
download | lua-language-server-41aec953bfa0f584ceb8de7c2f6203cb2075a215.zip |
实现 module 与 package.seeall
-rw-r--r-- | package.json | 1 | ||||
-rw-r--r-- | server/libs/lua/basic.lni | 1 | ||||
-rw-r--r-- | server/libs/lua/package.lni | 7 | ||||
-rw-r--r-- | server/locale/en-US/libs/lua/coroutine.lni | 3 | ||||
-rw-r--r-- | server/locale/en-US/libs/lua/package.lni | 3 | ||||
-rw-r--r-- | server/locale/zh-CN/libs/lua/debug.lni | 3 | ||||
-rw-r--r-- | server/locale/zh-CN/libs/lua/math.lni | 4 | ||||
-rw-r--r-- | server/locale/zh-CN/libs/lua/package.lni | 3 | ||||
-rw-r--r-- | server/src/vm/manager.lua | 5 | ||||
-rw-r--r-- | server/src/vm/module.lua | 56 | ||||
-rw-r--r-- | server/src/vm/vm.lua | 43 |
11 files changed, 115 insertions, 14 deletions
diff --git a/package.json b/package.json index 102f73d5..489ac0fc 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "type": "string", "default": "Lua 5.3", "enum": [ + "Lua 5.1", "Lua 5.2", "Lua 5.3", "Lua 5.4" diff --git a/server/libs/lua/basic.lni b/server/libs/lua/basic.lni index a1463c00..9f6c2d75 100644 --- a/server/libs/lua/basic.lni +++ b/server/libs/lua/basic.lni @@ -294,6 +294,7 @@ type = 'string' [module] version = 'Lua 5.1' +special = 'module' [[.args]] name = name type = string diff --git a/server/libs/lua/package.lni b/server/libs/lua/package.lni index 85234fab..43ae7344 100644 --- a/server/libs/lua/package.lni +++ b/server/libs/lua/package.lni @@ -67,3 +67,10 @@ default = '.' name = 'rep' type = 'string' optional = 'self' + +[seeall] +version = 'Lua 5.1' +special = seeall +[[.args]] +name = module +type = table diff --git a/server/locale/en-US/libs/lua/coroutine.lni b/server/locale/en-US/libs/lua/coroutine.lni index ec06f21d..3859ad4e 100644 --- a/server/locale/en-US/libs/lua/coroutine.lni +++ b/server/locale/en-US/libs/lua/coroutine.lni @@ -5,8 +5,7 @@ description = 'Creates a new coroutine.' description = 'Returns true when the running coroutine can yield.' [kill] -description = 'Kills coroutine `co` , -closing all its pending to-be-closed variables and putting the coroutine in a dead state.' +description = 'Kills coroutine `co` , closing all its pending to-be-closed variables and putting the coroutine in a dead state.' [resume] description = 'Starts or continues the execution of coroutine `co`.' diff --git a/server/locale/en-US/libs/lua/package.lni b/server/locale/en-US/libs/lua/package.lni index b0a861a9..3b482ae9 100644 --- a/server/locale/en-US/libs/lua/package.lni +++ b/server/locale/en-US/libs/lua/package.lni @@ -24,3 +24,6 @@ description = 'A table used by `require` to control how to load modules.' [searchpath] description = 'Searches for the given `name` in the given `path`.' + +[seeall] +describing = 'Sets a metatable for `module` with its `__index` field referring to the global environment, so that this module inherits values from the global environment. To be used as an option to function `module` . diff --git a/server/locale/zh-CN/libs/lua/debug.lni b/server/locale/zh-CN/libs/lua/debug.lni index 18c514c9..22e6d3b3 100644 --- a/server/locale/zh-CN/libs/lua/debug.lni +++ b/server/locale/zh-CN/libs/lua/debug.lni @@ -2,7 +2,7 @@ description = '进入一个用户交互模式,运行用户输入的每个字符串。' [getfenv] -description = '返回对象 `o` 的环境。` +description = '返回对象 `o` 的环境。' [gethook] description = '返回三个表示线程钩子设置的值: 当前钩子函数,当前钩子掩码,当前钩子计数 。' @@ -85,7 +85,6 @@ description = '将 `value` 设为函数 `f` 的第 `up` 个上值。' ["setuservalue Lua 5.4"] description = '将 `value` 设为 `udata` 的第 `n` 个关联值。' -值。' [setuservalue] description = '将 `value` 设为 `udata` 的关联值。' diff --git a/server/locale/zh-CN/libs/lua/math.lni b/server/locale/zh-CN/libs/lua/math.lni index 2f42b9e8..f1a6768a 100644 --- a/server/locale/zh-CN/libs/lua/math.lni +++ b/server/locale/zh-CN/libs/lua/math.lni @@ -50,10 +50,10 @@ description = '返回 `m * (2 ^ e)` 。' description = '返回以指定底的 `x` 的对数。' ['log Lua 5.1'] -description = '返回 `x` 的自然对数。` +description = '返回 `x` 的自然对数。' [log10] -description = '返回 `x` 的以10为底的对数。 +description = '返回 `x` 的以10为底的对数。' [max] description = '返回参数中最大的值, 大小由 Lua 操作 `<` 决定。' diff --git a/server/locale/zh-CN/libs/lua/package.lni b/server/locale/zh-CN/libs/lua/package.lni index 74dc0239..209a9dc1 100644 --- a/server/locale/zh-CN/libs/lua/package.lni +++ b/server/locale/zh-CN/libs/lua/package.lni @@ -24,3 +24,6 @@ description = '用于 `require` 控制如何加载模块的表。' [searchpath] description = '在指定 `path` 中搜索指定的 `name` 。' + +[seeall] +description = '给 `module` 设置一个元表,该元表的 `__index` 域为全局环境,这样模块便会继承全局环境的值。可作为 `module` 函数的选项。' diff --git a/server/src/vm/manager.lua b/server/src/vm/manager.lua new file mode 100644 index 00000000..2016465b --- /dev/null +++ b/server/src/vm/manager.lua @@ -0,0 +1,5 @@ +local mt = {} +mt.__index = mt +mt.type = 'vm' + +return mt diff --git a/server/src/vm/module.lua b/server/src/vm/module.lua new file mode 100644 index 00000000..60191bf3 --- /dev/null +++ b/server/src/vm/module.lua @@ -0,0 +1,56 @@ +local mt = require 'vm.manager' +local createMulti = require 'vm.multi' + +--[[ +function module(name, ...) + local env = {} + for _, opt in ipairs {...} do + opt(env) + end + @ENV = env +end +--]] +function mt:callModuel(func, values) + local envLoc = self:loadLocal('@ENV') + if not envLoc then + return + end + local source = self:getDefaultSource() + local newEnvValue = self:createValue('table', source) + local args = createMulti() + + args:push(newEnvValue) + + for i = 2, #values do + local value = values[i] + -- opt(env) + self:call(value, args, source) + end + + -- @ENV = env + envLoc:setValue(newEnvValue) +end + +--[[ +function package.seeall(env) + setmetatable(env, { __index = @ENV }) +end +--]] +function mt:callSeeAll(func, values) + local newEnv = values[1] + if not newEnv then + return + end + local envLoc = self:loadLocal('@ENV') + if not envLoc then + return + end + local oldEnv = envLoc:getValue() + if not oldEnv then + return + end + local source = self:getDefaultSource() + local meta = self:createValue('table', source) + meta:setChild('__index', oldEnv, source) + newEnv:setMetaTable(meta) +end diff --git a/server/src/vm/vm.lua b/server/src/vm/vm.lua index 02ced843..2a223d42 100644 --- a/server/src/vm/vm.lua +++ b/server/src/vm/vm.lua @@ -7,13 +7,14 @@ local sourceMgr = require 'vm.source' local buildGlobal = require 'vm.global' local createMulti = require 'vm.multi' local libraryBuilder = require 'vm.library' +local config = require 'config' +local mt = require 'vm.manager' + +require 'vm.module' -- TODO source测试 --rawset(_G, 'CachedSource', setmetatable({}, { __mode = 'kv' })) -local mt = {} -mt.__index = mt - function mt:getDefaultSource() return self:instantSource { start = 0, @@ -272,6 +273,10 @@ function mt:callLibrary(func, values, source, lib) self:callLoadFile(func, values) elseif lib.special == 'dofile' then self:callDoFile(func, values) + elseif lib.special == 'module' then + self:callModuel(func, values) + elseif lib.special == 'seeall' then + self:callSeeAll(func, values) end end end @@ -324,7 +329,12 @@ function mt:getName(name, source) if global then return global end - local ENV = self:loadLocal('_ENV') + local ENV + if self.envType == '_ENV' then + ENV = self:loadLocal('_ENV') + else + ENV = self:loadLocal('@ENV') + end local ENVValue = ENV:getValue() ENVValue:addInfo('get child', source, name) global = ENVValue:getChild(name, source) @@ -351,7 +361,12 @@ function mt:setName(name, source, value) if global then return global end - local ENV = self:loadLocal('_ENV') + local ENV + if self.envType == '_ENV' then + ENV = self:loadLocal('_ENV') + else + ENV = self:loadLocal('@ENV') + end local ENVValue = ENV:getValue() source:bindValue(value, 'set') ENVValue:setChild(name, value, source) @@ -1120,8 +1135,15 @@ function mt:createEnvironment(ast) end -- 全局变量`_G` local global = buildGlobal(self.lsp) - -- 隐藏的上值`_ENV` - local env = self:createLocal('_ENV', self:getDefaultSource(), global) + local env + if self.envType == '_ENV' then + -- 隐藏的上值`_ENV` + env = self:createLocal('_ENV', self:getDefaultSource(), global) + else + -- 为了实现方便,fenv也使用隐藏上值来实现 + -- 使用了非法标识符保证用户无法访问 + env = self:createLocal('@ENV', self:getDefaultSource(), global) + end env:set('hide', true) self.env = env end @@ -1159,9 +1181,14 @@ function mt:remove() end local function compile(vm, ast, lsp, uri) - -- 创建初始环境 ast.uri = vm.uri + -- 根据运行版本决定环境实现方式 + if config.config.runtime.version == 'Lua 5.1' then + vm.envType = 'fenv' + else + vm.envType = '_ENV' + end vm:instantSource(ast) vm:createEnvironment(ast) |