diff options
Diffstat (limited to 'server/src/vm')
-rw-r--r-- | server/src/vm/emmy.lua | 40 | ||||
-rw-r--r-- | server/src/vm/function.lua | 23 | ||||
-rw-r--r-- | server/src/vm/special.lua | 42 | ||||
-rw-r--r-- | server/src/vm/vm.lua | 5 |
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() |