diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2019-03-04 16:48:58 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2019-03-04 16:48:58 +0800 |
commit | 4843133cf08b1a05c506665b5b84bdf6ccbea884 (patch) | |
tree | 60c58b8e82b780600ae3801c954bd04794fd00f9 /server/src | |
parent | d165bf61b7f9d004cc670f6d5316096406054d2d (diff) | |
download | lua-language-server-4843133cf08b1a05c506665b5b84bdf6ccbea884.zip |
类型推断
Diffstat (limited to 'server/src')
-rw-r--r-- | server/src/vm/dots.lua | 28 | ||||
-rw-r--r-- | server/src/vm/function.lua | 35 | ||||
-rw-r--r-- | server/src/vm/multi.lua | 6 | ||||
-rw-r--r-- | server/src/vm/vm.lua | 111 |
4 files changed, 72 insertions, 108 deletions
diff --git a/server/src/vm/dots.lua b/server/src/vm/dots.lua deleted file mode 100644 index e9a1ac15..00000000 --- a/server/src/vm/dots.lua +++ /dev/null @@ -1,28 +0,0 @@ -local createValue = require 'vm.value' - -local mt = {} -mt.__index = mt -mt.type = 'dots' - -function mt:set(n, value) - self[n] = value -end - -function mt:get(expect) - local result = {} - if expect then - for i = 1, expect do - result[i] = self[i] or createValue('any') - end - else - for i = 1, #self do - result[i] = self[i] - end - end - return result -end - -return function () - local self = setmetatable({}, mt) - return self -end diff --git a/server/src/vm/function.lua b/server/src/vm/function.lua index 145e5eda..f3d4720c 100644 --- a/server/src/vm/function.lua +++ b/server/src/vm/function.lua @@ -1,4 +1,3 @@ -local createDots = require 'vm.dots' local createMulti = require 'vm.multi' local createValue = require 'vm.value' local createLocal = require 'vm.local' @@ -100,7 +99,7 @@ function mt:getReturn(index) self.returns = createMulti() end if index then - return self.returns:get(index) + return self.returns:get(index) or createValue('nil') else return self.returns end @@ -108,16 +107,16 @@ end function mt:returnDots(index) if not self.returns then - self.returns = {} + self.returns = createMulti() end - self.returns[index] = createDots() + self.returns[index] = createMulti() end -function mt:loadDots(expect) +function mt:loadDots() if not self._dots then - self._dots = createDots() + self._dots = createMulti() end - return self._dots:get(expect) + return self._dots end function mt:setObject(value, source) @@ -159,27 +158,29 @@ function mt:run() end function mt:setArgs(values) - if not self.argValues then - self.argValues = {} - end + self.argValues = {} for i = 1, #values do self.argValues[i] = values[i] end end -function mt:createArg(arg) +function mt:createArg(arg, values) if arg.type == 'name' then - local loc = createLocal(arg[1], arg, createValue('any', arg)) + local value = table.remove(values, 1) or createValue('nil', arg) + local loc = createLocal(arg[1], arg, value) self:saveLocal(arg[1], loc) self.args[#self.args+1] = loc elseif arg.type == '...' then - self._dots = createDots() + self._dots = createMulti(values) + for i = 1, #values do + self._dots:set(i, values[i]) + end end end function mt:createLibArg(arg) if arg.type == '...' then - self._dots = createDots() + self._dots = createMulti() else local name = arg.name or '_' local loc = createLocal(name, nil, createValue('any')) @@ -200,12 +201,14 @@ function mt:createArgs() if not args then return end + local values = self.argValues or {} + self.argValues = nil if args.type == 'list' then for _, arg in ipairs(args) do - self:createArg(arg) + self:createArg(arg, values) end else - self:createArg(args) + self:createArg(args, values) end end diff --git a/server/src/vm/multi.lua b/server/src/vm/multi.lua index 93900a36..f4f21b86 100644 --- a/server/src/vm/multi.lua +++ b/server/src/vm/multi.lua @@ -64,6 +64,12 @@ function mt:eachValue(callback) end end +function mt:merge(other) + other:eachValue(function (_, value) + self:push(value) + end) +end + return function () local self = setmetatable({}, mt) return self diff --git a/server/src/vm/vm.lua b/server/src/vm/vm.lua index 8c8be4f7..d2057ca7 100644 --- a/server/src/vm/vm.lua +++ b/server/src/vm/vm.lua @@ -40,17 +40,6 @@ function mt:eachInfo(var, callback) return nil end -function mt:createDots(index, source) - local dots = { - type = 'dots', - source = source or self:getDefaultSource(), - func = self:getCurrentFunction(), - index = index, - } - self.chunk.dots = dots - return dots -end - function mt:buildTable(source) local tbl = self:createValue('table', source) if not source then @@ -283,53 +272,57 @@ function mt:callDoFile(func, values) func:setReturn(1, requireValue) end +function mt:callLibrary(func, values, source, lib) + if lib.args then + for i, arg in ipairs(lib.args) do + local value = values[i] + if value and arg.type ~= '...' then + value:setType(arg.type, 1.0) + end + end + end + if lib.returns then + for i, rtn in ipairs(lib.returns) do + if rtn.type == '...' then + --func:getReturn(i):setType('any', 0.0) + else + func:getReturn(i):setType(rtn.type or 'any', 1.0) + end + end + end + if lib.special then + if lib.special == 'setmetatable' then + self:callSetMetaTable(func, values, source) + elseif lib.special == 'require' then + self:callRequire(func, values) + elseif lib.special == 'loadfile' then + self:callLoadFile(func, values) + elseif lib.special == 'dofile' then + self:callDoFile(func, values) + end + end +end + function mt:call(value, values, source) - local lib = value.lib + local lib = value:getLib() local func = value:getFunction() if not func then return end if lib then - if lib.args then - for i, arg in ipairs(lib.args) do - local value = values[i] - if value and arg.type ~= '...' then - value:setType(arg.type, 1.0) - end - end - end - if lib.returns then - for i, rtn in ipairs(lib.returns) do - if rtn.type == '...' then - func:getReturn(i):setType('any', 0.0) - else - func:getReturn(i):setType(rtn.type or 'any', 1.0) - end - end - end - if lib.special then - if lib.special == 'setmetatable' then - self:callSetMetaTable(func, values, source) - elseif lib.special == 'require' then - self:callRequire(func, values) - elseif lib.special == 'loadfile' then - self:callLoadFile(func, values) - elseif lib.special == 'dofile' then - self:callDoFile(func, values) - end - end + self:callLibrary(func, values, source, lib) else - if not func.source then + if func.source then + if not source:getFlag 'called' then + source:setFlag('called', true) + func:setArgs(values) + self:runFunction(func) + end + else func:setReturn(1, self:createValue('any', source)) end end - if not source.hasRuned and func.source then - source.hasRuned = true - func:setArgs(values) - self:runFunction(func) - end - return func:getReturn() end @@ -393,15 +386,7 @@ function mt:getIndex(source) end end --- expect表示遇到 ... 时,期待的返回数量 -function mt:unpackDots(res, expect) - local dots = self:loadDots(expect) - for _, v in ipairs(dots) do - res:push(v) - end -end - -function mt:unpackList(list, expect) +function mt:unpackList(list) local res = createMulti() if not list then return res @@ -409,7 +394,7 @@ function mt:unpackList(list, expect) if list.type == 'list' or list.type == 'call' or list.type == 'return' then for i, exp in ipairs(list) do if exp.type == '...' then - self:unpackDots(res, expect) + res:merge(self:loadDots()) break end local value = self:getExp(exp) @@ -426,7 +411,7 @@ function mt:unpackList(list, expect) end end elseif list.type == '...' then - self:unpackDots(res, expect) + res:merge(self:loadDots()) else local value = self:getExp(list) if value.type == 'multi' then @@ -463,7 +448,7 @@ function mt:getSimple(simple, max) for i = 2, max do local source = simple[i] self:instantSource(source) - value = self:getFirstInMulti(value) + value = self:getFirstInMulti(value) or createValue('nil') if source.type == 'call' then local args = self:unpackList(source) @@ -660,9 +645,7 @@ function mt:getExp(exp) elseif tp == 'table' then return self:buildTable(exp) elseif tp == '...' then - local value = { type = 'list' } - self:unpackDots(value) - return value + return self:loadDots() elseif tp == 'list' then return self:getMultiByList(exp) end @@ -1026,8 +1009,8 @@ function mt:loadLabel(name) return self.currentFunction:loadLabel(name) end -function mt:loadDots(expect) - return self.currentFunction:loadDots(expect) +function mt:loadDots() + return self.currentFunction:loadDots() end function mt:getUri() |