selfhost: ?/! postfix in parser + cgen; use ! in lex.ww escape path
Selfhost parser (lib/ww/parse/expr.ww) recognises postfix `?` and `!` at the same level as `as`/`is`/`:`. Selfhost cgen (selfhost/cmd/wcc/cgenexpr.ww) emits matching code: cmp AX against the success tag (0 in legacy mode), branch over the propagate / abort path, then unwrap (DX → AX, CX → BX for str). Mirrors the C cgen but without the tag-remap loop — none of the selfhost code that uses `?` today needs cross-shape remapping. lib/ww/lex/lex.ww \\x escape handling switched from 5-line match blocks to one-liners: ascii.digitval(c: rune)!. Both digits are already validated by isxdigit above; the void variant is unreachable, so `!` collapses correctly. 995 fixed-point gate verifies the selfhost cgen produces the same `!` codegen as C cgen.
This commit is contained in:
@@ -74,18 +74,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;
|
||||
};
|
||||
|
||||
@@ -97,9 +97,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;
|
||||
};
|
||||
|
||||
@@ -112,9 +112,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