summaryrefslogtreecommitdiff
path: root/server/src/vm
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/vm')
-rw-r--r--server/src/vm/dots.lua2
-rw-r--r--server/src/vm/function.lua87
-rw-r--r--server/src/vm/library.lua6
-rw-r--r--server/src/vm/source.lua4
-rw-r--r--server/src/vm/value.lua4
-rw-r--r--server/src/vm/vm.lua89
6 files changed, 121 insertions, 71 deletions
diff --git a/server/src/vm/dots.lua b/server/src/vm/dots.lua
index 1736de5c..db8e134e 100644
--- a/server/src/vm/dots.lua
+++ b/server/src/vm/dots.lua
@@ -3,4 +3,6 @@ mt.__index = mt
mt.type = 'dots'
return function ()
+ local self = setmetatable({}, mt)
+ return self
end
diff --git a/server/src/vm/function.lua b/server/src/vm/function.lua
index 25465398..90f975ae 100644
--- a/server/src/vm/function.lua
+++ b/server/src/vm/function.lua
@@ -4,7 +4,7 @@ local createDots = require 'vm.dots'
local mt = {}
mt.__index = mt
mt.type = 'function'
-mt._returnDots = false
+mt._runed = 0
function mt:getUri()
return self.source.uri
@@ -14,23 +14,94 @@ function mt:saveLocal(name, loc)
self.locals[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
+ 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
+ end
+ end
+ return nil
+end
+
function mt:setReturn(index, value)
+ if not self.returns then
+ self.returns = {}
+ end
self.returns[index] = value
end
-function mt:returnDots(index, value)
- self.returns[index] = value
- self._returnDots = true
+function mt:returnDots(index)
+ if not self.returns then
+ self.returns = {}
+ end
+ self.returns[index] = createDots()
end
-return function (source)
- if not source then
- error('Function must has a source')
+function mt:hasRuned()
+ return self._runed > 0
+end
+
+function mt:run()
+ self._runed = self._runed + 1
+ if not self.source then
+ return
end
+
+ --local index = 0
+ --if func.object then
+ -- local var = self:createArg('self', func.colon, self:getValue--(func.object, func.colon))
+ -- var.hide = true
+ -- var.link = func.object
+ -- if func.argValues[1] then
+ -- self:setValue(var, func.argValues[1])
+ -- end
+ -- index = 1
+ -- 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
+end
+
+return function (source)
local self = setmetatable({
source = source,
locals = {},
- returns = {},
+ upvalues = {},
}, mt)
return self
end
diff --git a/server/src/vm/library.lua b/server/src/vm/library.lua
index a6b9629e..bf18d177 100644
--- a/server/src/vm/library.lua
+++ b/server/src/vm/library.lua
@@ -19,12 +19,12 @@ function buildLibValue(lib)
value = createValue('table')
elseif tp == 'function' then
value = createValue('function')
- local func = createFunction(getDefaultSource())
+ local func = createFunction()
value:setFunction(func)
if lib.returns then
for i, rtn in ipairs(lib.returns) do
if rtn.type == '...' then
- func:returnDots(i, buildLibValue(rtn))
+ func:returnDots(i)
else
func:setReturn(i, buildLibValue(rtn))
end
@@ -40,8 +40,6 @@ function buildLibValue(lib)
value = createValue('integer')
elseif tp == 'nil' then
value = createValue('nil')
- elseif tp == '...' then
- value = createValue('any')
else
value = createValue(tp or 'any')
end
diff --git a/server/src/vm/source.lua b/server/src/vm/source.lua
index 5ec602c6..b4539ae5 100644
--- a/server/src/vm/source.lua
+++ b/server/src/vm/source.lua
@@ -13,6 +13,10 @@ function mt:setUri(uri)
self._uri = uri
end
+function mt:getUri()
+ return self._uri
+end
+
return function (source)
return setmetatable(source, mt)
end
diff --git a/server/src/vm/value.lua b/server/src/vm/value.lua
index 21dd4307..f8824db6 100644
--- a/server/src/vm/value.lua
+++ b/server/src/vm/value.lua
@@ -205,6 +205,10 @@ function mt:setFunction(func)
self:setType('function', 1.0)
end
+function mt:getFunction()
+ return self._func
+end
+
function mt:setLib(lib)
self._lib = lib
end
diff --git a/server/src/vm/vm.lua b/server/src/vm/vm.lua
index 48d7e038..4c1ce526 100644
--- a/server/src/vm/vm.lua
+++ b/server/src/vm/vm.lua
@@ -227,67 +227,18 @@ function mt:isGlobal(field)
return field.GLOBAL == true
end
-function mt:callLeftFuncions()
- for _, func in ipairs(self.results.funcs) do
- if func.built and not func.runed then
- self:runFunction(func)
- end
- end
-end
-
function mt:runFunction(func)
- func.runed = (func.runed or 0) + 1
- if func.runed > 1 then
- --return
- end
- self:scopePush(func.built)
- self.chunk:push()
- self.chunk:cut 'dots'
- self.chunk:cut 'labels'
- self.chunk:cut 'locals'
- self.chunk.func = func
-
- self.scope:cut 'locals'
- for name, loc in pairs(func.upvalues) do
- self.scope.locals[name] = loc
- end
-
- local index = 0
- if func.object then
- local var = self:createArg('self', func.colon, self:getValue(func.object, func.colon))
- var.hide = true
- var.link = func.object
- if func.argValues[1] then
- self:setValue(var, func.argValues[1])
- end
- index = 1
- func.args[index] = var
+ func:run()
+
+ if not func.source then
+ return
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)
+ local originFunction = self:getCurrentFunction()
- self:doActions(func.built)
+ self:doActions(func.source)
- self.chunk:pop()
- self:scopePop()
+ self:setCurrentFunction(originFunction)
end
function mt:buildFunction(exp, object, colon)
@@ -1202,7 +1153,6 @@ function mt:doAction(action)
-- Skip
return
end
- action.uri = self.chunk.func.uri
local tp = action.type
if tp == 'do' then
self:doDo(action)
@@ -1264,14 +1214,34 @@ function mt:createFunction(source)
return value
end
-function mt:setCurrentFunction(func)
- self.currentFunction = func
+function mt:callLeftFuncions()
+ for _, func in ipairs(self.funcs) do
+ if not func:hasRuned() then
+ self:runFunction(func)
+ end
+ end
+end
+
+function mt:setCurrentFunction(value)
+ self.currentFunction = value:getFunction()
+end
+
+function mt:getCurrentFunction()
+ return self.currentFunction
end
function mt:saveLocal(name, loc)
self.currentFunction:saveLocal(name, loc)
end
+function mt:loadLocal(name)
+ return self.currentFunction:loadLocal(name)
+end
+
+function mt:eachLocal(callback)
+ return self.currentFunction:eachLocal(callback)
+end
+
function mt:getUri()
return self.currentFunction:getUri()
end
@@ -1337,6 +1307,7 @@ local function compile(ast, lsp, uri)
-- 创建初始环境
ast.uri = vm.uri
+ vm:instantSource(ast)
vm:createEnvironment(ast)
-- 检查所有没有调用过的函数,调用一遍