There are two kind of the errors, one we trigger it by ourselves, another one is unexpected.
For the unexpected error, all we need is where it happened, we can use the `error(msg, 0)` to send the msg without change its error location, although the stacktrace info will be broken.
For the expected one, we have to deal with it, like log the error with trace back info, throw it to outside, replaced it with a new error message(like we call the function with wrong arguments).
To diff them, we can use exception object(table) for expected ones, since the unexpected errors are just strings. Here is an example from my PLoop lib, I use `throw` to generate an exception object and save the stack trace, so I can use error(ret) to continue throw it out or just handle it with exception information.
PLoop(function(_ENV) – just ignore this
throw("some thing error")
local ok, ret = pcall(a)
--some thing error
-- x:\WorkSpace\test.lua:5: in function <x:\WorkSpace\test.lua:4>