diff options
-rw-r--r-- | server/libs/@lua/basic.lni | 3 | ||||
-rw-r--r-- | server/src/vm/pcall.lua | 50 | ||||
-rw-r--r-- | server/src/vm/vm.lua | 5 | ||||
-rw-r--r-- | server/test/hover/init.lua | 40 |
4 files changed, 98 insertions, 0 deletions
diff --git a/server/libs/@lua/basic.lni b/server/libs/@lua/basic.lni index 85d5d6da..333e44cd 100644 --- a/server/libs/@lua/basic.lni +++ b/server/libs/@lua/basic.lni @@ -346,6 +346,7 @@ type = 'table' type = 'nil' [pcall] +special = pcall [[.args]] name = 'f' type = 'function' @@ -522,6 +523,7 @@ type = 'boolean' optional = 'after' [xpcall] +special = xpcall [[.args]] name = 'f' type = 'function' @@ -544,6 +546,7 @@ type = '...' ['xpcall Lua 5.1'] name = 'xpcall' version = 'Lua 5.1' +special = xpcall [[.args]] name = 'f' type = 'function' diff --git a/server/src/vm/pcall.lua b/server/src/vm/pcall.lua new file mode 100644 index 00000000..e5d1e26f --- /dev/null +++ b/server/src/vm/pcall.lua @@ -0,0 +1,50 @@ +local mt = require 'vm.manager' +local multi = require 'vm.multi' + +function mt:callPcall(func, values, source) + local funcValue = values:first() + 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 >= 2 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 + +function mt:callXpcall(func, values, source) + local funcValue = values:first() + 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 >= 3 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 aafe7a10..5091a1bc 100644 --- a/server/src/vm/vm.lua +++ b/server/src/vm/vm.lua @@ -12,6 +12,7 @@ local mt = require 'vm.manager' require 'vm.module' require 'vm.raw' +require 'vm.pcall' -- TODO source测试 --rawset(_G, 'CachedSource', setmetatable({}, { __mode = 'kv' })) @@ -282,6 +283,10 @@ function mt:callLibrary(func, values, source, lib) self:callRawSet(func, values, source) elseif lib.special == 'rawget' then self:callRawGet(func, values, source) + elseif lib.special == 'pcall' then + self:callPcall(func, values, source) + elseif lib.special == 'xpcall' then + self:callXpcall(func, values, source) end else -- 如果lib的参数中有function,则立即执行function diff --git a/server/test/hover/init.lua b/server/test/hover/init.lua index b144fd72..3d82777d 100644 --- a/server/test/hover/init.lua +++ b/server/test/hover/init.lua @@ -401,3 +401,43 @@ local sssss<utf8>: { offset: function, } ]] + +TEST[[ +function a(v) + print(<?v?>) +end +a(1) +]] +[[ +local v: number = 1 +]] + +TEST[[ +function a(v) + print(<?v?>) +end +pcall(a, 1) +]] +[[ +local v: number = 1 +]] + +TEST[[ +function a(v) + print(<?v?>) +end +xpcall(a, log.error, 1) +]] +[[ +local v: number = 1 +]] + +TEST[[ +function a(v) + return 'a' +end +local _, <?r?> = pcall(a, 1) +]] +[[ +local r: string = "a" +]] |