summaryrefslogtreecommitdiff
path: root/server/src/vm
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2019-01-31 18:11:10 +0800
committer最萌小汐 <sumneko@hotmail.com>2019-01-31 18:11:10 +0800
commit076aca36bab28e805a85ee2e6a8f347a9ea83ba7 (patch)
treee4b226855365c6812b7b1c97dfe8d16decd9cf5d /server/src/vm
parent92424baf13c2487145456e4062f9f4214f8b7bcd (diff)
downloadlua-language-server-076aca36bab28e805a85ee2e6a8f347a9ea83ba7.zip
整理代码
Diffstat (limited to 'server/src/vm')
-rw-r--r--server/src/vm/function.lua103
-rw-r--r--server/src/vm/label.lua15
-rw-r--r--server/src/vm/multi.lua46
-rw-r--r--server/src/vm/source.lua15
-rw-r--r--server/src/vm/vm.lua153
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,