summaryrefslogtreecommitdiff
path: root/server/src/vm
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/vm')
-rw-r--r--server/src/vm/emmy.lua40
-rw-r--r--server/src/vm/function.lua23
-rw-r--r--server/src/vm/special.lua42
-rw-r--r--server/src/vm/vm.lua5
4 files changed, 89 insertions, 21 deletions
diff --git a/server/src/vm/emmy.lua b/server/src/vm/emmy.lua
index 3ad0a472..5a15d3b0 100644
--- a/server/src/vm/emmy.lua
+++ b/server/src/vm/emmy.lua
@@ -196,7 +196,7 @@ function mt:doEmmyReturn(action)
---@type emmyMgr
local emmyMgr = self.emmyMgr
self:instantSource(action)
- local type = self:getGenericByType(action[1]) or self:buildEmmyAnyType(action[1])
+ local type = action[1] and (self:getGenericByType(action[1]) or self:buildEmmyAnyType(action[1]))
local rtn = emmyMgr:addReturn(action, type)
action:set('emmy.return', rtn)
self:addEmmyReturn(rtn)
@@ -299,23 +299,29 @@ function mt:buildEmmyFunctionType(source)
local funcObj = emmyMgr:addFunctionType(source)
---@type emmyFunction
local func = functionMgr.create(source)
- for i = 1, #source // 2 do
- local nameSource = source[i*2-1]
- local typeSource = source[i*2]
- local paramType = self:buildEmmyAnyType(typeSource)
- funcObj:addParam(nameSource[1], paramType)
- local value = self:createValue(paramType:getType(), typeSource)
- value:setEmmy(paramType)
- self:instantSource(nameSource)
- func:addArg(nameSource[1], nameSource, value)
+ local args = source.args
+ if args then
+ for i = 1, #args // 2 do
+ local nameSource = args[i*2-1]
+ local typeSource = args[i*2]
+ local paramType = self:buildEmmyAnyType(typeSource)
+ funcObj:addParam(nameSource[1], paramType)
+ local value = self:createValue(paramType:getType(), typeSource)
+ value:setEmmy(paramType)
+ self:instantSource(nameSource)
+ func:addArg(nameSource[1], nameSource, value)
+ end
end
- local returnSource = source[#source]
- if returnSource then
- local returnType = self:buildEmmyAnyType(returnSource)
- funcObj:addReturn(returnType)
- local value = self:createValue(returnType:getType(), returnSource)
- value:setEmmy(returnType)
- func:setReturn(1, value)
+ local returns = source.returns
+ if returns then
+ for i = 1, #returns do
+ local returnSource = returns[i]
+ local returnType = self:buildEmmyAnyType(returnSource)
+ funcObj:addReturn(returnType)
+ local value = self:createValue(returnType:getType(), returnSource)
+ value:setEmmy(returnType)
+ func:setReturn(i, value)
+ end
end
funcObj:bindFunction(func)
return funcObj
diff --git a/server/src/vm/function.lua b/server/src/vm/function.lua
index 8f7ac6c2..b6772cd1 100644
--- a/server/src/vm/function.lua
+++ b/server/src/vm/function.lua
@@ -162,8 +162,11 @@ function mt:rawSetReturn(index, value)
end
function mt:setReturn(index, value)
- if self._emmyReturns then
- return
+ local emmy = self._emmyReturns and self._emmyReturns[index]
+ if emmy then
+ if emmy:bindType() or emmy:bindGeneric() then
+ return
+ end
end
return self:rawSetReturn(index, value)
end
@@ -172,8 +175,11 @@ function mt:mergeReturn(index, value)
if self._removed then
return
end
- if self._emmyReturns then
- return
+ local emmy = self._emmyReturns and self._emmyReturns[index]
+ if emmy then
+ if emmy:bindType() or emmy:bindGeneric() then
+ return
+ end
end
self:set('hasReturn', true)
if not self.returns then
@@ -339,6 +345,15 @@ function mt:run(vm)
end
end
+function mt:eachEmmyReturn(callback)
+ if not self._emmyReturns then
+ return
+ end
+ for _, rtn in ipairs(self._emmyReturns) do
+ callback(rtn)
+ end
+end
+
function mt:setArgs(values)
for i = 1, #self.argValues do
self.argValues[i] = nil
diff --git a/server/src/vm/special.lua b/server/src/vm/special.lua
new file mode 100644
index 00000000..b22ed06d
--- /dev/null
+++ b/server/src/vm/special.lua
@@ -0,0 +1,42 @@
+local mt = require 'vm.manager'
+
+---@param func emmyFunction
+---@param values table
+function mt:callEmmySpecial(func, values)
+ local emmyParams = func:getEmmyParams()
+ for index, param in ipairs(emmyParams) do
+ local option = param:getOption()
+ if option and type(option.special) == 'string' then
+ self:checkEmmyParam(func, values, index, option.special)
+ end
+ end
+end
+
+---@param func emmyFunction
+---@param values table
+---@param index integer
+---@param special string
+function mt:checkEmmyParam(func, values, index, special)
+ if special == 'dofile:1' then
+ self:callEmmyDoFile(func, values, index)
+ end
+end
+
+---@param func emmyFunction
+---@param values table
+---@param index integer
+function mt:callEmmyDoFile(func, values, index)
+ if not values[index] then
+ values[index] = self:createValue('any', self:getDefaultSource())
+ end
+ local str = values[index]:getLiteral()
+ if type(str) ~= 'string' then
+ return
+ end
+ local requireValue = self:tryRequireOne(values[index], 'dofile')
+ if not requireValue then
+ requireValue = self:createValue('any', self:getDefaultSource())
+ requireValue.isRequire = true
+ end
+ func:setReturn(1, requireValue)
+end
diff --git a/server/src/vm/vm.lua b/server/src/vm/vm.lua
index f0e30537..bafd5841 100644
--- a/server/src/vm/vm.lua
+++ b/server/src/vm/vm.lua
@@ -16,6 +16,7 @@ require 'vm.raw'
require 'vm.pcall'
require 'vm.ipairs'
require 'vm.emmy'
+require 'vm.special'
-- TODO source测试
--rawset(_G, 'CachedSource', setmetatable({}, { __mode = 'kv' }))
@@ -325,6 +326,7 @@ end
function mt:call(value, values, source)
local lib = value:getLib()
+ ---@type emmyFunction
local func = value:getFunction()
value:setType('function', 0.5)
if not func then
@@ -343,6 +345,9 @@ function mt:call(value, values, source)
else
func:mergeReturn(1, self:createValue('any', source))
end
+ if func:getEmmyParams() then
+ self:callEmmySpecial(func, values)
+ end
end
return func:getReturn()