summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-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
-rw-r--r--server/test/full/dirty.lua (renamed from server/test/vm/dirty.lua)0
-rw-r--r--server/test/full/example.lua (renamed from server/test/vm/example.lua)2
-rw-r--r--server/test/full/init.lua15
-rw-r--r--server/test/full/normal.lua (renamed from server/test/vm/normal.lua)0
-rw-r--r--server/test/main.lua2
-rw-r--r--server/test/vm/init.lua17
12 files changed, 138 insertions, 90 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)
-- 检查所有没有调用过的函数,调用一遍
diff --git a/server/test/vm/dirty.lua b/server/test/full/dirty.lua
index 9c2e65fb..9c2e65fb 100644
--- a/server/test/vm/dirty.lua
+++ b/server/test/full/dirty.lua
diff --git a/server/test/vm/example.lua b/server/test/full/example.lua
index 9a2939b5..321f3bc7 100644
--- a/server/test/vm/example.lua
+++ b/server/test/full/example.lua
@@ -1,6 +1,6 @@
local fs = require 'bee.filesystem'
-TEST(io.load(ROOT / 'src' / 'core' / 'vm.lua'))
+TEST(io.load(ROOT / 'src' / 'vm' / 'vm.lua'))
-- 临时
local function testIfExit(path)
diff --git a/server/test/full/init.lua b/server/test/full/init.lua
new file mode 100644
index 00000000..f3a7402d
--- /dev/null
+++ b/server/test/full/init.lua
@@ -0,0 +1,15 @@
+local buildVM = require 'vm'
+local parser = require 'parser'
+
+rawset(_G, 'TEST', true)
+
+function TEST(script)
+ local ast = parser:ast(script)
+ assert(ast)
+ local vm = buildVM(ast)
+ assert(vm)
+end
+
+require 'full.normal'
+require 'full.example'
+require 'full.dirty'
diff --git a/server/test/vm/normal.lua b/server/test/full/normal.lua
index 02b1f4f0..02b1f4f0 100644
--- a/server/test/vm/normal.lua
+++ b/server/test/full/normal.lua
diff --git a/server/test/main.lua b/server/test/main.lua
index 8738002c..7a498929 100644
--- a/server/test/main.lua
+++ b/server/test/main.lua
@@ -25,7 +25,7 @@ local function main()
end
test 'core'
- test 'vm'
+ test 'full'
test 'definition'
test 'diagnostics'
test 'type_inference'
diff --git a/server/test/vm/init.lua b/server/test/vm/init.lua
deleted file mode 100644
index 6e7dc3ac..00000000
--- a/server/test/vm/init.lua
+++ /dev/null
@@ -1,17 +0,0 @@
-local core = require 'core'
-local parser = require 'parser'
-
-rawset(_G, 'TEST', true)
-
-function TEST(script)
- local ast = parser:ast(script)
- assert(ast)
- local vm = core.vm(ast)
- assert(vm)
- local results = vm.results
- assert(results)
-end
-
-require 'vm.normal'
-require 'vm.example'
-require 'vm.dirty'