summaryrefslogtreecommitdiff
path: root/script/vm/special.lua
diff options
context:
space:
mode:
Diffstat (limited to 'script/vm/special.lua')
-rw-r--r--script/vm/special.lua130
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