diff options
Diffstat (limited to 'script/vm/special.lua')
-rw-r--r-- | script/vm/special.lua | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/script/vm/special.lua b/script/vm/special.lua new file mode 100644 index 00000000..e93c4445 --- /dev/null +++ b/script/vm/special.lua @@ -0,0 +1,130 @@ +local mt = require 'vm.manager' +local multi = require 'vm.multi' +local library = require 'core.library' +local libraryBuilder = require 'vm.library' +local plugin = require 'plugin' + +---@param func emmyFunction +---@param values table +function mt:callEmmySpecial(func, values, source) + 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, source) + end + end +end + +---@param func emmyFunction +---@param values table +---@param index integer +---@param special string +function mt:checkEmmyParam(func, values, index, special, source) + if special == 'dofile:1' then + self:callEmmyDoFile(func, values, index) + elseif special == 'loadfile:1' then + self:callEmmyLoadFile(func, values, index) + elseif special == 'pcall:1' then + self:callEmmyPCall(func, values, index, source) + elseif special == 'require:1' then + self:callEmmyRequire(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(str, values[index], 'dofile') + if not requireValue then + requireValue = self:createValue('any', self:getDefaultSource()) + requireValue.isRequire = true + end + func:setReturn(1, requireValue) +end + +---@param func emmyFunction +---@param values table +---@param index integer +function mt:callEmmyLoadFile(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(str, values[index], 'loadfile') + if not requireValue then + requireValue = self:createValue('any', self:getDefaultSource()) + requireValue:set('cross file', true) + end + func:setReturn(1, requireValue) +end + +---@param func emmyFunction +---@param values table +---@param index integer +---@param source source +function mt:callEmmyPCall(func, values, index, source) + local funcValue = values[index] + if not funcValue then + return + end + local realFunc = funcValue:getFunction() + if not realFunc then + return + end + local argList = multi() + values:eachValue(function (i, v) + if i > index then + argList:push(v) + end + end) + self:call(funcValue, argList, source) + if realFunc ~= func then + func:setReturn(1, self:createValue('boolean', source)) + realFunc:getReturn():eachValue(function (i, v) + func:setReturn(i + 1, v) + end) + end +end + +---@param func emmyFunction +---@param values table +---@param index integer +function mt:callEmmyRequire(func, values, index) + if not values[index] then + values[index] = self:createValue('any', self:getDefaultSource()) + end + local strValue = values[index] + local strSource = strValue:getSource() + if not strSource then + return nil + end + local str = strValue:getLiteral() + local raw = self.text:sub(strSource.start, strSource.finish) + str = plugin.call('OnRequirePath', str, raw) or str + local lib = library.library[str] + if lib then + local value = libraryBuilder.value(lib) + value:markGlobal() + func:setReturn(1, value) + return + else + local requireValue = self:tryRequireOne(str, strValue, 'require') + if not requireValue then + requireValue = self:createValue('any', self:getDefaultSource()) + requireValue:set('cross file', true) + end + func:setReturn(1, requireValue) + end +end |