diff options
author | bfredl <bjorn.linse@gmail.com> | 2023-09-09 23:45:06 +0200 |
---|---|---|
committer | bfredl <bjorn.linse@gmail.com> | 2023-09-10 11:43:37 +0200 |
commit | 25e51d393a420765d5efd44c1b4be823a5cf280a (patch) | |
tree | b416b81858c9840fc14db7a79147cb9569bdd741 /runtime/lua/coxpcall.lua | |
parent | 87db6d894ad252edf69cd3382704c60d3115b51e (diff) | |
download | rneovim-25e51d393a420765d5efd44c1b4be823a5cf280a.tar.gz rneovim-25e51d393a420765d5efd44c1b4be823a5cf280a.tar.bz2 rneovim-25e51d393a420765d5efd44c1b4be823a5cf280a.zip |
build(lua): vendor coxpcall
Do not require luarocks on PUC lua CI just because of this single lua file
Diffstat (limited to 'runtime/lua/coxpcall.lua')
-rw-r--r-- | runtime/lua/coxpcall.lua | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/runtime/lua/coxpcall.lua b/runtime/lua/coxpcall.lua new file mode 100644 index 0000000000..6b179f1ef0 --- /dev/null +++ b/runtime/lua/coxpcall.lua @@ -0,0 +1,108 @@ +------------------------------------------------------------------------------- +-- Coroutine safe xpcall and pcall versions +-- +-- Encapsulates the protected calls with a coroutine based loop, so errors can +-- be dealed without the usual Lua 5.x pcall/xpcall issues with coroutines +-- yielding inside the call to pcall or xpcall. +-- +-- Authors: Roberto Ierusalimschy and Andre Carregal +-- Contributors: Thomas Harning Jr., Ignacio BurgueƱo, Fabio Mascarenhas +-- +-- Copyright 2005 - Kepler Project +-- +-- $Id: coxpcall.lua,v 1.13 2008/05/19 19:20:02 mascarenhas Exp $ +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- Checks if (x)pcall function is coroutine safe +------------------------------------------------------------------------------- +local function isCoroutineSafe(func) + local co = coroutine.create(function() + return func(coroutine.yield, function() end) + end) + + coroutine.resume(co) + return coroutine.resume(co) +end + +-- No need to do anything if pcall and xpcall are already safe. +if isCoroutineSafe(pcall) and isCoroutineSafe(xpcall) then + copcall = pcall + coxpcall = xpcall + return { pcall = pcall, xpcall = xpcall, running = coroutine.running } +end + +------------------------------------------------------------------------------- +-- Implements xpcall with coroutines +------------------------------------------------------------------------------- +local performResume, handleReturnValue +local oldpcall, oldxpcall = pcall, xpcall +local pack = table.pack or function(...) return {n = select("#", ...), ...} end +local unpack = table.unpack or unpack +local running = coroutine.running +local coromap = setmetatable({}, { __mode = "k" }) + +function handleReturnValue(err, co, status, ...) + if not status then + return false, err(debug.traceback(co, (...)), ...) + end + if coroutine.status(co) == 'suspended' then + return performResume(err, co, coroutine.yield(...)) + else + return true, ... + end +end + +function performResume(err, co, ...) + return handleReturnValue(err, co, coroutine.resume(co, ...)) +end + +local function id(trace, ...) + return trace +end + +function coxpcall(f, err, ...) + local current = running() + if not current then + if err == id then + return oldpcall(f, ...) + else + if select("#", ...) > 0 then + local oldf, params = f, pack(...) + f = function() return oldf(unpack(params, 1, params.n)) end + end + return oldxpcall(f, err) + end + else + local res, co = oldpcall(coroutine.create, f) + if not res then + local newf = function(...) return f(...) end + co = coroutine.create(newf) + end + coromap[co] = current + return performResume(err, co, ...) + end +end + +local function corunning(coro) + if coro ~= nil then + assert(type(coro)=="thread", "Bad argument; expected thread, got: "..type(coro)) + else + coro = running() + end + while coromap[coro] do + coro = coromap[coro] + end + if coro == "mainthread" then return nil end + return coro +end + +------------------------------------------------------------------------------- +-- Implements pcall with coroutines +------------------------------------------------------------------------------- + +function copcall(f, ...) + return coxpcall(f, id, ...) +end + +return { pcall = copcall, xpcall = coxpcall, running = corunning } |