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:
@@ -277,12 +277,13 @@ static const struct row rows[] = {
|
||||
/* alloc() builtin: heap-allocate a struct, init from struct-lit.
|
||||
* `package main;` is required so the bare-alloc-builtin gate
|
||||
* (task #23) sees c->cur_mod=="main" and doesn't suppress the
|
||||
* builtin via the inherited os.alloc decl. */
|
||||
* builtin via the inherited os.alloc decl. Task #30 graduated
|
||||
* the builtin to `(*T | nomem)`; the `!` aborts on OOM. */
|
||||
{ "package main;\n"
|
||||
"import os;\n"
|
||||
"type point = struct { x: i32, y: i32 };\n"
|
||||
"fn main() i32 = {\n"
|
||||
" let p: *point = alloc(point { x = 3, y = 4 });\n"
|
||||
" let p: *point = alloc(point { x = 3, y = 4 })!;\n"
|
||||
" return p.x * p.x + p.y * p.y;\n"
|
||||
"};", 25 },
|
||||
/* Hare-style range loop: for (let x .. slice) iterates elements */
|
||||
@@ -296,11 +297,13 @@ static const struct row rows[] = {
|
||||
" return total;\n"
|
||||
"};", 100 },
|
||||
/* alloc([], n): fresh empty slice with cap n. `package main;` for
|
||||
* the same reason as the value-form test above (task #23 gate). */
|
||||
* the same reason as the value-form test above (task #23 gate).
|
||||
* Task #30 graduated the slice form to `([]T | nomem)`; the `!`
|
||||
* aborts on OOM. */
|
||||
{ "package main;\n"
|
||||
"import os;\n"
|
||||
"fn main() i32 = {\n"
|
||||
" let s: []u8 = alloc([], 16);\n"
|
||||
" let s: []u8 = alloc([], 16)!;\n"
|
||||
" append(s, 72u8, 105u8);\n"
|
||||
" return s.cap;\n"
|
||||
"};", 16 },
|
||||
@@ -358,12 +361,13 @@ static const struct row rows[] = {
|
||||
" return (t.0 + t.1): i32;\n"
|
||||
"};", 42 },
|
||||
/* Hare-style abort/assert + free() builtin. `package main;` for
|
||||
* the alloc-builtin gate (task #23). */
|
||||
* the alloc-builtin gate (task #23). Task #30 graduated the
|
||||
* builtin to a fallible signature; the `!` aborts on OOM. */
|
||||
{ "package main;\n"
|
||||
"import os;\n"
|
||||
"type point = struct { x: i64, y: i64 };\n"
|
||||
"fn main() i32 = {\n"
|
||||
" let p: *point = alloc(point { x = 7, y = 35 });\n"
|
||||
" let p: *point = alloc(point { x = 7, y = 35 })!;\n"
|
||||
" let r: i64 = p.x + p.y;\n"
|
||||
" free(p);\n"
|
||||
" os.assert(r == 42, \"sum mismatch\\n\");\n"
|
||||
|
||||
Reference in New Issue
Block a user