From 00d88ff9fc10f3999178610a9d22df63cd3c7336 Mon Sep 17 00:00:00 2001 From: Hojun-Cho Date: Thu, 21 May 2026 01:01:13 +0900 Subject: [PATCH] =?UTF-8?q?lib:=20=CE=B1-batch-2=20rt.malloc=20=E2=86=92?= =?UTF-8?q?=20alloc([],=20N)!=20(path/shlex/fmt/ostest)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 0 #8 second α-batch. 7 sites: lib/path/path.ww `join` ×4, lib/shlex/shlex.ww `dupstr`, lib/fmt/fmt.ww `asprintf` tight-copy, lib/os/ostest.ww `test_alloc_free_roundtrip`. Same dup-pilot pattern (4c07ef0, 47918d3): `alloc([], N)!` + `buf.len = N;` + `return strings.frombytes(buf);`. Side effects: - path/shlex/fmt: import switches `rt` → `strings` (callers now reference `strings.frombytes`, not `rt.malloc` direct). - ostest.ww: `import rt;` retained — the alloc builtin lowers to `CALL malloc(SB)` which resolves via rt's @symbol("rt_malloc") decl. Other files reach rt transitively via `import strings`; ostest only imports os, so it needs the explicit rt import. - shlex stale comment "avoid strings dep" stripped — strings is now in scope. Verified make test 132/132 + 995_self_rebuild byte-identity. Advances #43. --- lib/fmt/fmt.ww | 9 ++++----- lib/os/ostest.ww | 16 ++++++---------- lib/path/path.ww | 34 +++++++++++++--------------------- lib/shlex/shlex.ww | 14 ++++++-------- 4 files changed, 29 insertions(+), 44 deletions(-) diff --git a/lib/fmt/fmt.ww b/lib/fmt/fmt.ww index d7af7130..970aa015 100644 --- a/lib/fmt/fmt.ww +++ b/lib/fmt/fmt.ww @@ -29,7 +29,7 @@ package fmt; import io; import memio; import os; -import rt; +import strings; import strconv; // i64dec_buf — scratch buffer for [[i64dec]] below. Module-level @@ -886,7 +886,7 @@ export fn asprintf(fmt: str, args: field...) str = { match (cres) { case void => {}; case io.closed => {}; }; return out; }; - let tight: *u8 = rt.malloc(view.len: u64): *u8; + let tight: []u8 = alloc([], view.len: u64)!; let i: i32 = 0; for (i < view.len) { tight[i] = view.ptr[i]; @@ -894,7 +894,6 @@ export fn asprintf(fmt: str, args: field...) str = { }; let cres: (void | io.closed) = io.close(&s); match (cres) { case void => {}; case io.closed => {}; }; - out.ptr = tight; - out.len = view.len; - return out; + tight.len = view.len; + return strings.frombytes(tight); }; diff --git a/lib/os/ostest.ww b/lib/os/ostest.ww index a79b2891..e3e15220 100644 --- a/lib/os/ostest.ww +++ b/lib/os/ostest.ww @@ -97,22 +97,18 @@ fn streq(a: str, b: str) bool = { // ---- alloc/free: mmap-backed runtime allocator ---------------------- // -// Direct round-trip. memio's dynamic-buffer tests already exercise -// os.alloc / os.free transitively; the row here pins the FFI shape -// at the lib/os layer (write+read-back proves the returned page is -// dereferenceable, not just non-nil). +// Direct round-trip. Write-then-read-back proves the returned page is +// dereferenceable. A miscompiled binding (wrong arg order, wrong ABI, +// etc.) would either fault or return zero here. @test fn test_alloc_free_roundtrip() void = { - let p: *u8 = rt.malloc(4096u64): *u8; - if (p == nil: *u8) { fail(); }; - // Write a sentinel at the head and tail of the page, read it - // back. A miscompiled binding (wrong arg order, wrong ABI, etc.) - // would either fault or return zero here. + let p: []u8 = alloc([], 4096u64)!; + p.len = 4096; p[0] = 90u8; // 0x5a p[4095] = 165u8; // 0xa5 if (p[0] != 90u8) { fail(); }; if (p[4095] != 165u8) { fail(); }; - os.free(p: *void, 4096u64); + os.free(p.ptr: *void, 4096u64); }; export fn main() i32 = { diff --git a/lib/path/path.ww b/lib/path/path.ww index abb3a368..8e7d1867 100644 --- a/lib/path/path.ww +++ b/lib/path/path.ww @@ -5,7 +5,7 @@ package path; -import rt; +import strings; def SEP: u8 = 47u8; // '/' @@ -95,31 +95,25 @@ export fn extension(p: str) str = { // two-arg join (no variadic). export fn join(a: str, b: str) str = { if (abs(b)) { - let buf: *u8 = rt.malloc(b.len: u64): *u8; + let buf: []u8 = alloc([], b.len: u64)!; let i: i32 = 0; for (i < b.len) { buf[i] = b[i]; i += 1; }; - let r: str; - r.ptr = buf; - r.len = b.len; - return r; + buf.len = b.len; + return strings.frombytes(buf); }; if (a.len == 0) { - let buf: *u8 = rt.malloc(b.len: u64): *u8; + let buf: []u8 = alloc([], b.len: u64)!; let i: i32 = 0; for (i < b.len) { buf[i] = b[i]; i += 1; }; - let r: str; - r.ptr = buf; - r.len = b.len; - return r; + buf.len = b.len; + return strings.frombytes(buf); }; if (b.len == 0) { - let buf: *u8 = rt.malloc(a.len: u64): *u8; + let buf: []u8 = alloc([], a.len: u64)!; let i: i32 = 0; for (i < a.len) { buf[i] = a[i]; i += 1; }; - let r: str; - r.ptr = buf; - r.len = a.len; - return r; + buf.len = a.len; + return strings.frombytes(buf); }; // Trim trailing '/' from a; b never starts with '/' here (checked // above via abs(b)). @@ -129,14 +123,12 @@ export fn join(a: str, b: str) str = { an -= 1; }; let total: i32 = an + 1 + b.len; - let buf: *u8 = rt.malloc(total: u64): *u8; + let buf: []u8 = alloc([], total: u64)!; let i: i32 = 0; for (i < an) { buf[i] = a[i]; i += 1; }; buf[an] = SEP; let j: i32 = 0; for (j < b.len) { buf[an + 1 + j] = b[j]; j += 1; }; - let r: str; - r.ptr = buf; - r.len = total; - return r; + buf.len = total; + return strings.frombytes(buf); }; diff --git a/lib/shlex/shlex.ww b/lib/shlex/shlex.ww index 71264b08..21dcca30 100644 --- a/lib/shlex/shlex.ww +++ b/lib/shlex/shlex.ww @@ -97,7 +97,7 @@ package shlex; import io; import memio; import os; -import rt; +import strings; // rt_ensure is the runtime slice-growth helper invoked by the // `append(s, v)` builtin. We bind it directly because the builtin's @@ -118,20 +118,18 @@ export fn strerror(err: syntaxerr) str = { return "Invalid shell syntax"; }; -// dupstr — local strings.dup. Inlined to avoid a `use strings;` dep -// on this small site; same algorithm and same {nil, 0} handling for -// empty input. +// dupstr — local strings.dup. Inlined (same algorithm and same +// {nil, 0} handling for empty input). fn dupstr(s: str) str = { let r: str; r.ptr = nil; r.len = 0; if (s.len == 0) { return r; }; - let buf: *u8 = rt.malloc(s.len: u64): *u8; + let buf: []u8 = alloc([], s.len: u64)!; let i: i32 = 0; for (i < s.len) { buf[i] = s[i]; i += 1; }; - r.ptr = buf; - r.len = s.len; - return r; + buf.len = s.len; + return strings.frombytes(buf); }; // appendstr — grow `*slice` by one and store `item` (16B). Bypasses