cmd+rt+selfhost+test: graduate alloc to (*T | nomem) / ([]T | nomem)
Per Hare convention, alloc is a typed builtin that returns a tagged
union carrying nomem as the OOM variant. Callers spell their policy:
`alloc(T)!` aborts on OOM (the old behavior), `alloc(T)?` propagates
when the enclosing fn already returns nomem.
cstage: check builds TY_TAGGED{*T | nomem} (or {[]T | nomem}); cgen
emits AX=tag, DX=ptr per the general tagged-return ABI (the (*T|!void)
nullable-ptr fold gated in ea76ee4 keeps this clean). wwstage cgalloc
mirrors. rt/alloc.s zeroes AX on syscall error so the builtin's null
check sees a clean 0 instead of mmap's -errno leaking through as a
poisoned pointer.
Migration: 3 `!` sites in test/wcc/700_e2e.c, 1 `!` site in
rt/ensure.ww (preserves the pre-existing sizeof bug tracked by #27),
1 `?` site in selfhost/test/tagged_ptr_ret.ww (allocbox exercises
real `?` propagation against a (*T | nomem) return).
130/130 tests green, 994_w6c_ww + 995_self_rebuild stage byte-identity
preserved. Follow-ups #31 (wwstage checkletassign leniency), #32
(wwstage slice-form gap), #33 (tagged_ptr_ret.ww make-test wiring).
This commit is contained in:
@@ -13,10 +13,19 @@
|
||||
// Two match arms cover both runtime outcomes — success unwrap (tag=0,
|
||||
// ptr payload in DX) and error propagation (tag=1) — exercising the
|
||||
// same AX/DX ABI both stages must agree on.
|
||||
//
|
||||
// Task #30: the `alloc` builtin itself now returns `(*T | nomem)`. The
|
||||
// allocbox arm below propagates the builtin's tagged return through
|
||||
// the enclosing fn via `?` against a same-shape `(*point | nomem)`
|
||||
// — matching the team-lead spec's "exercise `alloc(T)?` against a
|
||||
// real function returning `(T | nomem)`".
|
||||
|
||||
package test;
|
||||
package main;
|
||||
|
||||
import fmt;
|
||||
import os;
|
||||
|
||||
type point = struct { x: i32, y: i32 };
|
||||
|
||||
fn alloc1(fail: i64) (*u8 | nomem) = {
|
||||
if (fail != 0i64) { let e: nomem; return e; };
|
||||
@@ -29,6 +38,11 @@ fn caller(fail: i64) (*u8 | nomem) = {
|
||||
return p;
|
||||
};
|
||||
|
||||
fn allocbox() (*point | nomem) = {
|
||||
let p: *point = alloc(point { x = 3, y = 4 })?;
|
||||
return p;
|
||||
};
|
||||
|
||||
export fn main() i32 = {
|
||||
let rc: i32 = 0;
|
||||
match (caller(0i64)) {
|
||||
@@ -50,5 +64,15 @@ export fn main() i32 = {
|
||||
fmt.println("nomem as expected");
|
||||
};
|
||||
};
|
||||
match (allocbox()) {
|
||||
case let p: *point => {
|
||||
fmt.println("allocbox ok");
|
||||
if (p.x * p.x + p.y * p.y != 25) { rc = 4; };
|
||||
};
|
||||
case nomem => {
|
||||
fmt.println("allocbox unexpected nomem");
|
||||
rc = 5;
|
||||
};
|
||||
};
|
||||
return rc;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user