From 54453139868cdef82406b5868a9f78bc0838b6f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Thu, 4 Jul 2019 19:25:37 +0800 Subject: =?UTF-8?q?=E6=9B=B4=E6=96=B0=20meta?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/meta/Lua 5.4/basic.lua | 32 ++++++++++++++++++++++++ server/src/vm/special.lua | 57 ++++++++++++++++++++++++++++++++++++++++--- server/src/vm/vm.lua | 2 +- 3 files changed, 87 insertions(+), 4 deletions(-) diff --git a/server/meta/Lua 5.4/basic.lua b/server/meta/Lua 5.4/basic.lua index 7fa412de..06a5c810 100644 --- a/server/meta/Lua 5.4/basic.lua +++ b/server/meta/Lua 5.4/basic.lua @@ -72,6 +72,19 @@ function load(chunk, chunkname, mode, env) return function (...) end end +--- 从文件中获取代码块。 +---@overload fun():function,string +---@overload fun(filename:string):function,string +---@overload fun(filename:string, mode:loadOption):function,string +---@param filename string {optional = 'after', special = 'loadfile:1'} +---@param mode loadOption {optional = 'after'} +---@param env table {optional = 'self'} +---@return {name = 'init'} +---@return string {name = 'errMessage', optional = 'self'} +function loadfile(filename, mode, env) + return function (...) end +end + --- 返回该键的下一个键及其关联的值。 ---@overload fun(t:table):any, any ---@param t table @@ -102,5 +115,24 @@ function pairs(t) return next, t, nil end +--- 传入参数,以 *保护模式* 调用函数 `f` 。 +---@param f function {special = 'pcall:1'} +---@param arg1 any {optional = 'after'} +---@return boolean {name = 'success'} +---@return {name = 'result'} +function pcall(f, arg1, ...) +end + +--- 接收任意数量的参数,并将它们的值打印到 `stdout`。 +function print(...) +end + +--- 在不触发任何元方法的情况下 检查 `v1` 是否和 `v2` 相等。 +---@param v1 any +---@param v2 any +---@return boolean +function rawequal(v1, v2) +end + --- 当前解释器版本号。 _VERSION = 'Lua 5.4' diff --git a/server/src/vm/special.lua b/server/src/vm/special.lua index b22ed06d..f8a03a34 100644 --- a/server/src/vm/special.lua +++ b/server/src/vm/special.lua @@ -1,13 +1,14 @@ local mt = require 'vm.manager' +local multi = require 'vm.multi' ---@param func emmyFunction ---@param values table -function mt:callEmmySpecial(func, values) +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) + self:checkEmmyParam(func, values, index, option.special, source) end end end @@ -16,9 +17,13 @@ end ---@param values table ---@param index integer ---@param special string -function mt:checkEmmyParam(func, values, index, special) +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) end end @@ -40,3 +45,49 @@ function mt:callEmmyDoFile(func, values, index) 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(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 +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 diff --git a/server/src/vm/vm.lua b/server/src/vm/vm.lua index bafd5841..d41d17bb 100644 --- a/server/src/vm/vm.lua +++ b/server/src/vm/vm.lua @@ -346,7 +346,7 @@ function mt:call(value, values, source) func:mergeReturn(1, self:createValue('any', source)) end if func:getEmmyParams() then - self:callEmmySpecial(func, values) + self:callEmmySpecial(func, values, source) end end -- cgit v1.2.3