os: graduate tryopen/trywrite/tryread to (T | oserror)
Final piece of the os module graduation: the three try* wrappers move off the (T | str) placeholder shape. `oserror` becomes a real Hare-style error type (`!i64` instead of plain `i64`), so it's picked up by ?-propagation as the error half without callers having to name it. tryread: (i64 | oserror) was (i64 | str) trywrite: (i64 | oserror) was (i64 | str) tryopen: (i32 | oserror) was (i32 | str) Callsites updated: wwdump uses tryopen; the e2e trywrite probe matches on os.oserror and validates -EBADF for a bad fd (-9 instead of the old "write failed" string length). selfhost/test/smoke.ww switched to raw os.open(2) instead of os.tryopen for probe 7 — same reason as the os.readall switch in the prior commit: probe 6 in 990_selfhost compiles smoke.ww standalone, and cross-module type refs like `os.oserror` don't resolve in that mode.
This commit is contained in:
25
lib/os/os.ww
25
lib/os/os.ww
@@ -73,18 +73,18 @@ export fn dup2(oldfd: i32, newfd: i32) i32 = {
|
||||
return syscall2(SYS_DUP2, oldfd: i64, newfd: i64): i32;
|
||||
};
|
||||
|
||||
// Fallible wrappers. The error variant is a plain str (Plan 9 errstr
|
||||
// model, see lib/errors); the sum type makes success/failure explicit
|
||||
// without overloading length-zero.
|
||||
export fn tryread(fd: i32, buf: *u8, n: u64) (i64 | str) = {
|
||||
// Fallible wrappers. The error variant is `oserror` (an i64 carrying
|
||||
// -errno). The sum type makes success/failure explicit and lets
|
||||
// callers `?` the result up the stack.
|
||||
export fn tryread(fd: i32, buf: *u8, n: u64) (i64 | oserror) = {
|
||||
let r: i64 = read(fd, buf, n);
|
||||
if (r < 0) { return "read failed"; };
|
||||
if (r < 0) { return r: oserror; };
|
||||
return r;
|
||||
};
|
||||
|
||||
export fn trywrite(fd: i32, buf: *u8, n: u64) (i64 | str) = {
|
||||
export fn trywrite(fd: i32, buf: *u8, n: u64) (i64 | oserror) = {
|
||||
let r: i64 = write(fd, buf, n);
|
||||
if (r < 0) { return "write failed"; };
|
||||
if (r < 0) { return r: oserror; };
|
||||
return r;
|
||||
};
|
||||
|
||||
@@ -96,9 +96,9 @@ export fn open(path: *u8, flags: i32, mode: i32) i32 = {
|
||||
return syscall3(SYS_OPEN, path: i64, flags: i64, mode: i64): i32;
|
||||
};
|
||||
|
||||
export fn tryopen(path: *u8, flags: i32, mode: i32) (i32 | str) = {
|
||||
export fn tryopen(path: *u8, flags: i32, mode: i32) (i32 | oserror) = {
|
||||
let fd: i32 = open(path, flags, mode);
|
||||
if (fd < 0) { return "open failed"; };
|
||||
if (fd < 0) { return fd: i64: oserror; };
|
||||
return fd;
|
||||
};
|
||||
|
||||
@@ -111,9 +111,10 @@ export fn lseek(fd: i32, off: i64, whence: i32) i64 = {
|
||||
|
||||
// oserror — the underlying errno from a failed syscall, as a
|
||||
// negative i64 (Linux's int convention; e.g. -2 = ENOENT). The
|
||||
// NAMED-i64 alias makes it a distinct variant tag from a "good"
|
||||
// i64 byte count. Hare's analogue is errors::errno.
|
||||
export type oserror = i64;
|
||||
// `!`-flagged alias makes ?-propagation pick this variant as the
|
||||
// error half of any (T | oserror) shape. Hare's analogue is
|
||||
// errors::errno carried inside io::error.
|
||||
export type oserror = !i64;
|
||||
|
||||
// filesize — byte length of an open fd via lseek-to-end-and-back.
|
||||
export fn filesize(fd: i32) (i64 | oserror) = {
|
||||
|
||||
Reference in New Issue
Block a user