Warning: this is an htmlized version!
The original is here, and
the conversion rules are here.
-- This file:
--   http://anggtwu.net/LUA/PCall1.lua.html
--   http://anggtwu.net/LUA/PCall1.lua
--          (find-angg "LUA/PCall1.lua")
-- Author: Eduardo Ochs <eduardoochs@gmail.com>
--
-- (defun xp () (interactive) (find-angg "LUA/XPCall1.lua"))
-- (defun pc () (interactive) (find-angg "LUA/PCall1.lua"))
--
-- This is a simpler, and older, version of:
--   (find-angg "LUA/XPCall2.lua")
-- This file doesn't have any dependencies, except for pack and unpack:
--   (find-angg "LUA/lua50init.lua" "pack-and-unpack")
-- Used by:
--   (find-angg "LUA/Globals1.lua" "Globals")
--   (find-angg "LUA/Globals1.lua" "Globals" "run =")
-- Supersedes:
--   (find-angg "LUA/lua50init.lua" "MyXpcall")
--   (find-angg "LUA/myxpcall.lua" "MyXpcall")
--   (find-angg "edrxrepl/edrxpcall.lua")
--   (find-angg "emacs-lua/EdrxPcall.lua")
--   (find-angg "emacs-lua/EdrxPcall.lua" "EdrxPcall")
--   (find-es "lua5" "xpcall-2020")
--   (find-es "fennel" "traceback")
-- See:
--   https://en.wikipedia.org/wiki/Exception_handling
--   Rationale behind unwind-protect and double errors:
--     https://groups.google.com/g/comp.lang.lisp/c/OWg7boIvyM8?pli=1
--   (find-elnode "Catch and Throw")
--   (find-elnode "Cleanups")
--   (find-clnode "Blocks and Exits")
--   http://lua-users.org/wiki/FinalizedExceptions
--
-- «.PCall»		(to "PCall")
-- «.PCall-tests»	(to "PCall-tests")


--  ____   ____      _ _ 
-- |  _ \ / ___|__ _| | |
-- | |_) | |   / _` | | |
-- |  __/| |__| (_| | | |
-- |_|    \____\__,_|_|_|
--                       
-- «PCall»  (to ".PCall")

PCall = Class {
  type    = "PCall",
  __index = {
    --
    -- :mayrun(o) is a utility function that runs o if o is non-nil.
    mayrun = function (pc, o)
        if type(o) == "function" then o(pc);     return pc end
        if type(o) == "string"   then pc[o](pc); return pc end
        return pc
      end,
    --
    -- :a() runs some preparations (in pc.before),
    -- :b() runs the body of the protected call (in pc.f),
    -- :c() runs some cleanups (in pc.after).
    a = function (pc) return pc:mayrun(pc.before) end,
    b = function (pc, ...)
        local args = pack(...)
        pc.results = pack(pcall(function () return pc.f(unpack(args)) end))
        return pc
      end,
    c = function (pc) return pc:mayrun(pc.after) end,
    --
    -- :run(...) is the highest-level method.
    run = function (pc, ...) return pc:a():b(...):c():rrye() end,
    rrye = function (pc)
        if pc:gotok()
        then return pc:returnresults()
        else pc:yielderror()
        end
      end,
    gotok         = function (pc) return pc.results[1] end,
    yielderror    = function (pc) error(pc.results[2]) end,
    returnresults = function (pc) return unpack(pc.results, 2, pc.results.n) end,
  },
}

-- «PCall-tests»  (to ".PCall-tests")
--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "Globals1.lua"
p = PCall {
  before = function () print "(before)" end,
  f      = function (a,b) print(a,b); return a+b,a*b end,
  after  = function () print "(after)" end,
}
= p:run(3,4)
= p:run(3,nil)

--]]




-- Local Variables:
-- coding:  utf-8-unix
-- End: