x-lang

← Index

x/type/err

Structured errors: the Err class, tag taxonomy, errno translation.

The structured-error convention: tag + message + data over the untyped C error prim. See the header comment for the tag vocabulary and the guard/match idiom.

Class Err

Structured error value: tag symbol + message string + data alist.

The tag 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 tag e) – total over all error values, legacy bare strings answer ‘user.

tag

Member: data carried by a Err instance.

msg

Member: data carried by a Err instance.

data

Member: data carried by a Err instance.

(tag? k)

Test this error’s tag.

Instance method: called on a Err instance.

Parameters:

Returns: BOOL — True when the error’s tag is k

Examples:

((Err make 'io "x" ()) tag? 'io) => #t

(%repr)

Inspection form: #.

Instance method: called on a Err instance.

Returns: STRING — The repr string

%engine-type

Member: data carried by a Err instance.

(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:

Returns: STRING — The slot’s bytes

(Err make tag msg data)

Construct an Err value.

Parameters:

Returns: OBJECT — The Err instance

Examples:

(Err make 'value "bad" ()) => #<err:value bad>

(Err raise tag msg data)

Construct an Err and raise it: (error (Err make tag msg data) “tag: msg”).

Parameters:

Returns: ANY — Does not return

(Err err? v)

Test whether v is an Err instance.

Parameters:

Returns: BOOL — True for Err instances only

Examples:

(Err err? 42) => #f

(Err tag v)

The tag of any error value – TOTAL, so one match discriminates every error the system can raise: an Err answers its own tag, an engine-raised ERR answers ‘engine, and anything else (a legacy bare string) answers ‘user.

Parameters:

Returns: SYMBOL — The Err’s tag, ‘engine, or ‘user

Examples:

(Err tag "bare string") => 'user
(Err tag (Err make 'index "oops" ())) => 'index
(guard (e (Err tag e)) (no-such-binding)) => 'engine

(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:

Returns: 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:

Returns: 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:

Returns: 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:

Returns: 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:

Returns: INT — The positive errno

(Err from-errno n op . detail)

Translate an errno into a tag ‘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:

Returns: 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