selfhost/cmd/ww: strip *arena cascade (γ-5)

amalloc has 0 callers post-γ-2; the *arena threaded through ww
driver's importpathform / locatein / locateimport / enumeratedir /
peekpackage / arenadupcstr / builddirmodulepath / buildsearchpath /
resolvemodule and the expctx.a field are vestigial.

Drop `import mem;`, remove expctx.a, strip *arena from 9 signatures,
update 9 call sites. Drop 4 dead `let a: *arena = newarena();` in
buildone/dobuild/dorun/dotest. Comments retidied. main.combined.ww
auto-regenerated.

builddirmodulepath body intact — still 0 callers; γ-5b drops it.
arenadupcstr name is now a misnomer (task #10).

Verified 132/132 incl. 993_ww_ww + 995_self_rebuild byte-identity.
This commit is contained in:
2026-05-21 12:17:25 +09:00
parent 6faf00223e
commit 7f2a6aa9f3
2 changed files with 54 additions and 160 deletions

View File

@@ -750,98 +750,6 @@ package rt;
// a future task (task #39). ref/hare/rt/malloc.ha:27.
@symbol("rt_malloc") export fn malloc(n: u64) *void;
// selfhost/cmd/wcc/mem.ww — port of cmd/wcc/mem.c.
//
// Bump arena allocator. Backed by the runtime page allocator
// (rt_malloc / rt_free), no libc. Each chunk is mmap'd; when the
// current chunk runs out we link a fresh one. Freeing the arena
// unmaps the chain.
//
// Memory handed out is 16-byte aligned. The C version under
// cmd/wcc/ is retained until the three-stage bootstrap diffs clean.
package wcc;
import os;
import rt;
def ALIGN: u64 = 16u64;
def INIT_CHUNK: u64 = 65536u64;
def MAX_CHUNK: u64 = 4194304u64;
def ARENA_SZ: u64 = 48u64; // sizeof(arena), kept in sync below
type arena = struct {
buf: *u8,
off: u64,
cap: u64,
next: *arena,
total: u64,
};
fn roundup(n: u64, a: u64) u64 = {
return (n + a - 1u64) & ~(a - 1u64);
};
export fn newarena() *arena = {
let a: *arena = rt.malloc(ARENA_SZ): *arena;
a.buf = rt.malloc(INIT_CHUNK): *u8;
a.off = 0u64;
a.cap = INIT_CHUNK;
a.next = nil;
a.total = 0u64;
return a;
};
// Grow: link a fresh chunk in front of the head. We push the old
// chunk into `next` so the head always describes the current bump
// region. Chunk size doubles up to MAX_CHUNK.
fn grow(a: *arena, need: u64) bool = {
let want: u64 = a.cap * 2u64;
if (want < need) { want = need; };
if (want > MAX_CHUNK) { want = MAX_CHUNK; };
if (want < need) { return false; }; // single allocation too big
let old: *arena = rt.malloc(ARENA_SZ): *arena;
old.buf = a.buf;
old.off = a.off;
old.cap = a.cap;
old.next = a.next;
old.total = 0u64;
a.buf = rt.malloc(want): *u8;
a.off = 0u64;
a.cap = want;
a.next = old;
return true;
};
export fn amalloc(a: *arena, n: u64) *void = {
let need: u64 = roundup(n, ALIGN);
if (need > a.cap - a.off) {
if (!grow(a, need)) { return nil; };
};
let p: *u8 = a.buf + a.off;
a.off += need;
a.total += need;
// Zero the region. Plan 9 amalloc zeroes; we mirror that here so
// the checker can assume freshly allocated nodes start at 0.
let i: u64 = 0u64;
for (i < need) {
p[i] = 0u8;
i += 1u64;
};
return p: *void;
};
export fn freearena(a: *arena) void = {
for (a != nil) {
let next: *arena = a.next;
os.free(a.buf: *void, a.cap);
os.free(a: *void, ARENA_SZ);
a = next;
};
};
// types — integer limits. Mirrors Hare's types::limits (I8_MAX, …)
// platform-fixed for amd64. Numeric helpers live in lib/math, matching
// Hare's split between types::limits and math::.
@@ -2790,7 +2698,6 @@ package main;
import os;
import rt;
import mem;
import strings;
// All path/string scratch buffers go on the runtime page allocator.
@@ -2807,7 +2714,7 @@ fn cstrlen(p: *u8) u64 = {
};
// pathstr — view a NUL-terminated *u8 as a str. Bridges the
// driver's argv/arena *u8 paths to lib/os entrypoints (str
// driver's argv-style *u8 paths to lib/os entrypoints (str
// post-task-#23).
fn pathstr(p: *u8) str = {
let r: str;
@@ -2978,7 +2885,6 @@ type strnode = struct {
};
type expctx = struct {
a: *arena, // arena for path strings + the visited list
out: i32, // fd we're writing the combined source to
dirs: *u8, // ":"-separated search path (NUL-terminated)
visit: *strnode,
@@ -3011,7 +2917,7 @@ fn visitadd(c: *expctx, path: str) void = {
// use-path → fs-path mapping
// (ref/hare/hare/module/srcs.ha:78 builds the same shape via
// path::push per ident part).
fn importpathform(a: *arena, name: *u8, namelen: u64) *u8 = {
fn importpathform(name: *u8, namelen: u64) *u8 = {
let buf: []u8 = alloc([], namelen + 1u64)!;
let i: u64 = 0u64;
for (i < namelen) {
@@ -3029,7 +2935,7 @@ fn importpathform(a: *arena, name: *u8, namelen: u64) *u8 = {
// form was dropped in task #22 — directory-as-module enumeration
// replaces it, mirroring ref/hare/hare/module/srcs.ha (Hare has no
// `foo/foo.ha` fallback; a module IS the directory).
fn locatein(a: *arena, dir: *u8, dirlen: u64,
fn locatein(dir: *u8, dirlen: u64,
pathform: *u8, pflen: u64, isdir: *i32) *u8 = {
let buf: []u8 = alloc([], PATH_MAX)!;
let off: u64 = 0u64;
@@ -3078,9 +2984,9 @@ fn locatein(a: *arena, dir: *u8, dirlen: u64,
// Walk a colon-separated dirlist, return first hit or nil. Sets
// *isdir on hit.
fn locateimport(a: *arena, dirs: *u8, name: *u8, namelen: u64,
fn locateimport(dirs: *u8, name: *u8, namelen: u64,
isdir: *i32) *u8 = {
let pathform: *u8 = importpathform(a, name, namelen);
let pathform: *u8 = importpathform(name, namelen);
let pflen: u64 = cstrlen(pathform);
let total: u64 = cstrlen(dirs);
let p: u64 = 0u64;
@@ -3092,7 +2998,7 @@ fn locateimport(a: *arena, dirs: *u8, name: *u8, namelen: u64,
};
let seglen: u64 = q - p;
if (seglen > 0u64) {
let hit: *u8 = locatein(a, dirs + p, seglen,
let hit: *u8 = locatein(dirs + p, seglen,
pathform, pflen, isdir);
if (hit != nil) { return hit; };
};
@@ -3170,8 +3076,8 @@ fn bytecmp(a: *u8, alen: u64, b: *u8, blen: u64) i32 = {
// enumeratedir — list *.ww entries of `dirpath` (less *test.ww and
// *.combined.ww), byte-sort. Returns (names[], nnames) with each
// name a NUL-terminated arena copy.
fn enumeratedir(a: *arena, dirpath: *u8) (**u8, i32) = {
// name a NUL-terminated heap copy.
fn enumeratedir(dirpath: *u8) (**u8, i32) = {
let fd: i32 = os.open(pathstr(dirpath), os.flag.RDONLY, 0i32);
if (fd < 0) { return nil: **u8, 0; };
let maxnames: i32 = 256;
@@ -3332,7 +3238,7 @@ fn expand(c: *expctx, pathcs: *u8) void = {
idp, idn = scanuse(bufp + i, j - i);
if (idp != nil) {
let isdir: i32 = 0;
let ipath: *u8 = locateimport(c.a, c.dirs, idp, idn,
let ipath: *u8 = locateimport(c.dirs, idp, idn,
&isdir);
if (ipath != nil) {
if (isdir != 0) { expanddir(c, ipath); }
@@ -3347,9 +3253,10 @@ fn expand(c: *expctx, pathcs: *u8) void = {
};
// Scan `pathcs` for its first non-comment-non-blank line; if it
// starts with `package <name>;` return the package name as a
// borrowed-arena str, else nil. Same shape as cstage peek_package.
fn peekpackage(a: *arena, pathcs: *u8) *u8 = {
// starts with `package <name>;` return the package name as a fresh
// heap-allocated NUL-terminated *u8, else nil. Same shape as cstage
// peek_package.
fn peekpackage(pathcs: *u8) *u8 = {
let fd: i32 = os.open(pathstr(pathcs), os.flag.RDONLY, 0i32);
if (fd < 0) { return nil; };
let buf: []u8 = alloc([], 2048u64)!;
@@ -3451,7 +3358,7 @@ fn strictpkgmismatch(file: *u8, pkg: *u8, dirpkg: *u8, dirpath: *u8) void = {
fn expanddir(c: *expctx, dirpath: *u8) void = {
let names: **u8;
let n: i32;
names, n = enumeratedir(c.a, dirpath);
names, n = enumeratedir(dirpath);
let dlen: u64 = cstrlen(dirpath);
let dirpkg: *u8 = nil;
let i: i32 = 0;
@@ -3464,7 +3371,7 @@ fn expanddir(c: *expctx, dirpath: *u8) void = {
k = 0u64;
for (k < nlen) { fp[dlen + 1u64 + k] = names[i][k]; k += 1u64; };
fp[dlen + 1u64 + nlen] = 0u8;
let pkg: *u8 = peekpackage(c.a, fp.ptr);
let pkg: *u8 = peekpackage(fp.ptr);
if (pkg != nil) {
if (dirpkg == nil) { dirpkg = pkg; }
else { if (!cstreq(dirpkg, pkg)) {
@@ -3532,8 +3439,6 @@ type lflags = struct {
// still drives the C-built w6c/w6a/w6l. Test 993 pins the two
// pipelines to byte-identical output on a corpus.
fn buildone(selfdir: *u8, src: *u8, entryisdir: i32, out: *u8, incs: *u8, lf: *lflags) i32 = {
let a: *arena = newarena();
let c6: *u8 = joinpathlit(selfdir, "w6c_ww");
let a6: *u8 = joinpathlit(selfdir, "w6a_ww");
let l6: *u8 = joinpathlit(selfdir, "w6l_ww");
@@ -3638,7 +3543,6 @@ fn buildone(selfdir: *u8, src: *u8, entryisdir: i32, out: *u8, incs: *u8, lf: *l
};
{
let c: expctx;
c.a = a;
c.out = cf;
c.dirs = searchpath.ptr;
c.visit = nil;
@@ -3762,8 +3666,8 @@ fn basenameoff(p: *u8, plen: u64) u64 = {
};
// arenadupcstr — copy `plen` bytes from `src` into a fresh NUL-sealed
// arena buffer.
fn arenadupcstr(a: *arena, src: *u8, plen: u64) *u8 = {
// heap buffer.
fn arenadupcstr(src: *u8, plen: u64) *u8 = {
let buf: []u8 = alloc([], plen + 1u64)!;
let i: u64 = 0u64;
for (i < plen) { buf[i] = src[i]; i += 1u64; };
@@ -3771,8 +3675,8 @@ fn arenadupcstr(a: *arena, src: *u8, plen: u64) *u8 = {
return buf.ptr;
};
// builddirmodulepath — alloc <dir>/<base>.ww, NUL-terminated, in `a`.
fn builddirmodulepath(a: *arena, dir: *u8, dlen: u64,
// builddirmodulepath — alloc <dir>/<base>.ww, NUL-terminated.
fn builddirmodulepath(dir: *u8, dlen: u64,
base: *u8, blen: u64) *u8 = {
let need: u64 = dlen + 1u64 + blen + 3u64 + 1u64;
let buf: []u8 = alloc([], need)!;
@@ -3791,7 +3695,7 @@ fn builddirmodulepath(a: *arena, dir: *u8, dlen: u64,
// buildsearchpath — compose the colon-separated lookup path used by
// resolvemodule's case (4). Order: "." : <incs> : <selfdir>/../../lib
fn buildsearchpath(a: *arena, selfdir: *u8, incs: *u8) *u8 = {
fn buildsearchpath(selfdir: *u8, incs: *u8) *u8 = {
let buf: []u8 = alloc([], PATH_MAX * 2u64)!;
let off: u64 = 0u64;
buf[off] = 46u8; off += 1u64; // '.'
@@ -3811,14 +3715,14 @@ fn buildsearchpath(a: *arena, selfdir: *u8, incs: *u8) *u8 = {
// resolvemodule — map a name like "foo", "lib/foo", "foo.ww", or
// "." to a concrete entry path. Sets *isdir when the entry is a
// module directory (caller will dir-enumerate).
fn resolvemodule(a: *arena, selfdir: *u8, name: *u8, incs: *u8, isdir: *i32) *u8 = {
fn resolvemodule(selfdir: *u8, name: *u8, incs: *u8, isdir: *i32) *u8 = {
let nlen: u64 = cstrlen(name);
// (1) Literal file that exists → use as-is.
if (cstrendswithlit(name, ".ww")) {
if (os.access(pathstr(name), 0i32) == 0) {
*isdir = 0;
return arenadupcstr(a, name, nlen);
return arenadupcstr(name, nlen);
};
};
@@ -3837,12 +3741,12 @@ fn resolvemodule(a: *arena, selfdir: *u8, name: *u8, incs: *u8, isdir: *i32) *u8
};
if (found) {
*isdir = foundisdir;
return arenadupcstr(a, name, nlen);
return arenadupcstr(name, nlen);
};
// (3) Search-path lookup with dot-to-slash path translation.
let search: *u8 = buildsearchpath(a, selfdir, incs);
return locateimport(a, search, name, nlen, isdir);
let search: *u8 = buildsearchpath(selfdir, incs);
return locateimport(search, name, nlen, isdir);
};
// ---- Subcommand handlers ----------------------------------------------
@@ -3891,7 +3795,6 @@ fn defaultoutpath(src: *u8) *u8 = {
};
fn dobuild(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
let a: *arena = newarena();
let src: *u8 = nil;
let incs: []u8 = alloc([], PATH_MAX * 2u64)!;
incs.len = (PATH_MAX * 2u64): i32;
@@ -3980,7 +3883,7 @@ fn dobuild(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
src = &dot[0];
};
let isdir: i32 = 0;
let resolved: *u8 = resolvemodule(a, selfdir, src, incs.ptr, &isdir);
let resolved: *u8 = resolvemodule(selfdir, src, incs.ptr, &isdir);
if (resolved == nil) {
os.write(2, "ww build: cannot find module\n".ptr, 29u64);
return 1;
@@ -4042,7 +3945,6 @@ fn makeruntmp(buf: *u8) void = {
};
fn dorun(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
let a: *arena = newarena();
let src: *u8 = nil;
let passstart: i32 = -1; // first argv idx to pass through to program
let incs: []u8 = alloc([], PATH_MAX * 2u64)!;
@@ -4139,7 +4041,7 @@ fn dorun(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
src = &dot[0];
};
let isdir: i32 = 0;
let resolved: *u8 = resolvemodule(a, selfdir, src, incs.ptr, &isdir);
let resolved: *u8 = resolvemodule(selfdir, src, incs.ptr, &isdir);
if (resolved == nil) {
os.write(2, "ww run: cannot find module\n".ptr, 27u64);
return 1;
@@ -4278,7 +4180,6 @@ fn rundirtests(selfdir: *u8, dir: *u8) i32 = {
};
fn dotest(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
let a: *arena = newarena();
let target: *u8;
if (start >= argc) {
let dot: [2]u8 = ['.': u8, 0u8];

View File

@@ -15,7 +15,6 @@ package main;
import os;
import rt;
import mem;
import strings;
// All path/string scratch buffers go on the runtime page allocator.
@@ -32,7 +31,7 @@ fn cstrlen(p: *u8) u64 = {
};
// pathstr — view a NUL-terminated *u8 as a str. Bridges the
// driver's argv/arena *u8 paths to lib/os entrypoints (str
// driver's argv-style *u8 paths to lib/os entrypoints (str
// post-task-#23).
fn pathstr(p: *u8) str = {
let r: str;
@@ -203,7 +202,6 @@ type strnode = struct {
};
type expctx = struct {
a: *arena, // arena for path strings + the visited list
out: i32, // fd we're writing the combined source to
dirs: *u8, // ":"-separated search path (NUL-terminated)
visit: *strnode,
@@ -236,7 +234,7 @@ fn visitadd(c: *expctx, path: str) void = {
// use-path → fs-path mapping
// (ref/hare/hare/module/srcs.ha:78 builds the same shape via
// path::push per ident part).
fn importpathform(a: *arena, name: *u8, namelen: u64) *u8 = {
fn importpathform(name: *u8, namelen: u64) *u8 = {
let buf: []u8 = alloc([], namelen + 1u64)!;
let i: u64 = 0u64;
for (i < namelen) {
@@ -254,7 +252,7 @@ fn importpathform(a: *arena, name: *u8, namelen: u64) *u8 = {
// form was dropped in task #22 — directory-as-module enumeration
// replaces it, mirroring ref/hare/hare/module/srcs.ha (Hare has no
// `foo/foo.ha` fallback; a module IS the directory).
fn locatein(a: *arena, dir: *u8, dirlen: u64,
fn locatein(dir: *u8, dirlen: u64,
pathform: *u8, pflen: u64, isdir: *i32) *u8 = {
let buf: []u8 = alloc([], PATH_MAX)!;
let off: u64 = 0u64;
@@ -303,9 +301,9 @@ fn locatein(a: *arena, dir: *u8, dirlen: u64,
// Walk a colon-separated dirlist, return first hit or nil. Sets
// *isdir on hit.
fn locateimport(a: *arena, dirs: *u8, name: *u8, namelen: u64,
fn locateimport(dirs: *u8, name: *u8, namelen: u64,
isdir: *i32) *u8 = {
let pathform: *u8 = importpathform(a, name, namelen);
let pathform: *u8 = importpathform(name, namelen);
let pflen: u64 = cstrlen(pathform);
let total: u64 = cstrlen(dirs);
let p: u64 = 0u64;
@@ -317,7 +315,7 @@ fn locateimport(a: *arena, dirs: *u8, name: *u8, namelen: u64,
};
let seglen: u64 = q - p;
if (seglen > 0u64) {
let hit: *u8 = locatein(a, dirs + p, seglen,
let hit: *u8 = locatein(dirs + p, seglen,
pathform, pflen, isdir);
if (hit != nil) { return hit; };
};
@@ -395,8 +393,8 @@ fn bytecmp(a: *u8, alen: u64, b: *u8, blen: u64) i32 = {
// enumeratedir — list *.ww entries of `dirpath` (less *test.ww and
// *.combined.ww), byte-sort. Returns (names[], nnames) with each
// name a NUL-terminated arena copy.
fn enumeratedir(a: *arena, dirpath: *u8) (**u8, i32) = {
// name a NUL-terminated heap copy.
fn enumeratedir(dirpath: *u8) (**u8, i32) = {
let fd: i32 = os.open(pathstr(dirpath), os.flag.RDONLY, 0i32);
if (fd < 0) { return nil: **u8, 0; };
let maxnames: i32 = 256;
@@ -557,7 +555,7 @@ fn expand(c: *expctx, pathcs: *u8) void = {
idp, idn = scanuse(bufp + i, j - i);
if (idp != nil) {
let isdir: i32 = 0;
let ipath: *u8 = locateimport(c.a, c.dirs, idp, idn,
let ipath: *u8 = locateimport(c.dirs, idp, idn,
&isdir);
if (ipath != nil) {
if (isdir != 0) { expanddir(c, ipath); }
@@ -572,9 +570,10 @@ fn expand(c: *expctx, pathcs: *u8) void = {
};
// Scan `pathcs` for its first non-comment-non-blank line; if it
// starts with `package <name>;` return the package name as a
// borrowed-arena str, else nil. Same shape as cstage peek_package.
fn peekpackage(a: *arena, pathcs: *u8) *u8 = {
// starts with `package <name>;` return the package name as a fresh
// heap-allocated NUL-terminated *u8, else nil. Same shape as cstage
// peek_package.
fn peekpackage(pathcs: *u8) *u8 = {
let fd: i32 = os.open(pathstr(pathcs), os.flag.RDONLY, 0i32);
if (fd < 0) { return nil; };
let buf: []u8 = alloc([], 2048u64)!;
@@ -676,7 +675,7 @@ fn strictpkgmismatch(file: *u8, pkg: *u8, dirpkg: *u8, dirpath: *u8) void = {
fn expanddir(c: *expctx, dirpath: *u8) void = {
let names: **u8;
let n: i32;
names, n = enumeratedir(c.a, dirpath);
names, n = enumeratedir(dirpath);
let dlen: u64 = cstrlen(dirpath);
let dirpkg: *u8 = nil;
let i: i32 = 0;
@@ -689,7 +688,7 @@ fn expanddir(c: *expctx, dirpath: *u8) void = {
k = 0u64;
for (k < nlen) { fp[dlen + 1u64 + k] = names[i][k]; k += 1u64; };
fp[dlen + 1u64 + nlen] = 0u8;
let pkg: *u8 = peekpackage(c.a, fp.ptr);
let pkg: *u8 = peekpackage(fp.ptr);
if (pkg != nil) {
if (dirpkg == nil) { dirpkg = pkg; }
else { if (!cstreq(dirpkg, pkg)) {
@@ -757,8 +756,6 @@ type lflags = struct {
// still drives the C-built w6c/w6a/w6l. Test 993 pins the two
// pipelines to byte-identical output on a corpus.
fn buildone(selfdir: *u8, src: *u8, entryisdir: i32, out: *u8, incs: *u8, lf: *lflags) i32 = {
let a: *arena = newarena();
let c6: *u8 = joinpathlit(selfdir, "w6c_ww");
let a6: *u8 = joinpathlit(selfdir, "w6a_ww");
let l6: *u8 = joinpathlit(selfdir, "w6l_ww");
@@ -863,7 +860,6 @@ fn buildone(selfdir: *u8, src: *u8, entryisdir: i32, out: *u8, incs: *u8, lf: *l
};
{
let c: expctx;
c.a = a;
c.out = cf;
c.dirs = searchpath.ptr;
c.visit = nil;
@@ -987,8 +983,8 @@ fn basenameoff(p: *u8, plen: u64) u64 = {
};
// arenadupcstr — copy `plen` bytes from `src` into a fresh NUL-sealed
// arena buffer.
fn arenadupcstr(a: *arena, src: *u8, plen: u64) *u8 = {
// heap buffer.
fn arenadupcstr(src: *u8, plen: u64) *u8 = {
let buf: []u8 = alloc([], plen + 1u64)!;
let i: u64 = 0u64;
for (i < plen) { buf[i] = src[i]; i += 1u64; };
@@ -996,8 +992,8 @@ fn arenadupcstr(a: *arena, src: *u8, plen: u64) *u8 = {
return buf.ptr;
};
// builddirmodulepath — alloc <dir>/<base>.ww, NUL-terminated, in `a`.
fn builddirmodulepath(a: *arena, dir: *u8, dlen: u64,
// builddirmodulepath — alloc <dir>/<base>.ww, NUL-terminated.
fn builddirmodulepath(dir: *u8, dlen: u64,
base: *u8, blen: u64) *u8 = {
let need: u64 = dlen + 1u64 + blen + 3u64 + 1u64;
let buf: []u8 = alloc([], need)!;
@@ -1016,7 +1012,7 @@ fn builddirmodulepath(a: *arena, dir: *u8, dlen: u64,
// buildsearchpath — compose the colon-separated lookup path used by
// resolvemodule's case (4). Order: "." : <incs> : <selfdir>/../../lib
fn buildsearchpath(a: *arena, selfdir: *u8, incs: *u8) *u8 = {
fn buildsearchpath(selfdir: *u8, incs: *u8) *u8 = {
let buf: []u8 = alloc([], PATH_MAX * 2u64)!;
let off: u64 = 0u64;
buf[off] = 46u8; off += 1u64; // '.'
@@ -1036,14 +1032,14 @@ fn buildsearchpath(a: *arena, selfdir: *u8, incs: *u8) *u8 = {
// resolvemodule — map a name like "foo", "lib/foo", "foo.ww", or
// "." to a concrete entry path. Sets *isdir when the entry is a
// module directory (caller will dir-enumerate).
fn resolvemodule(a: *arena, selfdir: *u8, name: *u8, incs: *u8, isdir: *i32) *u8 = {
fn resolvemodule(selfdir: *u8, name: *u8, incs: *u8, isdir: *i32) *u8 = {
let nlen: u64 = cstrlen(name);
// (1) Literal file that exists → use as-is.
if (cstrendswithlit(name, ".ww")) {
if (os.access(pathstr(name), 0i32) == 0) {
*isdir = 0;
return arenadupcstr(a, name, nlen);
return arenadupcstr(name, nlen);
};
};
@@ -1062,12 +1058,12 @@ fn resolvemodule(a: *arena, selfdir: *u8, name: *u8, incs: *u8, isdir: *i32) *u8
};
if (found) {
*isdir = foundisdir;
return arenadupcstr(a, name, nlen);
return arenadupcstr(name, nlen);
};
// (3) Search-path lookup with dot-to-slash path translation.
let search: *u8 = buildsearchpath(a, selfdir, incs);
return locateimport(a, search, name, nlen, isdir);
let search: *u8 = buildsearchpath(selfdir, incs);
return locateimport(search, name, nlen, isdir);
};
// ---- Subcommand handlers ----------------------------------------------
@@ -1116,7 +1112,6 @@ fn defaultoutpath(src: *u8) *u8 = {
};
fn dobuild(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
let a: *arena = newarena();
let src: *u8 = nil;
let incs: []u8 = alloc([], PATH_MAX * 2u64)!;
incs.len = (PATH_MAX * 2u64): i32;
@@ -1205,7 +1200,7 @@ fn dobuild(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
src = &dot[0];
};
let isdir: i32 = 0;
let resolved: *u8 = resolvemodule(a, selfdir, src, incs.ptr, &isdir);
let resolved: *u8 = resolvemodule(selfdir, src, incs.ptr, &isdir);
if (resolved == nil) {
os.write(2, "ww build: cannot find module\n".ptr, 29u64);
return 1;
@@ -1267,7 +1262,6 @@ fn makeruntmp(buf: *u8) void = {
};
fn dorun(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
let a: *arena = newarena();
let src: *u8 = nil;
let passstart: i32 = -1; // first argv idx to pass through to program
let incs: []u8 = alloc([], PATH_MAX * 2u64)!;
@@ -1364,7 +1358,7 @@ fn dorun(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
src = &dot[0];
};
let isdir: i32 = 0;
let resolved: *u8 = resolvemodule(a, selfdir, src, incs.ptr, &isdir);
let resolved: *u8 = resolvemodule(selfdir, src, incs.ptr, &isdir);
if (resolved == nil) {
os.write(2, "ww run: cannot find module\n".ptr, 27u64);
return 1;
@@ -1503,7 +1497,6 @@ fn rundirtests(selfdir: *u8, dir: *u8) i32 = {
};
fn dotest(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
let a: *arena = newarena();
let target: *u8;
if (start >= argc) {
let dot: [2]u8 = ['.': u8, 0u8];