diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2019-01-31 18:11:10 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2019-01-31 18:11:10 +0800 |
commit | 076aca36bab28e805a85ee2e6a8f347a9ea83ba7 (patch) | |
tree | e4b226855365c6812b7b1c97dfe8d16decd9cf5d /server/src/vm | |
parent | 92424baf13c2487145456e4062f9f4214f8b7bcd (diff) | |
download | lua-language-server-076aca36bab28e805a85ee2e6a8f347a9ea83ba7.zip |
整理代码
Diffstat (limited to 'server/src/vm')
-rw-r--r-- | server/src/vm/function.lua | 103 | ||||
-rw-r--r-- | server/src/vm/label.lua | 15 | ||||
-rw-r--r-- | server/src/vm/multi.lua | 46 | ||||
-rw-r--r-- | server/src/vm/source.lua | 15 | ||||
-rw-r--r-- | server/src/vm/vm.lua | 153 |
5 files changed, 235 insertions, 97 deletions
diff --git a/server/src/vm/function.lua b/server/src/vm/function.lua index 90f975ae..0d9c4489 100644 --- a/server/src/vm/function.lua +++ b/server/src/vm/function.lua @@ -5,32 +5,67 @@ local mt = {} mt.__index = mt mt.type = 'function' mt._runed = 0 +mt._top = 0 function mt:getUri() return self.source.uri end +function mt:push() + self._top = self._top + 1 + self.locals[self._top] = {} +end + +function mt:pop() + self._top = self._top - 1 +end + function mt:saveLocal(name, loc) - self.locals[name] = loc + self.locals[self._top][name] = loc end function mt:loadLocal(name) - local loc = self.locals[name] - if loc then - return loc - end - loc = self.upvalues(name) - if loc then - return loc + for i = self._top, 1, -1 do + local locals = self.locals[i] + local loc = locals[name] + if loc then + return loc + end end return nil end function mt:eachLocal(callback) - for name, loc in pairs(self.locals) do - local res = callback(name, loc) - if res ~= nil then - return res + local mark = {} + for i = self._top, 1, -1 do + local locals = self.locals[i] + for name, loc in pairs(locals) do + if not mark[name] then + mark[name] = true + local res = callback(name, loc) + if res ~= nil then + return res + end + end + end + end + return nil +end + +function mt:saveLabel(label) + if not self._label then + self._label = {} + end + self._label[#self._label+1] = label +end + +function mt:loadLabel(name) + if not self._label then + return nil + end + for _, label in ipairs(self._label) do + if label:getName() == name then + return label end end return nil @@ -72,36 +107,32 @@ function mt:run() -- func.args[index] = var --end - local stop - self:forList(func.built.arg, function (arg) - if stop then - return - end - index = index + 1 - if arg.type == 'name' then - local var = self:createArg(arg[1], arg) - self:setValue(var, func.argValues[index] or self:createValue('nil')) - func.args[index] = var - elseif arg.type == '...' then - local dots = self:createDots(index, arg) - for i = index, #func.argValues do - dots[#dots+1] = func.argValues[i] - end - func.hasDots = true - stop = true - end - end) -end - -function mt:saveUpvalues(name, loc) - self.upvalues[name] = loc + --local stop + --self:forList(func.built.arg, function (arg) + -- if stop then + -- return + -- end + -- index = index + 1 + -- if arg.type == 'name' then + -- local var = self:createArg(arg[1], arg) + -- self:setValue(var, func.argValues[index] or self:createValue--('nil')) + -- func.args[index] = var + -- elseif arg.type == '...' then + -- local dots = self:createDots(index, arg) + -- for i = index, #func.argValues do + -- dots[#dots+1] = func.argValues[i] + -- end + -- func.hasDots = true + -- stop = true + -- end + --end) end return function (source) local self = setmetatable({ source = source, locals = {}, - upvalues = {}, }, mt) + self:push() return self end diff --git a/server/src/vm/label.lua b/server/src/vm/label.lua new file mode 100644 index 00000000..f8f8eb81 --- /dev/null +++ b/server/src/vm/label.lua @@ -0,0 +1,15 @@ +local mt = {} +mt.__index = mt +mt.type = 'label' + +function mt:getName() + return self.name +end + +return function (name, source) + local self = setmetatable({ + name = name, + source = source, + }, mt) + return self +end diff --git a/server/src/vm/multi.lua b/server/src/vm/multi.lua new file mode 100644 index 00000000..91ab4577 --- /dev/null +++ b/server/src/vm/multi.lua @@ -0,0 +1,46 @@ +local createValue = require 'vm.value' + +local mt = {} +mt.__index = mt +mt.type = 'multi' + +function mt:push(value) + self[#self+1] = value +end + +function mt:first() + local value = self[1] + if not value then + return createValue('nil') + end + if value.type == 'multi' then + return value:first() + else + return value + end +end + +function mt:eachValue(callback) + local i = 0 + for n, value in ipairs(self) do + if value.type == 'multi' then + if n == #self then + value:eachValue(function (_, nvalue) + i = i + 1 + callback(i, nvalue) + end) + else + i = i + 1 + value:first() + end + else + i = i + 1 + callback(i, value) + end + end +end + +return function () + local self = setmetatable({}, mt) + return self +end diff --git a/server/src/vm/source.lua b/server/src/vm/source.lua index b4539ae5..c5bad8bf 100644 --- a/server/src/vm/source.lua +++ b/server/src/vm/source.lua @@ -1,5 +1,6 @@ local mt = {} mt.__index = mt +mt._hasInstant = true function mt:bindLocal(loc) if loc then @@ -9,6 +10,14 @@ function mt:bindLocal(loc) end end +function mt:bindLabel(label) + if label then + self._bindLabel = label + else + return self._bindLabel + end +end + function mt:setUri(uri) self._uri = uri end @@ -18,5 +27,9 @@ function mt:getUri() end return function (source) - return setmetatable(source, mt) + if source._hasInstant then + return false + end + setmetatable(source, mt) + return true end diff --git a/server/src/vm/vm.lua b/server/src/vm/vm.lua index 4c1ce526..73daaac5 100644 --- a/server/src/vm/vm.lua +++ b/server/src/vm/vm.lua @@ -1,9 +1,11 @@ local library = require 'core.library' local createValue = require 'vm.value' local createLocal = require 'vm.local' +local createLabel = require 'vm.label' local createFunction = require 'vm.function' local instantSource = require 'vm.source' local buildGlobal = require 'vm.global' +local createMulti = require 'vm.multi' local mt = {} mt.__index = mt @@ -83,16 +85,12 @@ function mt:createArg(key, source, value) return loc end -function mt:scopePush(block) - if not block.start then - error('Scope push without start!') - end - self.scope:push() - self.scope.block = block +function mt:scopePush() + self.currentFunction:push() end function mt:scopePop() - self.scope:pop() + self.currentFunction:pop() end function mt:addInfo(var, type, source, value) @@ -967,10 +965,20 @@ function mt:getExp(exp) local value = { type = 'list' } self:unpackDots(value) return value + elseif tp == 'list' then + return self:getMultiByList(exp) end error('Unkown exp type: ' .. tostring(tp)) end +function mt:getMultiByList(list) + local multi = createMulti() + for _, exp in ipairs(list) do + multi:push(self:getExp(exp)) + end + return multi +end + function mt:doDo(action) self:scopePush(action) self:doActions(action) @@ -978,64 +986,76 @@ function mt:doDo(action) end function mt:doReturn(action) - self:getCurrentFunction().hasReturn = true - for i, exp in ipairs(action) do - local value = self:getExp(exp) - if value.type == 'list' then - if i == #action then - if #value == 0 then - value[1] = self:createValue('any', exp) - end - for x, v in ipairs(value) do - v:addInfo('return', exp) - self:setFunctionReturn(self:getCurrentFunction(), i + x - 1, v) - end - break - else - local v = value[1] or self:createValue('nil', exp) - v:addInfo('return', exp) - self:setFunctionReturn(self:getCurrentFunction(), i, v) - end - else - value:addInfo('return', exp) - self:setFunctionReturn(self:getCurrentFunction(), i, value) - end + if #action == 0 then + return + end + local value = self:getExp(action[2]) + local func = self:getCurrentFunction() + if value.type == 'multi' then + value:eachValue(function (i, v) + func:setReturn(i, v) + end) + else + func:setReturn(1, value) end end -function mt:createLabel(source) - if source.bind then - return source.bind +function mt:doLabel(source) + local name = source[1] + self:createLabel(name, source) +end + +function mt:createLabel(name, source) + local label = self:bindLabel(source) + if label then + self:saveLabel(label) + return label end + + label = createLabel(name, source) + self:saveLabel(label) + self:bindLabel(source, label) + return label +end + +function mt:doGoTo(source) local name = source[1] - if not self.chunk.labels[name] then - local label = { - type = 'label', - key = name, - } - self.chunk.labels[name] = label - self.results.labels[#self.results.labels+1] = label + local label = self:loadLabel(name) + if not label then + label = self:createLabel(name, source) + end +end + +function mt:setOne(var, value) + if not value then + value = createValue('nil') + end + self:instantSource(var) + if var.type == 'name' then + else end - source.bind = self.chunk.labels[name] - self.results.sources[#self.results.sources+1] = source - return self.chunk.labels[name] end function mt:doSet(action) if not action[2] then return end - local n = self:countList(action[1]) -- 要先计算值 - local values = self:unpackList(action[2], n) - self:forList(action[1], function (key) - local value = table.remove(values, 1) - if key.type == 'name' then - self:setName(key[1], key, value) - elseif key.type == 'simple' then - local field = self:getSimple(key, 'field') - self:setValue(field, value, key[#key]) - end + local vars = action[1] + local exps = action[2] + local value = self:getExp(exps) + local values = {} + if value.type == 'multi' then + value:eachValue(function (i, v) + values[i] = v + end) + else + values[1] = value + end + local i = 0 + self:forList(vars, function (var) + i = i + 1 + self:setOne(var, values[i]) end) end @@ -1160,11 +1180,9 @@ function mt:doAction(action) elseif tp == 'return' then self:doReturn(action) elseif tp == 'label' then - local label = self:createLabel(action) - self:addInfo(label, 'set', action) + self:doLabel(action) elseif tp == 'goto' then - local label = self:createLabel(action) - self:addInfo(label, 'goto', action) + self:doGoTo(action) elseif tp == 'set' then self:doSet(action) elseif tp == 'local' then @@ -1242,12 +1260,21 @@ function mt:eachLocal(callback) return self.currentFunction:eachLocal(callback) end +function mt:saveLabel(label) + self.currentFunction:saveLabel(label) +end + +function mt:loadLabel(name) + return self.currentFunction:loadLocal(name) +end + function mt:getUri() return self.currentFunction:getUri() end function mt:instantSource(source) if instantSource(source) then + source:setUri(self:getUri()) self.sources[#self.sources+1] = source end end @@ -1259,14 +1286,22 @@ function mt:bindLocal(source, loc) self:instantSource(source) if loc then source:bindLocal(loc) - source:setUri(self:getUri()) else return source:bindLocal() end end +function mt:bindLabel(source, label) + self:instantSource(source) + if label then + source:bindLabel(label) + else + return source:bindLabel() + end +end + function mt:createLocal(key, source, value) - local loc = self:bindLocal(source) + local loc = self:bindLocal(source) if loc then self:saveLocal(key, loc) return loc @@ -1296,8 +1331,6 @@ end local function compile(ast, lsp, uri) local vm = setmetatable({ - strings= {}, - sources= {}, funcs = {}, main = nil, env = nil, |