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 /server/src | |
parent | b9ef666714e03e2108f4b1f8c245e721dc4fb2fb (diff) | |
download | lua-language-server-41aec953bfa0f584ceb8de7c2f6203cb2075a215.zip |
实现 module 与 package.seeall
Diffstat (limited to 'server/src')
-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 |
3 files changed, 96 insertions, 8 deletions
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) |