summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--server/src/core/vm.lua140
1 files changed, 70 insertions, 70 deletions
diff --git a/server/src/core/vm.lua b/server/src/core/vm.lua
index 61314add..219c5be1 100644
--- a/server/src/core/vm.lua
+++ b/server/src/core/vm.lua
@@ -359,55 +359,88 @@ function mt:isGlobal(field)
end
end
-function mt:buildFunction(exp, object)
- local func = self:createValue('function', exp)
- func.args = {}
- func.argValues = {}
-
- if not exp then
- return func
+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
- func.built = true
-
- self:scopePush(exp)
+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
- if object then
- local var = self:createArg('self', object.source, self:getValue(object))
+ 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.object.source, self:getValue(func.object))
var.hide = true
- func.args[1] = var
+ self:setValue(var, func.argValues[1] or self:createValue('nil'))
+ index = 1
+ func.args[index] = var
end
local stop
- self:forList(exp.arg, function (arg)
+ 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)
arg.isArg = true
- func.args[#func.args+1] = var
- func.argValues[#func.args] = self:getValue(var)
+ self:setValue(var, func.argValues[index] or self:createValue('nil'))
+ func.args[index] = var
elseif arg.type == '...' then
- self:createDots(#func.args+1, arg)
- func.hasDots = true
- for _ = 1, 10 do
- func.argValues[#func.argValues+1] = self:createValue('any', arg)
+ 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)
- self:doActions(exp)
-
- self.results.funcs[#self.results.funcs+1] = func
+ self:doActions(func.built)
self.chunk:pop()
self:scopePop()
+end
+
+function mt:buildFunction(exp, object)
+ if exp and exp.func then
+ return exp.func
+ end
+
+ local func = self:createValue('function', exp)
+ func.args = {}
+ func.argValues = {}
+
+ if not exp then
+ return func
+ end
+
+ func.built = exp
+ func.upvalues = {}
+ func.object = object
+ exp.func = func
+ for name, loc in pairs(self.scope.locals) do
+ func.upvalues[name] = loc
+ end
+
+ self.results.funcs[#self.results.funcs+1] = func
return func
end
@@ -435,31 +468,6 @@ function mt:countList(list)
return 1
end
-function mt:updateFunctionArgs(func)
- if not func.argValues then
- return
- end
- if not func.args then
- return
- end
-
- local values = func.argValues
- for i, var in ipairs(func.args) do
- if var.type == 'dots' then
- local list = {
- type = 'list',
- }
- for n = i, #values do
- list[n-i+1] = values[n]
- end
- self:setValue(var, list)
- break
- else
- self:setValue(var, values[i])
- end
- end
-end
-
function mt:setFunctionArg(func, values)
if func.uri ~= self.uri then
return
@@ -468,25 +476,14 @@ function mt:setFunctionArg(func, values)
func.argValues = {}
end
for i = 1, #values do
- if not func.argValues[i] then
- func.argValues[i] = values[i]
- end
- values[i]:inference(func.argValues[i]:getType())
- func.argValues[i]:inference(values[i]:getType())
+ func.argValues[i] = values[i]
end
-
- self:updateFunctionArgs(func)
end
function mt:getFunctionArg(func, i)
if not func.argValues then
func.argValues = {}
end
- if not func.argValues[i] then
- for n = #func.argValues+1, i do
- func.argValues[n] = self:createValue('any')
- end
- end
return func.argValues[i]
end
@@ -633,17 +630,13 @@ function mt:callDoFile(func, values)
self:setFunctionReturn(func, 1, requireValue)
end
-function mt:call(func, values)
+function mt:call(func, values, source)
func:inference('function')
local lib = func.lib
if lib then
if lib.args then
for i, arg in ipairs(lib.args) do
- if arg.type == '...' then
- self:getFunctionArg(func, i):inference('any')
- else
- self:getFunctionArg(func, i):inference(arg.type or 'any')
- end
+ -- TODO 反向推测调用参数的类型
end
end
if lib.returns then
@@ -668,7 +661,11 @@ function mt:call(func, values)
end
end
- self:setFunctionArg(func, values)
+ if not source.hasRuned and func.built then
+ source.hasRuned = true
+ self:setFunctionArg(func, values)
+ self:runFunction(func)
+ end
return self:getFunctionReturns(func)
end
@@ -786,7 +783,7 @@ function mt:getLibValue(lib, parentType, v)
for i, arg in ipairs(lib.args) do
values[i] = self:getLibValue(arg, parentType) or self:createValue('any')
end
- self:setFunctionArg(value, values)
+ -- TODO 确定参数类型
end
elseif tp == 'string' then
value = self:createValue('string', nil, v or lib.value)
@@ -933,7 +930,7 @@ function mt:getSimple(simple, mode)
end
local func = value
-- 函数的返回值一定是list
- value = self:call(func, args)
+ value = self:call(func, args, obj)
if i < #simple then
value = value[1] or self:createValue('any')
end
@@ -1303,7 +1300,7 @@ function mt:doIn(action)
self:scopePush(action)
local func = table.remove(args, 1) or self:createValue('any')
- local values = self:call(func, args)
+ local values = self:call(func, args, action)
self:forList(action.arg, function (arg)
local value = table.remove(values, 1)
self:createLocal(arg[1], arg, value)
@@ -1487,6 +1484,9 @@ local function compile(ast, lsp, uri)
-- 执行代码
vm:doActions(ast)
+ -- 检查所有没有调用过的函数,调用一遍
+ vm:callLeftFuncions()
+
vm.scope = nil
vm.chunk = nil