Structured errors: the Err class, label taxonomy, errno translation.
The structured-error convention: label + message + data over the untyped C error prim. See the header comment for the label vocabulary and the guard/match idiom.
ErrStructured error value: label symbol + message string + data alist.
The label vocabulary is blessed but open: ‘type ‘value ‘index ‘io ‘state ‘user (see contributing.md). Raise with (Err raise …) or (error (Err make …)); discriminate in a guard with (Err label e) – total over all error values, legacy bare strings answer ‘user.
labelField: data carried by a Err instance.
msgField: data carried by a Err instance.
dataField: data carried by a Err instance.
(label? k)Test this error’s label.
Instance method: called on a Err instance.
Parameters:
SYMBOL — Label to test againstReturns: BOOL — True when the error’s label is k
Examples:
((Err make 'io "x" ()) label? 'io) => #t(%repr)Inspection form: #
Instance method: called on a Err instance.
Returns: STRING — The repr string
Examples:
((Err make 'io "boom" ()) %repr) => "#<err:io boom>"(%str)Display form: LABEL: MESSAGE, the sentence (Err raise …) wrote.
Instance method: called on a Err instance.
An ERR’s code and subject are static-string ATOMS – the engine repoints their string pointers per raise, which is what keeps a raise allocation-free – so they carry no STRING type and Str8 refuses them. Appending to “” copies the bytes out, the same lift the printer always used on a raw error atom.
Returns: STRING — The label, a colon and the message
Examples:
(Str8 str (Err make 'io "boom" ())) => "io: boom"%engine-typeStatic field: data held by Err itself, not by its instances.
(Err %str a)Lift an ERR slot to a real STRING.
An ERR’s code and subject are static-string ATOMS – the engine repoints their string pointers per raise, which is what keeps a raise allocation-free – so they carry no STRING type and Str8 refuses them. Appending to “” copies the bytes out, the same lift the printer always used on a raw error atom.
Parameters:
ANY — An ERR slot: a static-string atomReturns: STRING — The slot’s bytes
Examples:
(guard (e (Err %str (first e))) (no-such-binding)) => "Unbound SYMBOL"(Err make label msg data)Construct an Err value.
Parameters:
SYMBOL — Error label, e.g. ‘ioSTRING — Human-readable messageALIST — Context alist (or ())Returns: OBJECT — The Err instance
Examples:
(Err make 'value "bad" ()) => #<err:value bad>(Err raise label msg data)Construct an Err and raise it: (error (Err make label msg data) “label: msg”).
Parameters:
SYMBOL — Error label, e.g. ‘ioSTRING — Human-readable messageALIST — Context alist (or ())Returns: ANY — Does not return
Examples:
(guard (e (Err label e)) (Err raise 'value "bad" ())) => 'value
(guard (e (e msg)) (Err raise 'value "bad" ())) => "bad"(Err err? v)Test whether v is an Err instance.
Parameters:
ANY — Any valueReturns: BOOL — True for Err instances only
Examples:
(Err err? 42) => #f(Err label v)The label of any error value – TOTAL, so one match discriminates every error the system can raise: an Err answers its own label, an engine-raised ERR answers ‘engine, and anything else (a legacy bare string) answers ‘user.
Parameters:
ANY — Any error valueReturns: SYMBOL — The Err’s label, ‘engine, or ‘user
Examples:
(Err label "bare string") => 'user
(Err label (Err make 'index "oops" ())) => 'index
(guard (e (Err label e)) (no-such-binding)) => 'engine(Err text v)The message of any error value – TOTAL, like label: an Err answers its msg, an engine-raised ERR its code and subject joined by “: “ (the code alone when the raise named no subject), a bare string itself, and anything else “an internal error”.
Parameters:
ANY — Any error valueReturns: STRING — The message
Examples:
(Err text (Err make 'io "boom" ())) => "boom"
(guard (e (Err text e)) (no-such-binding)) => "Unbound SYMBOL: no-such-binding"
(Err text "bare string") => "bare string"(Err engine? v)Test whether v is an ERR – the value the ENGINE raises (an unbound symbol, a failed include), as opposed to an Err the library raised or a bare string.
Parameters:
ANY — Any error valueReturns: BOOL — True for engine-raised errors only
Examples:
(guard (e (Err engine? e)) (no-such-binding)) => #t(Err code-of v)The raise site’s message literal, as a STRING – “Unbound SYMBOL”, “include: cannot open”. The engine’s whole vocabulary is five of these; a lang keys its own wording off them.
Parameters:
ANY — An ERR valueReturns: STRING — The code, or “” for a non-ERR
Examples:
(guard (e (Err code-of e)) (no-such-binding)) => "Unbound SYMBOL"(Err subject-of v)What the raise was about – the unbound symbol’s name, the path that would not open – as a STRING, separate from the code rather than quoted into it. Empty when the raise named no subject.
Parameters:
ANY — An ERR valueReturns: STRING — The subject, or “”
Examples:
(guard (e (Err subject-of e)) (no-such-binding)) => "no-such-binding"(Err stop? v)Test whether v is the interrupt error – ctrl-c, which the engine raises with the code STOP.
Total, and deliberately accepts both spellings: an engine raise arrives as an ERR whose code is STOP, while a bare (error “STOP”) arrives as the string. The REPL’s ctrl-c path tests this rather than lifting bytes out of the value – reading an error’s memory as a symbol name is what printed garbage for every structured error in #46, and an ERR is atom? too, so the same lift would have failed the same way.
Parameters:
ANY — Any error valueReturns: BOOL — True for an interrupt, however it was delivered
Examples:
(guard (e (Err stop? e)) (error "STOP")) => #t(Err errno-of r)Recover the CURRENT errno after a failed libc/syscall call. The syscall prim routes through libc on both OSes, returning a bare -1 with the reason parked behind the per-thread errno location – __error() on Darwin, __errno_location() on Linux; this derefs it (lazily resolving the symbol once). Falls back to (- 0 r) on a libc without the symbol. Fetch BEFORE any intervening call (a close on the error path clobbers errno).
Parameters:
INTEGER — A failed call’s raw return value (negative)Returns: INTEGER — The positive errno
(Err from-errno n op . detail)Translate an errno into a label ‘io Err. The message is strerror-style prefixed with op; data carries ((errno . N) (sym . ENOENT-style-symbol) (op . OP) (detail . D)). Numbers are per-OS (picked at load via os-darwin?); unknown numbers get sym ‘unknown.
Parameters:
INTEGER — errno, positive or the syscall layer’s negative -errnoSYMBOL — The operation, e.g. ‘openANY — Optional context value, e.g. the pathReturns: OBJECT — The Err instance
Examples:
((Err from-errno 2 'open "/nope") msg) => "open: No such file or directory"
(Assoc get 'errno ((Err from-errno -2 'open ()) data)) => 2