lib: banner purge + WHY-only comment sweep (rule 8)
Every // ---- section banner dies (132 -> 0): names carry the WHAT. Narration deleted (filename restatements, run-with lines, what-the- next-line-does); every ref/hare cite, task cite, divergence, ABI/ layout contract, and ownership qualifier kept (borrowed-view lines restored where the sweep over-cut). Comment-only proven: all 442 walk-workdir .s and 32 import-probe .s byte-identical before/after; libbyteid 56-roster all-ID.
This commit is contained in:
@@ -1,7 +1,4 @@
|
||||
// lib/ww/syntax/ast.ww — port of cmd/wcc/ast.c (Node defs + printer).
|
||||
//
|
||||
// Status: AST printer is fully ported. Constructor `newnode` is here.
|
||||
// The parser (parse.ww) is currently minimal — see its file header.
|
||||
// Port of cmd/wcc/ast.c (Node defs + printer).
|
||||
//
|
||||
// Calling-convention shim: same as tok/lex — `node` is too big to pass
|
||||
// by value (8 *node pointers + 2 strs + a few ints), so callers always
|
||||
@@ -12,14 +9,10 @@ package syntax;
|
||||
import os;
|
||||
import strconv;
|
||||
|
||||
// ---- Nkind ------------------------------------------------------------
|
||||
//
|
||||
// Mirror of cmd/wcc/ww.h Nkind. Values must stay numerically equal
|
||||
// to the C side (rule-6 data-shape mirror).
|
||||
|
||||
// Mirror of the C `Nkind` enum in cmd/wcc/ww.h. Numeric values are
|
||||
// explicit and must stay in sync with the C side. Tail-appended
|
||||
// entries (TYPETEST onward) preserve every prior N_* value.
|
||||
// Mirror of the C `Nkind` enum in cmd/wcc/ww.h (rule-6 data-shape
|
||||
// mirror). Numeric values are explicit and must stay in sync with the
|
||||
// C side. Tail-appended entries (TYPETEST onward) preserve every prior
|
||||
// N_* value.
|
||||
export type nkind = enum i32 {
|
||||
N_NONE = 0,
|
||||
|
||||
@@ -112,8 +105,6 @@ export type nkind = enum i32 {
|
||||
N_LAST = 68,
|
||||
};
|
||||
|
||||
// ---- Node -------------------------------------------------------------
|
||||
|
||||
export type node = struct {
|
||||
kind: nkind,
|
||||
file: str,
|
||||
@@ -150,8 +141,6 @@ export fn newnode(k: nkind, file: str, line: i32, col: i32) *node = {
|
||||
return n;
|
||||
};
|
||||
|
||||
// ---- printer ----------------------------------------------------------
|
||||
|
||||
export fn nkname(k: nkind) str = {
|
||||
switch (k) {
|
||||
case nkind.N_NONE: return "none";
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
// asttest — functional-equivalence pin for [[nkname]] after the
|
||||
// if-ladder → switch fold (struct fold S2). Run with
|
||||
// `ww run -I lib/ww lib/ww/syntax/asttest.ww`.
|
||||
// Functional-equivalence pin for [[nkname]] after the
|
||||
// if-ladder → switch fold (struct fold S2).
|
||||
//
|
||||
// nkname is checked against every nkind value (the full ladder the
|
||||
// switch replaced) plus the out-of-band fallback ("?"). A failing row
|
||||
// aborts via the assert/abort builtin (task #5 @test conversion).
|
||||
// `package main` + bare `import ast` mirrors wwdump (the external
|
||||
// astprint consumer).
|
||||
|
||||
package syntax_test;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// lib/ww/syntax/decl.ww — declaration parsing, split out of parse.ww.
|
||||
// Declaration-parsing half of the cmd/wcc/parse.c port.
|
||||
|
||||
package syntax;
|
||||
|
||||
@@ -14,7 +14,7 @@ fn parseuse(p: *parser) *node = {
|
||||
let pf: str = p.curfile;
|
||||
let pl: i32 = p.curline;
|
||||
let pc: i32 = p.curcol;
|
||||
advance(p); // past `use`
|
||||
advance(p);
|
||||
let n: *node = newnode(nkind.N_USE, pf, pl, pc);
|
||||
n.nmod = p.curmod;
|
||||
// M1 #22: accumulate the full dotted import path (n.usepath) for the
|
||||
@@ -24,7 +24,7 @@ fn parseuse(p: *parser) *node = {
|
||||
expectident(p, &leaf);
|
||||
let path: str = leaf;
|
||||
for (p.curkind == tkind.TK_DOT) {
|
||||
advance(p); // past `.`
|
||||
advance(p);
|
||||
expectident(p, &leaf);
|
||||
path = strings.concat(path, ".", leaf);
|
||||
};
|
||||
@@ -38,7 +38,7 @@ fn parsedef(p: *parser, exported: i32) *node = {
|
||||
let pf: str = p.curfile;
|
||||
let pl: i32 = p.curline;
|
||||
let pc: i32 = p.curcol;
|
||||
advance(p); // past `def`
|
||||
advance(p);
|
||||
let n: *node = newnode(nkind.N_DEF, pf, pl, pc);
|
||||
n.nmod = p.curmod;
|
||||
let id: str;
|
||||
@@ -160,7 +160,7 @@ fn parsefn(p: *parser, exported: i32, attrs: *node) *node = {
|
||||
let pf: str = p.curfile;
|
||||
let pl: i32 = p.curline;
|
||||
let pc: i32 = p.curcol;
|
||||
advance(p); // past `fn`
|
||||
advance(p);
|
||||
let n: *node = newnode(nkind.N_FNDECL, pf, pl, pc);
|
||||
n.nmod = p.curmod;
|
||||
let id: str;
|
||||
@@ -190,7 +190,7 @@ fn parsetypedecl(p: *parser, exported: i32) *node = {
|
||||
let pf: str = p.curfile;
|
||||
let pl: i32 = p.curline;
|
||||
let pc: i32 = p.curcol;
|
||||
advance(p); // past `type`
|
||||
advance(p);
|
||||
let n: *node = newnode(nkind.N_TYPEDECL, pf, pl, pc);
|
||||
n.nmod = p.curmod;
|
||||
let id: str;
|
||||
@@ -202,4 +202,3 @@ fn parsetypedecl(p: *parser, exported: i32) *node = {
|
||||
n.exported = exported;
|
||||
return n;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
// lib/ww/syntax/expr.ww — expression parsing, split out of parse.ww.
|
||||
// Expression-parsing half of the cmd/wcc/parse.c port.
|
||||
|
||||
package syntax;
|
||||
|
||||
import os;
|
||||
|
||||
// streqlocal — str-to-str compare. Inlined here to avoid a cross-
|
||||
// module `use sym;` for one call site.
|
||||
// Inlined to avoid a cross-module `use sym;` for one call site.
|
||||
fn streqlocal(a: str, b: str) bool = {
|
||||
if (a.len != b.len) { return false; };
|
||||
let i: i32 = 0;
|
||||
@@ -113,7 +112,6 @@ fn parseprimary(p: *parser) *node = {
|
||||
if (p.curkind == tkind.TK_LPAREN) {
|
||||
advance(p);
|
||||
let e: *node = parseexpr(p);
|
||||
// Tuple literal: (a, b, ...)
|
||||
if (accepttok(p, tkind.TK_COMMA)) {
|
||||
let t: *node = newnode(nkind.N_TUPLE, pf, pl, pc);
|
||||
t.list = e;
|
||||
@@ -194,7 +192,7 @@ fn parseprimary(p: *parser) *node = {
|
||||
let cf: str = p.curfile;
|
||||
let cl: i32 = p.curline;
|
||||
let cc: i32 = p.curcol;
|
||||
advance(p); // past `case`
|
||||
advance(p);
|
||||
let mc: *node = newnode(nkind.N_MCASE, cf, cl, cc);
|
||||
if (p.curkind == tkind.TK_LET) {
|
||||
advance(p);
|
||||
@@ -545,4 +543,3 @@ fn parseexpr(p: *parser) *node = {
|
||||
};
|
||||
return e;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// lib/ww/syntax/lex.ww — port of cmd/wcc/lex.c.
|
||||
// Port of cmd/wcc/lex.c.
|
||||
//
|
||||
// The DFA, the helpers, and the order of decisions all mirror the C
|
||||
// version exactly; any divergence surfaces as a cs/ww byte split in
|
||||
@@ -18,9 +18,8 @@ import strings;
|
||||
import strconv;
|
||||
import encoding.utf8;
|
||||
|
||||
// isidstart / isidpart — identifier classification. Lexer-local
|
||||
// because the "alpha or '_' / alnum or '_'" set isn't part of Hare's
|
||||
// ascii::; ascii::isalpha + the '_' check live here instead.
|
||||
// Lexer-local because the "alpha or '_' / alnum or '_'" set isn't part
|
||||
// of Hare's ascii::; ascii::isalpha + the '_' check live here instead.
|
||||
fn isidstart(c: rune) bool = {
|
||||
if (ascii.isalpha(c)) { return true; };
|
||||
if (c == '_') { return true; };
|
||||
@@ -33,8 +32,6 @@ fn isidpart(c: rune) bool = {
|
||||
return false;
|
||||
};
|
||||
|
||||
// hexval — value of `c` as a hex digit (0..15) or void if not a hex
|
||||
// digit. Used by string-literal `\xHH` escapes.
|
||||
fn hexval(c: rune) (i32 | void) = {
|
||||
if (ascii.isdigit(c)) { return (c - '0'): i32; };
|
||||
if (c >= 'A') {
|
||||
@@ -81,7 +78,6 @@ export fn lexinit(l: *lex, file: str, src: *u8, len: u64) void = {
|
||||
l.modresetpathset = 0;
|
||||
};
|
||||
|
||||
// srcb — byte at offset; helper that lifts the cast out of indexing.
|
||||
fn srcb(l: *lex, off: u64) i32 = {
|
||||
let i: i32 = off: i32;
|
||||
let b: u8 = l.src[i];
|
||||
@@ -139,7 +135,7 @@ fn skipws(l: *lex) bool = {
|
||||
if (c == '/') {
|
||||
let c2: i32 = lpeek(l, 1u64);
|
||||
if (c2 == '/') {
|
||||
lget(l); lget(l); // consume '//'
|
||||
lget(l); lget(l);
|
||||
// #16 opt-B: recognize the driver's curmod-reset
|
||||
// boundary directive `//ww:module-reset` (whole
|
||||
// line) and flag it; lexnext emits TK_MODRESET.
|
||||
@@ -371,7 +367,6 @@ fn escape(l: *lex, out: *i32) bool = {
|
||||
return false;
|
||||
};
|
||||
|
||||
// scandecimalrun — consume a run of decimal digits and underscores.
|
||||
fn scandecimalrun(l: *lex) void = {
|
||||
for (true) {
|
||||
let c: i32 = lpeek(l, 0u64);
|
||||
@@ -415,7 +410,6 @@ fn scanoctrun(l: *lex) void = {
|
||||
};
|
||||
};
|
||||
|
||||
// scanexp — consume the [eE][+-]?[0-9]+ tail of a float, if present.
|
||||
fn scanexp(l: *lex) void = {
|
||||
let e: i32 = lpeek(l, 0u64);
|
||||
if (e != 'e') { if (e != 'E') { return; }; };
|
||||
@@ -752,8 +746,6 @@ fn emitsimple(start: *pos, k: tkind, out: *tok) void = {
|
||||
out.col = start.col;
|
||||
};
|
||||
|
||||
// setposfrom — copy file/line/col from a *pos into a tok. Used by
|
||||
// the err-token path where we already have a pos.
|
||||
fn setposfrom(out: *tok, p: *pos) void = {
|
||||
out.file = p.file;
|
||||
out.line = p.line;
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
// lib/ww/syntax/parse.ww — port of cmd/wcc/parse.c (entry + plumbing).
|
||||
//
|
||||
// Split into Hare-style submodule: parse.ww (here) holds the parser
|
||||
// struct, lexer plumbing, parsetype, parsefile (entry). Expression,
|
||||
// statement, and declaration parsers live in expr.ww, stmt.ww,
|
||||
// decl.ww respectively — all in the same `parse` module.
|
||||
// Port of cmd/wcc/parse.c (entry + plumbing).
|
||||
//
|
||||
// Calling-convention shim: w6c can't yet pass a sub-struct field
|
||||
// (e.g. p.cur.line where p.cur is a `tok` of size 76). The parser
|
||||
@@ -96,7 +91,6 @@ fn expecttok(p: *parser, k: tkind, what: str) bool = {
|
||||
return false;
|
||||
};
|
||||
|
||||
// expectident — consume the current tkind.TK_IDENT and return its text.
|
||||
// Returns the empty str on error (and advances to make progress).
|
||||
fn expectident(p: *parser, into: *str) bool = {
|
||||
if (p.curkind != tkind.TK_IDENT) {
|
||||
@@ -109,9 +103,7 @@ fn expectident(p: *parser, into: *str) bool = {
|
||||
return true;
|
||||
};
|
||||
|
||||
// expectbindname — like expectident but also accepts a bare `_`
|
||||
// discard marker. On `_`, returns "" so the checker skips
|
||||
// scope_define for the binding.
|
||||
// On `_`, returns "" so the checker skips scope_define for the binding.
|
||||
fn expectbindname(p: *parser, into: *str) bool = {
|
||||
if (p.curkind == tkind.TK_UNDER) {
|
||||
*into = "";
|
||||
@@ -121,14 +113,7 @@ fn expectbindname(p: *parser, into: *str) bool = {
|
||||
return expectident(p, into);
|
||||
};
|
||||
|
||||
// ---- type expressions ------------------------------------------------
|
||||
//
|
||||
// Currently: TNAME (single ident, no dotted path yet) and TPTR (`*T`).
|
||||
// Other forms (slice, array, struct, fn, chan, tuple, tagged) will
|
||||
// land in subsequent commits.
|
||||
|
||||
// joindotted — build "head.tail" for dotted type-name path
|
||||
// collapse. Mirrors aprintf in C parser; pulled local to avoid a
|
||||
// Mirrors aprintf in the C parser; pulled local to avoid a
|
||||
// cross-module dependency.
|
||||
fn joindotted(head: str, tail: str) str = {
|
||||
let n: u64 = head.len: u64 + 1u64 + tail.len: u64;
|
||||
@@ -391,13 +376,6 @@ fn parsetype(p: *parser) *node = {
|
||||
return newnode(nkind.N_TNAME, pf, pl, pc);
|
||||
};
|
||||
|
||||
// ---- expressions (Pratt) ---------------------------------------------
|
||||
//
|
||||
// Forwards: parseexpr → parsebin → parseunary → parsepostfix(parseprimary).
|
||||
// Tuple literals, match expressions, struct literals, slice [lo:hi],
|
||||
// and the ?/! try operators are not yet wired — they'll arrive as the
|
||||
// AST diff fixture grows to need them.
|
||||
|
||||
fn bprec(k: tkind) i32 = {
|
||||
if (k == tkind.TK_OR) { return 1; };
|
||||
if (k == tkind.TK_AND) { return 2; };
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// lib/ww/syntax/stmt.ww — statement parsing, split out of parse.ww.
|
||||
// Statement-parsing half of the cmd/wcc/parse.c port.
|
||||
|
||||
package syntax;
|
||||
|
||||
@@ -118,7 +118,7 @@ fn parseif(p: *parser) *node = {
|
||||
let pf = p.curfile;
|
||||
let pl = p.curline;
|
||||
let pc = p.curcol;
|
||||
advance(p); // past `if`
|
||||
advance(p);
|
||||
expecttok(p, tkind.TK_LPAREN, "expected '(' after if");
|
||||
let n = newnode(nkind.N_IF, pf, pl, pc);
|
||||
n.cond = parseexpr(p);
|
||||
@@ -138,7 +138,7 @@ fn parsefor(p: *parser) *node = {
|
||||
let pf = p.curfile;
|
||||
let pl = p.curline;
|
||||
let pc = p.curcol;
|
||||
advance(p); // past `for`
|
||||
advance(p);
|
||||
|
||||
// Go's bare `for { }` — no header at all (cmd/wcc/parse.c:1023;
|
||||
// Go's for has exactly three forms and this is the empty one).
|
||||
@@ -172,9 +172,8 @@ fn parsefor(p: *parser) *node = {
|
||||
// Range and 3-clause both lead with `let`, so we commit to consuming
|
||||
// `let` then disambiguate by looking at what follows.
|
||||
if (p.curkind == tkind.TK_LET) {
|
||||
advance(p); // past `let`
|
||||
advance(p);
|
||||
|
||||
// Tuple destructure: `for (let (a, b) .. expr)`.
|
||||
if (p.curkind == tkind.TK_LPAREN) {
|
||||
advance(p);
|
||||
let names: *node = nil;
|
||||
@@ -215,7 +214,7 @@ fn parsefor(p: *parser) *node = {
|
||||
let lpf = p.curfile;
|
||||
let lpl = p.curline;
|
||||
let lpc = p.curcol;
|
||||
advance(p); // consume IDENT/UNDER
|
||||
advance(p);
|
||||
|
||||
if (p.curkind == tkind.TK_DOTDOT) {
|
||||
advance(p);
|
||||
@@ -277,7 +276,7 @@ fn parseswitch(p: *parser) *node = {
|
||||
let pf = p.curfile;
|
||||
let pl = p.curline;
|
||||
let pc = p.curcol;
|
||||
advance(p); // past `switch`
|
||||
advance(p);
|
||||
expecttok(p, tkind.TK_LPAREN, "expected '(' after switch");
|
||||
let n = newnode(nkind.N_SWITCH, pf, pl, pc);
|
||||
n.lhs = parseexpr(p);
|
||||
@@ -289,7 +288,7 @@ fn parseswitch(p: *parser) *node = {
|
||||
let cpf = p.curfile;
|
||||
let cpl = p.curline;
|
||||
let cpc = p.curcol;
|
||||
advance(p); // past `case`
|
||||
advance(p);
|
||||
let cs = newnode(nkind.N_CASE, cpf, cpl, cpc);
|
||||
let eh: *node = nil;
|
||||
let et: *node = nil;
|
||||
@@ -437,4 +436,3 @@ fn parsestmt(p: *parser) *node = {
|
||||
expecttok(p, tkind.TK_SEMI, "expected ';' after expression statement");
|
||||
return n;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
// lib/ww/syntax/sym.ww — port of cmd/wcc/sym.c.
|
||||
// Port of cmd/wcc/sym.c.
|
||||
//
|
||||
// Per-scope hashtable, chained to the parent. Lookup walks up.
|
||||
// Plan 9 / Hare flavoured. Duplicate definitions in the same scope
|
||||
// return nil; the caller flags the error.
|
||||
// Duplicate definitions in the same scope return nil; the caller
|
||||
// flags the error.
|
||||
|
||||
package syntax;
|
||||
|
||||
@@ -103,11 +102,8 @@ export fn scopelookup(s: *scope, name: str) *sym = {
|
||||
return nil;
|
||||
};
|
||||
|
||||
// scopelookuptype — find an SK_TYPE entry by name, same-module preferred.
|
||||
//
|
||||
// Same FNV bucket + hashnext chain + parent walk as scopelookup, with
|
||||
// an `skind == SK_TYPE` filter. Used to disambiguate the bare-TNAME
|
||||
// vs imported-module-bareword collision: when scopelookup returns the
|
||||
// Disambiguates the bare-TNAME vs imported-module-bareword
|
||||
// collision: when scopelookup returns the
|
||||
// SK_USE sym for a leaf that ALSO names a type (a same-name `import X;`
|
||||
// SK_USE shadowing a struct X declared in another module), the resolver
|
||||
// needs the type entry — the struct's mod may differ from the leaf so
|
||||
@@ -151,10 +147,7 @@ export fn scopelookuptype(s: *scope, mod: str, name: str) *sym = {
|
||||
return nil;
|
||||
};
|
||||
|
||||
// scopelookupuselocal — find a same-leaf SK_USE entry within ONE scope.
|
||||
//
|
||||
// Same FNV bucket + hashnext chain as scopelookuplocal, with a
|
||||
// `skind == SK_USE` filter and NO parent walk. The dot-lhs twin of
|
||||
// The dot-lhs twin of
|
||||
// scopelookuptype: when a `use mod;` and a colliding top-level
|
||||
// `fn mod` / `type mod` of the same leaf coexist (random.random,
|
||||
// fnmatch.fnmatch), the mod-preferring scopelookupprefer returns the
|
||||
@@ -198,12 +191,9 @@ export fn scopelookupuselocal(s: *scope, name: str) *sym = {
|
||||
return nil;
|
||||
};
|
||||
|
||||
// scopelookupinmodule — module-filtered chain walk.
|
||||
//
|
||||
// Same FNV bucket + hashnext chain + parent walk as scopelookup, plus
|
||||
// a `b.mod.len > 0 && streq(b.mod, mod)` filter. When `mod` is empty
|
||||
// we fall back to unfiltered scopelookup semantics, so callers that
|
||||
// don't care about disambiguation get the default.
|
||||
// When `mod` is empty we fall back to unfiltered scopelookup
|
||||
// semantics, so callers that don't care about disambiguation get the
|
||||
// default.
|
||||
//
|
||||
// Used by the dot-prefixed type-name lookup in selfhost/cmd/wcc/
|
||||
// check.ww to pick the right same-leaf-name type when two imports
|
||||
@@ -229,10 +219,7 @@ export fn scopelookupinmodule(s: *scope, mod: str, name: str) *sym = {
|
||||
return nil;
|
||||
};
|
||||
|
||||
// scopelookupprefer — bare-leaf lookup with same-module preference.
|
||||
//
|
||||
// Walks the same FNV bucket + hashnext chain + parent walk scopelookup
|
||||
// uses. Within each scope's bucket: Pass 1 prefers entries whose
|
||||
// Within each scope's bucket: Pass 1 prefers entries whose
|
||||
// `sym.mod` matches `mod`; Pass 2 falls back to the first match
|
||||
// regardless of mod (same semantics as scopelookup). We only descend
|
||||
// to the parent scope when the current scope has no matching entry at
|
||||
@@ -276,8 +263,6 @@ export fn scopedefine(s: *scope, name: str, k: skind, t: *tinfo, decl: *node) *s
|
||||
return scopedefineinmodule(s, name, empty, k, t, decl);
|
||||
};
|
||||
|
||||
// scopedefineinmodule — bucket insert with per-mod dedup.
|
||||
//
|
||||
// Same insertion as scopedefine, but the duplicate-rejection key is
|
||||
// (name, mod) rather than name alone. This lets two imports each
|
||||
// register their own `stream` SK_TYPE in the flat scope, and lets the
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
// symtest — behavior pin for [[newscope]]/[[scopedefine]]/[[scopelookup]]
|
||||
// Behavior pin for [[newscope]]/[[scopedefine]]/[[scopelookup]]
|
||||
// (hashtable scope semantics: define, same-scope duplicate reject,
|
||||
// kind-preserving lookup, not-found nil). Run with
|
||||
// `ww test -I lib/ww lib/ww/syntax/symtest.ww`.
|
||||
// kind-preserving lookup, not-found nil).
|
||||
//
|
||||
// Migrated from selfhost/test/sym_link.ww (the 990_selfhost link
|
||||
// probe): the toolchain-link half of that probe is owned by the
|
||||
// fixture corpus' ww-stage cells, so only the scope behavior rows
|
||||
// survive, as in-language rows. `package main` + bare `import syntax`
|
||||
// mirrors toktest/asttest.
|
||||
// survive, as in-language rows.
|
||||
|
||||
package syntax_test;
|
||||
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
// lib/ww/syntax/tok.ww — port of cmd/wcc/tok.c plus the Tkind /
|
||||
// Tok / Pos shapes from cmd/wcc/ww.h.
|
||||
// Port of cmd/wcc/tok.c plus the Tkind / Tok / Pos shapes from cmd/wcc/ww.h.
|
||||
//
|
||||
// Token kind values must stay numerically equal to the C side
|
||||
// (rule-6 data-shape mirror of cmd/wcc/ww.h). Reordering this list
|
||||
// shifts the integers and splits the two frontends.
|
||||
//
|
||||
// Bottom of file: tokprint, which emits one token per line in a
|
||||
// format identical to cmd/wcc/tok.c:tokprint().
|
||||
|
||||
package syntax;
|
||||
|
||||
@@ -14,7 +10,6 @@ import os;
|
||||
import strconv;
|
||||
import strings;
|
||||
|
||||
// ---- tkind ------------------------------------------------------------
|
||||
// Mirror of the C `Tkind` enum in cmd/wcc/ww.h. Numeric values are
|
||||
// explicit and must stay in sync with the C side.
|
||||
|
||||
@@ -125,8 +120,6 @@ export type tkind = enum i32 {
|
||||
TK_LAST = 89,
|
||||
};
|
||||
|
||||
// ---- Pos / Tok --------------------------------------------------------
|
||||
//
|
||||
// `pos` is used at error-reporting boundaries; we always pass it via
|
||||
// *pos so the value never gets struct-copied (w6c can't yet copy a
|
||||
// 24-byte struct).
|
||||
@@ -152,8 +145,6 @@ export type tok = struct {
|
||||
tsuffix: str, // typed numeric literal suffix or empty
|
||||
};
|
||||
|
||||
// ---- keyword lookup ---------------------------------------------------
|
||||
|
||||
// keep alphabetised, so kwlookup is easy to read — mirrors the C twin
|
||||
// cmd/wcc/tok.c:18-47. Two parallel arrays, not a [N]kwent array-of-
|
||||
// struct: a str *inside* an aggregate element is the filed #18 follow-up
|
||||
@@ -180,9 +171,7 @@ let kwkinds: [30]tkind = [
|
||||
tkind.TK_VOID, tkind.TK_YIELD,
|
||||
];
|
||||
|
||||
// kwlookup — returns the matching TK_* keyword kind for a byte run,
|
||||
// or tkind.TK_NONE if it's an ordinary identifier. Linear scan over the
|
||||
// table, matching cmd/wcc/tok.c:kwlookup (N=30, no hash).
|
||||
// Linear scan over the table, matching cmd/wcc/tok.c:kwlookup (N=30, no hash).
|
||||
export fn kwlookup(p: *u8, n: i32) tkind = {
|
||||
let cand: str;
|
||||
cand.ptr = p;
|
||||
@@ -197,10 +186,7 @@ export fn kwlookup(p: *u8, n: i32) tkind = {
|
||||
return tkind.TK_NONE;
|
||||
};
|
||||
|
||||
// ---- tokname ----------------------------------------------------------
|
||||
//
|
||||
// Returns the canonical printable spelling for a token kind. Matches
|
||||
// the C tokname()'s output exactly so wwdump output diffs cleanly.
|
||||
// Matches the C tokname()'s output exactly so wwdump output diffs cleanly.
|
||||
|
||||
export fn tokname(k: tkind) str = {
|
||||
switch (k) {
|
||||
@@ -306,8 +292,6 @@ export fn tokname(k: tkind) str = {
|
||||
return "<?>";
|
||||
};
|
||||
|
||||
// ---- writer for tokprint ----------------------------------------------
|
||||
//
|
||||
// fputq mirrors cmd/wcc/tok.c:fputq — quote the string with C-style
|
||||
// escapes for \, ", \n, \t, \r and \xNN for other non-printables.
|
||||
|
||||
@@ -358,8 +342,8 @@ fn fputq(fd: i32, p: *u8, n: i32) void = {
|
||||
fputcbyte(fd, '"');
|
||||
};
|
||||
|
||||
// tokprint — write one token line to fd. Format must match
|
||||
// cmd/wcc/tok.c:tokprint() byte-for-byte: that's the diff anchor.
|
||||
// Format must match cmd/wcc/tok.c:tokprint() byte-for-byte: that's
|
||||
// the diff anchor.
|
||||
// "<file>:<line>:<col> <kindname>[ <value>]\n"
|
||||
//
|
||||
// Takes `t` by pointer because w6c can't yet pass a >16-byte struct
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// toktest — functional-equivalence pin for [[tokname]], [[kwlookup]]
|
||||
// Functional-equivalence pin for [[tokname]], [[kwlookup]]
|
||||
// (struct fold S1) and [[tokprint]]/fputq (struct fold S9, the
|
||||
// if-ladder → switch folds in tok.ww).
|
||||
// Run with `ww run -I lib/ww lib/ww/syntax/toktest.ww`.
|
||||
//
|
||||
// tokname is checked against every tkind value (the full ladder the
|
||||
// switch replaced, plus the unknown-kind fallback); kwlookup is
|
||||
@@ -16,8 +15,6 @@
|
||||
// A failing row aborts via the assert/abort builtin (task #5 @test
|
||||
// conversion); per-row exit-code pinpoint is intentionally dropped (the
|
||||
// abort reports the file, not the row; drew-t2-conversion-spec sec.5).
|
||||
// `package main` + bare `import tok/lex` mirrors wwdump (the only other
|
||||
// external lex consumer).
|
||||
|
||||
package syntax_test;
|
||||
|
||||
@@ -205,8 +202,7 @@ fn checkkw(s: str, want: tkind) void = {
|
||||
};
|
||||
};
|
||||
|
||||
// checkprint — tokprint `t` to a freshly-rewound fd, read the bytes
|
||||
// back, and assert they equal `want`. The fd is RDWR; we lseek to 0
|
||||
// The fd is RDWR; we lseek to 0
|
||||
// before each write so earlier (possibly longer) content past want.len
|
||||
// is irrelevant — only want.len bytes from offset 0 are compared.
|
||||
fn checkprint(fd: i32, t: *tok, want: str) void = {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// lib/ww/syntax/typ.ww — port of cmd/wcc/type.c.
|
||||
// Port of cmd/wcc/type.c.
|
||||
//
|
||||
// Status: full structural port. The C version uses module-globals for
|
||||
// The C version uses module-globals for
|
||||
// the primitive types (tyvoid, tyi32, …); ww doesn't have writable
|
||||
// global storage yet, so we bundle the primitives into a `tctx` that
|
||||
// the checker passes around explicitly. typesinit fills the tctx
|
||||
@@ -10,11 +10,6 @@ package syntax;
|
||||
|
||||
import os;
|
||||
|
||||
// ---- TypeKind ---------------------------------------------------------
|
||||
// Numeric values must stay aligned with cmd/wcc/ww.h TypeKind so the
|
||||
// next diff signal (typed-AST printer / cgen) can compare across the
|
||||
// two implementations.
|
||||
|
||||
// Mirror of the C `TypeKind` enum in cmd/wcc/ww.h. Numeric values
|
||||
// are explicit and must stay in sync — the selfhost selfcheck and
|
||||
// typed-AST printers depend on matching numeric layout.
|
||||
@@ -67,8 +62,6 @@ export type tykind = enum i32 {
|
||||
// fabricate a 0-byte slot. Value == U64_MAX.
|
||||
def SIZE_UNDEFINED: u64 = 18446744073709551615;
|
||||
|
||||
// ---- tinfo / tfield / tparam -----------------------------------------
|
||||
|
||||
export type tfield = struct {
|
||||
name: str,
|
||||
type_: *tinfo,
|
||||
@@ -173,8 +166,6 @@ export type tinfocacheent = struct {
|
||||
// scaled up — sym's 16 would give ~340-deep chains here.
|
||||
def NBUCKETS_TINFO: u64 = 8192u64;
|
||||
|
||||
// ---- tctx — the box of primitive types -------------------------------
|
||||
|
||||
export type tctx = struct {
|
||||
tyvoid: *tinfo,
|
||||
tybool: *tinfo,
|
||||
@@ -206,8 +197,6 @@ export type tctx = struct {
|
||||
tinfobuckets: **tinfocacheent, // length NBUCKETS_TINFO; node-ptr hash index
|
||||
};
|
||||
|
||||
// ---- constructors -----------------------------------------------------
|
||||
|
||||
export fn newtype(k: tykind) *tinfo = {
|
||||
let t: *tinfo = alloc(tinfo{kind=k, size=0u64, align=0u64, sub=nil, alen=0u64, fields=nil, params=nil, tupleelems=nil, ret=nil, variadic=0, nullable=0, name="", under=nil, slotsize=0u64, packed=0})!;
|
||||
return t;
|
||||
@@ -357,8 +346,6 @@ export fn tinfocachebind(c: *tctx, key: *node, val: *tinfo) void = {
|
||||
c.tinfobuckets[bi] = e;
|
||||
};
|
||||
|
||||
// ---- predicates -------------------------------------------------------
|
||||
|
||||
export fn typeisint(t: *tinfo) bool = {
|
||||
if (t == nil) { return false; };
|
||||
let k: tykind = t.kind;
|
||||
|
||||
Reference in New Issue
Block a user