ww+wcc: emit and lex // MODULE: <name> directive in combined.ww

This commit is contained in:
2026-05-11 14:54:56 +09:00
parent 5d91ee778e
commit d7036be0e5
9 changed files with 296 additions and 2 deletions

View File

@@ -1,3 +1,4 @@
// MODULE: os
// os — process and filesystem facade. The body of each call lands
// either in libwwrt.a (rt_syscall trampoline) or libc bindings,
// depending on how the program was linked.
@@ -207,6 +208,7 @@ export fn getdents64(fd: i32, buf: *u8, n: u64) i64 = {
return syscall3(SYS_GETDENTS64, fd: i64, buf: i64, n: i64);
};
// MODULE: wcc
// selfhost/cmd/wcc/mem.ww — port of cmd/wcc/mem.c.
//
// Bump arena allocator. Backed by the runtime page allocator
@@ -314,6 +316,7 @@ export fn freearena(a: *arena) void = {
};
};
// MODULE: strconv
// strconv — number↔string conversions. Decimal i64 to/from a fixed
// buffer. Two error idioms ship side by side:
// - Plan 9 style (atoi64): tuple `(value, ok)`. Pre-dates the
@@ -434,6 +437,7 @@ export fn parseu64(s: str) (u64 | str) = {
return v;
};
// MODULE: wcc
// selfhost/cmd/wcc/tok.ww — port of cmd/wcc/tok.c plus the Tkind /
// Tok / Pos shapes from cmd/wcc/ww.h.
//
@@ -829,6 +833,7 @@ export fn tokprint(fd: i32, t: *tok) void = {
fputcbyte(fd, 10u8); // '\n'
};
// MODULE: ascii
// ascii — byte-class predicates and case folding for the ASCII range.
// Matches Hare's ascii::isdigit family. Bytes outside 0..127 always
// answer `false`. The lexer hot path uses these inline; they are
@@ -922,6 +927,7 @@ export fn toupper(c: u8) u8 = {
return c;
};
// MODULE: wcc
// selfhost/cmd/wcc/lex.ww — port of cmd/wcc/lex.c.
//
// The DFA, the helpers, and the order of decisions all mirror the C
@@ -949,6 +955,7 @@ type lex = struct {
col: i32,
a: *arena,
errs: i32,
module: str, // current module from `// MODULE: foo` directive; "" if none
};
export fn lexinit(l: *lex, a: *arena, file: str, src: *u8, len: u64) void = {
@@ -960,6 +967,10 @@ export fn lexinit(l: *lex, a: *arena, file: str, src: *u8, len: u64) void = {
l.col = 1;
l.a = a;
l.errs = 0;
let empty: str;
empty.ptr = nil;
empty.len = 0;
l.module = empty;
};
// srcb — byte at offset; helper that lifts the cast out of indexing.
@@ -1037,6 +1048,32 @@ fn skipws(l: *lex) bool = {
if (c == 47) { // '/'
let c2: i32 = lpeek(l, 1u64);
if (c2 == 47) {
lget(l); lget(l); // consume '//'
// Driver injects `// MODULE: foo` before each
// source file's contents; capture so cgen can
// mangle private symbols by module.
if (lpeek(l, 0u64) == 32) { // ' '
if (lpeek(l, 1u64) == 77) { // 'M'
if (lpeek(l, 2u64) == 79) { // 'O'
if (lpeek(l, 3u64) == 68) { // 'D'
if (lpeek(l, 4u64) == 85) { // 'U'
if (lpeek(l, 5u64) == 76) { // 'L'
if (lpeek(l, 6u64) == 69) { // 'E'
if (lpeek(l, 7u64) == 58) { // ':'
if (lpeek(l, 8u64) == 32) { // ' '
let i: i32 = 0;
for (i < 9) { lget(l); i += 1; };
let start: u64 = l.lpos;
for (true) {
let cx: i32 = lpeek(l, 0u64);
if (cx < 0) { break; };
if (cx == 10) { break; };
if (cx == 13) { break; };
lget(l);
};
let n: u64 = l.lpos - start;
l.module = astrndup(l.a, l.src + start, n);
};};};};};};};};};
for (true) {
let cx: i32 = lpeek(l, 0u64);
if (cx < 0) { return false; };
@@ -1579,6 +1616,7 @@ export fn lexnext(l: *lex, out: *tok) void = {
out.text = astrndup(l.a, one.ptr, 1u64);
};
// MODULE: wcc
// selfhost/cmd/wcc/ast.ww — port of cmd/wcc/ast.c (Node defs + printer).
//
// Status: AST printer is fully ported. Constructor `newnode` is here.
@@ -1915,6 +1953,7 @@ export fn astprint(fd: i32, n: *node) void = {
pr(fd, n, 0);
};
// MODULE: wcc
// selfhost/cmd/wcc/parse.ww — port of cmd/wcc/parse.c.
//
// Status: GROWING stub. Currently handles top-level `use IDENT;`,
@@ -2898,6 +2937,7 @@ export fn parsefile(p: *parser) *node = {
return f;
};
// MODULE: wcc
// selfhost/cmd/wcc/type.ww — port of cmd/wcc/type.c.
//
// Status: full structural port. The C version uses module-globals for
@@ -3228,6 +3268,7 @@ export fn typeeq(a: *tinfo, b: *tinfo) bool = {
return true; // primitives match by kind alone
};
// MODULE: wcc
// selfhost/cmd/wcc/sym.ww — port of cmd/wcc/sym.c.
//
// Per-scope hashtable, chained to the parent. Lookup walks up.
@@ -3342,6 +3383,7 @@ export fn scopedefine(s: *scope, name: str, k: i32, t: *tinfo, decl: *node) *sym
return sy;
};
// MODULE: wcc
// selfhost/cmd/wcc/check.ww — minimal port of cmd/wcc/check.c.
//
// Status: name-resolution + primitive-type seeding only. Full type
@@ -3590,6 +3632,7 @@ export fn checkfile(c: *checker, file: *node) void = {
};
};
// MODULE: wcc
// selfhost/cmd/wcc/cgen.ww — port of cmd/w6c/cgen.c.
//
// Status: GROWING. Each subsystem we add is verified by `wwdump_ww -c`
@@ -6673,6 +6716,7 @@ export fn cgfile(c: *cgen, file: *node) void = {
emitdefconstants(c, file);
};
// MODULE: w6c
// selfhost/cmd/w6c/main.ww — port of cmd/w6c/main.c.
//
// w6c = amd64 compiler. Read .ww, parse, codegen, emit Plan 9 amd64