lib: port errors.errno + os errno/strerror sys-layer (#6)
Hare-faithful port of errors::errno (ref/hare/errors/{rt,common,opaque}.ha): the 13 named common error conditions, opaque_data/opaque_ (the type-erased tail whose strerror fn-ptr defers to os.strerror), and errno(os.errno) error mapping the ~12 mapped errnos to named conditions and wrapping the unmapped tail in opaque_. The raw errno type (!i32, kernel-int width, distinct from oserror's !i64 negative raw return), the E* constants, and the strerror message table live in lib/os: ww folds Hare's sys role into os, so os is the import floor that lib/io and lib/errors build on -- documented in lib/CLAUDE.md (os never imports io or errors). errors.error is explicitly enumerated, matching Hare; the ...errors::error spread is only io.error's (blocked by #199b). Prereq for post-eFinal #5's faithful io error mapping; retires the nomem-collapse interim. Adds errnotest (mapping / opaque-tail / strerror) + test/wcc/902_errno_run. Landing required two wwstage cgen fixes (#9 struct-variant-large-union return, #11 deref-store alias narrow). Divergences cited at-site: bare-type-name return -> let+return; switch fall-through vs Hare's exhaustiveness-only default; opaque_ const dropped.
This commit is contained in:
@@ -265,6 +265,57 @@ export fn lseek(fd: i32, off: i64, w: whence) i64 = {
|
||||
// errors::errno carried inside io::error.
|
||||
export type oserror = !i64;
|
||||
|
||||
// errno — the raw Linux errno as a positive code (ref/hare/sys/+linux/
|
||||
// errno.ha:5, `errno = !int`). ww folds Hare's `sys` role into os
|
||||
// (lib/CLAUDE.md), so the sys::errno machinery lands here. Spelled i32
|
||||
// rather than int: Linux errnos are kernel ints (32-bit), keeping os's
|
||||
// kernel-facing surface uniformly i32. Distinct from [[oserror]] (!i64,
|
||||
// the syscall's *negative* raw return) — the two model different
|
||||
// things, so they are not unified; the negative→positive normalization
|
||||
// lives at the oserror→errors.error boundary in those callers.
|
||||
export type errno = !i32;
|
||||
|
||||
// Mapped errno values, ref/hare/sys/+linux/errno.ha:559-682. Positive,
|
||||
// matching Hare's defs (the kernel returns -N; the wrap-to-positive is
|
||||
// the caller's concern). Subset: exactly the errnos [[errors.errno]]
|
||||
// maps to a named condition; grow as callers surface more.
|
||||
export def ENOENT: errno = 2;
|
||||
export def EINTR: errno = 4;
|
||||
export def EAGAIN: errno = 11;
|
||||
export def EACCES: errno = 13;
|
||||
export def EBUSY: errno = 16;
|
||||
export def EEXIST: errno = 17;
|
||||
export def EINVAL: errno = 22;
|
||||
export def EOVERFLOW: errno = 75;
|
||||
export def ENETUNREACH: errno = 101;
|
||||
export def ETIMEDOUT: errno = 110;
|
||||
export def ECONNREFUSED: errno = 111;
|
||||
export def ECANCELED: errno = 125;
|
||||
|
||||
// strerror — human-readable text for an [[errno]] (Hare's
|
||||
// sys::strerror, ref/hare/sys/+linux/errno.ha:18). FAITHFUL MINIMAL
|
||||
// SUBSET: the mapped errnos above plus a generic fallback; grow the
|
||||
// switch as callers surface more (lib/CLAUDE.md documented-subset, not
|
||||
// a workaround). Messages verbatim from the reference. Hare's
|
||||
// unknown_errno formats the numeric value; that is deferred.
|
||||
export fn strerror(err: errno) str = {
|
||||
switch (err) {
|
||||
case ENOENT: return "No such file or directory";
|
||||
case EINTR: return "Interrupted system call";
|
||||
case EAGAIN: return "Resource temporarily unavailable";
|
||||
case EACCES: return "Permission denied";
|
||||
case EBUSY: return "Device or resource busy";
|
||||
case EEXIST: return "File exists";
|
||||
case EINVAL: return "Invalid argument";
|
||||
case EOVERFLOW: return "Value too large for defined data type";
|
||||
case ENETUNREACH: return "Network is unreachable";
|
||||
case ETIMEDOUT: return "Connection timed out";
|
||||
case ECONNREFUSED: return "Connection refused";
|
||||
case ECANCELED: return "Operation canceled";
|
||||
};
|
||||
return "Unknown error";
|
||||
};
|
||||
|
||||
// filesize — byte length of an open fd via lseek-to-end-and-back.
|
||||
export fn filesize(fd: i32) (i64 | oserror) = {
|
||||
let end: i64 = lseek(fd, 0i64, whence.END);
|
||||
|
||||
Reference in New Issue
Block a user