lib/ww/ast: nkname if-ladder -> switch (Wave-2 structural)
Fold the 69-arm `if (k == nkind.N_X) return "..."` ladder in nkname to a single `switch (k)` with the terminal `return "?"` as the fall-past default. The other ast.ww ladders stay: pr()'s kind dispatch is side-effecting (emits output, recurses) and uses ||-grouped multi-kind predicates, not a pure value->value mapping a switch can express. Not byte-id-neutral (if-chain -> switch dispatch changes the asm), so the ladder->switch equivalence is pinned by a new table-driven test: lib/ww/asttest.ww drives nkname over every nkind plus the out-of-band "?" fallback, wired as 905_nkname_run (same `ww run` @test shape as 904_tok_run). The 990_selfhost wwdump diff only covers kinds that appear in its corpus. Regenerates the w6c + wwdump combined.ww amalgamations (nkname region only).
This commit is contained in:
146
lib/ww/ast.ww
146
lib/ww/ast.ww
@@ -150,75 +150,83 @@ export fn newnode(k: nkind, file: str, line: i32, col: i32) *node = {
|
||||
// ---- printer ----------------------------------------------------------
|
||||
|
||||
export fn nkname(k: nkind) str = {
|
||||
if (k == nkind.N_NONE) { return "none"; };
|
||||
if (k == nkind.N_INTLIT) { return "int"; };
|
||||
if (k == nkind.N_FLOATLIT) { return "float"; };
|
||||
if (k == nkind.N_STRLIT) { return "str"; };
|
||||
if (k == nkind.N_RUNELIT) { return "rune"; };
|
||||
if (k == nkind.N_TRUE) { return "true"; };
|
||||
if (k == nkind.N_FALSE) { return "false"; };
|
||||
if (k == nkind.N_NIL) { return "nil"; };
|
||||
if (k == nkind.N_IDENT) { return "id"; };
|
||||
if (k == nkind.N_BIN) { return "bin"; };
|
||||
if (k == nkind.N_UN) { return "un"; };
|
||||
if (k == nkind.N_CALL) { return "call"; };
|
||||
if (k == nkind.N_INDEX) { return "index"; };
|
||||
if (k == nkind.N_DOT) { return "dot"; };
|
||||
if (k == nkind.N_CAST) { return "cast"; };
|
||||
if (k == nkind.N_STRUCTLIT) { return "structlit"; };
|
||||
if (k == nkind.N_ARRLIT) { return "arrlit"; };
|
||||
if (k == nkind.N_FIELD) { return "field"; };
|
||||
if (k == nkind.N_ASSIGN) { return "assign"; };
|
||||
if (k == nkind.N_ALLOC) { return "alloc"; };
|
||||
if (k == nkind.N_FREE) { return "free"; };
|
||||
if (k == nkind.N_RECV) { return "recv"; };
|
||||
if (k == nkind.N_SLICE) { return "slice"; };
|
||||
if (k == nkind.N_SPREAD) { return "spread"; };
|
||||
if (k == nkind.N_BLOCK) { return "block"; };
|
||||
if (k == nkind.N_EXPRSTMT) { return "exprstmt"; };
|
||||
if (k == nkind.N_LET) { return "let"; };
|
||||
if (k == nkind.N_RETURN) { return "return"; };
|
||||
if (k == nkind.N_IF) { return "if"; };
|
||||
if (k == nkind.N_FOR) { return "for"; };
|
||||
if (k == nkind.N_FORRANGE) { return "forrange"; };
|
||||
if (k == nkind.N_DEFER) { return "defer"; };
|
||||
if (k == nkind.N_BREAK) { return "break"; };
|
||||
if (k == nkind.N_CONTINUE) { return "continue"; };
|
||||
if (k == nkind.N_SWITCH) { return "switch"; };
|
||||
if (k == nkind.N_CASE) { return "case"; };
|
||||
if (k == nkind.N_FILE) { return "file"; };
|
||||
if (k == nkind.N_USE) { return "use"; };
|
||||
if (k == nkind.N_DEF) { return "def"; };
|
||||
if (k == nkind.N_TYPEDECL) { return "typedecl"; };
|
||||
if (k == nkind.N_FNDECL) { return "fn"; };
|
||||
if (k == nkind.N_PARAM) { return "param"; };
|
||||
if (k == nkind.N_TNAME) { return "tname"; };
|
||||
if (k == nkind.N_TPTR) { return "tptr"; };
|
||||
if (k == nkind.N_TSLICE) { return "tslice"; };
|
||||
if (k == nkind.N_TARRAY) { return "tarray"; };
|
||||
if (k == nkind.N_TFN) { return "tfn"; };
|
||||
if (k == nkind.N_TSTRUCT) { return "tstruct"; };
|
||||
if (k == nkind.N_TFIELD) { return "tfield"; };
|
||||
if (k == nkind.N_TCHAN) { return "tchan"; };
|
||||
if (k == nkind.N_ATTR) { return "attr"; };
|
||||
if (k == nkind.N_TTUPLE) { return "ttuple"; };
|
||||
if (k == nkind.N_TTAGGED) { return "ttagged"; };
|
||||
if (k == nkind.N_TUPLE) { return "tuple"; };
|
||||
if (k == nkind.N_MATCH) { return "match"; };
|
||||
if (k == nkind.N_MCASE) { return "mcase"; };
|
||||
if (k == nkind.N_TRYPROP) { return "tryprop"; };
|
||||
if (k == nkind.N_TRYUNW) { return "tryunw"; };
|
||||
if (k == nkind.N_MLET) { return "mlet"; };
|
||||
if (k == nkind.N_MASSIGN) { return "massign"; };
|
||||
if (k == nkind.N_TYPETEST) { return "typetest"; };
|
||||
if (k == nkind.N_TYPEASSERT) { return "typeassert"; };
|
||||
if (k == nkind.N_VOIDLIT) { return "voidlit"; };
|
||||
if (k == nkind.N_TBANG) { return "tbang"; };
|
||||
if (k == nkind.N_YIELD) { return "yield"; };
|
||||
if (k == nkind.N_TENUM) { return "tenum"; };
|
||||
if (k == nkind.N_TENUMMEMBER) { return "tenummember"; };
|
||||
if (k == nkind.N_TPARAM) { return "tparam"; };
|
||||
if (k == nkind.N_LAST) { return "last"; };
|
||||
switch (k) {
|
||||
case nkind.N_NONE: return "none";
|
||||
case nkind.N_INTLIT: return "int";
|
||||
case nkind.N_FLOATLIT: return "float";
|
||||
case nkind.N_STRLIT: return "str";
|
||||
case nkind.N_RUNELIT: return "rune";
|
||||
case nkind.N_TRUE: return "true";
|
||||
case nkind.N_FALSE: return "false";
|
||||
case nkind.N_NIL: return "nil";
|
||||
case nkind.N_IDENT: return "id";
|
||||
|
||||
case nkind.N_BIN: return "bin";
|
||||
case nkind.N_UN: return "un";
|
||||
case nkind.N_CALL: return "call";
|
||||
case nkind.N_INDEX: return "index";
|
||||
case nkind.N_DOT: return "dot";
|
||||
case nkind.N_CAST: return "cast";
|
||||
case nkind.N_STRUCTLIT: return "structlit";
|
||||
case nkind.N_ARRLIT: return "arrlit";
|
||||
case nkind.N_FIELD: return "field";
|
||||
case nkind.N_ASSIGN: return "assign";
|
||||
case nkind.N_ALLOC: return "alloc";
|
||||
case nkind.N_FREE: return "free";
|
||||
case nkind.N_RECV: return "recv";
|
||||
case nkind.N_SLICE: return "slice";
|
||||
case nkind.N_SPREAD: return "spread";
|
||||
|
||||
case nkind.N_BLOCK: return "block";
|
||||
case nkind.N_EXPRSTMT: return "exprstmt";
|
||||
case nkind.N_LET: return "let";
|
||||
case nkind.N_RETURN: return "return";
|
||||
case nkind.N_IF: return "if";
|
||||
case nkind.N_FOR: return "for";
|
||||
case nkind.N_FORRANGE: return "forrange";
|
||||
case nkind.N_DEFER: return "defer";
|
||||
case nkind.N_BREAK: return "break";
|
||||
case nkind.N_CONTINUE: return "continue";
|
||||
case nkind.N_SWITCH: return "switch";
|
||||
case nkind.N_CASE: return "case";
|
||||
|
||||
case nkind.N_FILE: return "file";
|
||||
case nkind.N_USE: return "use";
|
||||
case nkind.N_DEF: return "def";
|
||||
case nkind.N_TYPEDECL: return "typedecl";
|
||||
case nkind.N_FNDECL: return "fn";
|
||||
case nkind.N_PARAM: return "param";
|
||||
|
||||
case nkind.N_TNAME: return "tname";
|
||||
case nkind.N_TPTR: return "tptr";
|
||||
case nkind.N_TSLICE: return "tslice";
|
||||
case nkind.N_TARRAY: return "tarray";
|
||||
case nkind.N_TFN: return "tfn";
|
||||
case nkind.N_TSTRUCT: return "tstruct";
|
||||
case nkind.N_TFIELD: return "tfield";
|
||||
case nkind.N_TCHAN: return "tchan";
|
||||
|
||||
case nkind.N_ATTR: return "attr";
|
||||
case nkind.N_TTUPLE: return "ttuple";
|
||||
case nkind.N_TTAGGED: return "ttagged";
|
||||
case nkind.N_TUPLE: return "tuple";
|
||||
case nkind.N_MATCH: return "match";
|
||||
case nkind.N_MCASE: return "mcase";
|
||||
case nkind.N_TRYPROP: return "tryprop";
|
||||
case nkind.N_TRYUNW: return "tryunw";
|
||||
case nkind.N_MLET: return "mlet";
|
||||
case nkind.N_MASSIGN: return "massign";
|
||||
|
||||
case nkind.N_TYPETEST: return "typetest";
|
||||
case nkind.N_TYPEASSERT: return "typeassert";
|
||||
case nkind.N_VOIDLIT: return "voidlit";
|
||||
case nkind.N_TBANG: return "tbang";
|
||||
case nkind.N_YIELD: return "yield";
|
||||
case nkind.N_TENUM: return "tenum";
|
||||
case nkind.N_TENUMMEMBER: return "tenummember";
|
||||
case nkind.N_TPARAM: return "tparam";
|
||||
case nkind.N_LAST: return "last";
|
||||
};
|
||||
return "?";
|
||||
};
|
||||
|
||||
|
||||
110
lib/ww/asttest.ww
Normal file
110
lib/ww/asttest.ww
Normal file
@@ -0,0 +1,110 @@
|
||||
// asttest — functional-equivalence pin for [[nkname]] after the
|
||||
// if-ladder → switch fold (struct fold S2). Run with
|
||||
// `ww run lib/ww/asttest.ww`.
|
||||
//
|
||||
// nkname is checked against every nkind value (the full ladder the
|
||||
// switch replaced) plus the out-of-band fallback ("?"). A non-zero
|
||||
// exit pinpoints the failing row (signalled + 10), same convention as
|
||||
// toktest. `package main` + bare `import ast` mirrors wwdump (the
|
||||
// external astprint consumer).
|
||||
|
||||
package main;
|
||||
|
||||
import os;
|
||||
import ast;
|
||||
|
||||
let signalled: i32 = 0;
|
||||
fn fail() void = { os.exit(signalled + 10); };
|
||||
|
||||
fn checkname(k: nkind, want: str) void = {
|
||||
if (nkname(k) != want) { fail(); };
|
||||
};
|
||||
|
||||
// One row per nkind value — same string the if-ladder returned. The
|
||||
// final row pins the unknown-kind fallback ("?").
|
||||
@test fn nkname_cases() void = {
|
||||
signalled = 100; checkname(nkind.N_NONE, "none");
|
||||
signalled = 101; checkname(nkind.N_INTLIT, "int");
|
||||
signalled = 102; checkname(nkind.N_FLOATLIT, "float");
|
||||
signalled = 103; checkname(nkind.N_STRLIT, "str");
|
||||
signalled = 104; checkname(nkind.N_RUNELIT, "rune");
|
||||
signalled = 105; checkname(nkind.N_TRUE, "true");
|
||||
signalled = 106; checkname(nkind.N_FALSE, "false");
|
||||
signalled = 107; checkname(nkind.N_NIL, "nil");
|
||||
signalled = 108; checkname(nkind.N_IDENT, "id");
|
||||
|
||||
signalled = 109; checkname(nkind.N_BIN, "bin");
|
||||
signalled = 110; checkname(nkind.N_UN, "un");
|
||||
signalled = 111; checkname(nkind.N_CALL, "call");
|
||||
signalled = 112; checkname(nkind.N_INDEX, "index");
|
||||
signalled = 113; checkname(nkind.N_DOT, "dot");
|
||||
signalled = 114; checkname(nkind.N_CAST, "cast");
|
||||
signalled = 115; checkname(nkind.N_STRUCTLIT, "structlit");
|
||||
signalled = 116; checkname(nkind.N_ARRLIT, "arrlit");
|
||||
signalled = 117; checkname(nkind.N_FIELD, "field");
|
||||
signalled = 118; checkname(nkind.N_ASSIGN, "assign");
|
||||
signalled = 119; checkname(nkind.N_ALLOC, "alloc");
|
||||
signalled = 120; checkname(nkind.N_FREE, "free");
|
||||
signalled = 121; checkname(nkind.N_RECV, "recv");
|
||||
signalled = 122; checkname(nkind.N_SLICE, "slice");
|
||||
signalled = 123; checkname(nkind.N_SPREAD, "spread");
|
||||
|
||||
signalled = 124; checkname(nkind.N_BLOCK, "block");
|
||||
signalled = 125; checkname(nkind.N_EXPRSTMT, "exprstmt");
|
||||
signalled = 126; checkname(nkind.N_LET, "let");
|
||||
signalled = 127; checkname(nkind.N_RETURN, "return");
|
||||
signalled = 128; checkname(nkind.N_IF, "if");
|
||||
signalled = 129; checkname(nkind.N_FOR, "for");
|
||||
signalled = 130; checkname(nkind.N_FORRANGE, "forrange");
|
||||
signalled = 131; checkname(nkind.N_DEFER, "defer");
|
||||
signalled = 132; checkname(nkind.N_BREAK, "break");
|
||||
signalled = 133; checkname(nkind.N_CONTINUE, "continue");
|
||||
signalled = 134; checkname(nkind.N_SWITCH, "switch");
|
||||
signalled = 135; checkname(nkind.N_CASE, "case");
|
||||
|
||||
signalled = 136; checkname(nkind.N_FILE, "file");
|
||||
signalled = 137; checkname(nkind.N_USE, "use");
|
||||
signalled = 138; checkname(nkind.N_DEF, "def");
|
||||
signalled = 139; checkname(nkind.N_TYPEDECL, "typedecl");
|
||||
signalled = 140; checkname(nkind.N_FNDECL, "fn");
|
||||
signalled = 141; checkname(nkind.N_PARAM, "param");
|
||||
|
||||
signalled = 142; checkname(nkind.N_TNAME, "tname");
|
||||
signalled = 143; checkname(nkind.N_TPTR, "tptr");
|
||||
signalled = 144; checkname(nkind.N_TSLICE, "tslice");
|
||||
signalled = 145; checkname(nkind.N_TARRAY, "tarray");
|
||||
signalled = 146; checkname(nkind.N_TFN, "tfn");
|
||||
signalled = 147; checkname(nkind.N_TSTRUCT, "tstruct");
|
||||
signalled = 148; checkname(nkind.N_TFIELD, "tfield");
|
||||
signalled = 149; checkname(nkind.N_TCHAN, "tchan");
|
||||
|
||||
signalled = 150; checkname(nkind.N_ATTR, "attr");
|
||||
signalled = 151; checkname(nkind.N_TTUPLE, "ttuple");
|
||||
signalled = 152; checkname(nkind.N_TTAGGED, "ttagged");
|
||||
signalled = 153; checkname(nkind.N_TUPLE, "tuple");
|
||||
signalled = 154; checkname(nkind.N_MATCH, "match");
|
||||
signalled = 155; checkname(nkind.N_MCASE, "mcase");
|
||||
signalled = 156; checkname(nkind.N_TRYPROP, "tryprop");
|
||||
signalled = 157; checkname(nkind.N_TRYUNW, "tryunw");
|
||||
signalled = 158; checkname(nkind.N_MLET, "mlet");
|
||||
signalled = 159; checkname(nkind.N_MASSIGN, "massign");
|
||||
|
||||
signalled = 160; checkname(nkind.N_TYPETEST, "typetest");
|
||||
signalled = 161; checkname(nkind.N_TYPEASSERT, "typeassert");
|
||||
signalled = 162; checkname(nkind.N_VOIDLIT, "voidlit");
|
||||
signalled = 163; checkname(nkind.N_TBANG, "tbang");
|
||||
signalled = 164; checkname(nkind.N_YIELD, "yield");
|
||||
signalled = 165; checkname(nkind.N_TENUM, "tenum");
|
||||
signalled = 166; checkname(nkind.N_TENUMMEMBER, "tenummember");
|
||||
signalled = 167; checkname(nkind.N_TPARAM, "tparam");
|
||||
signalled = 168; checkname(nkind.N_LAST, "last");
|
||||
|
||||
// Unknown kind → the post-switch fallback. N_LAST is the highest
|
||||
// named value (68); 69 is out of band, exercising the "?" tail.
|
||||
signalled = 169; checkname(69: nkind, "?");
|
||||
};
|
||||
|
||||
export fn main() i32 = {
|
||||
signalled = 1; nkname_cases();
|
||||
return 0;
|
||||
};
|
||||
Reference in New Issue
Block a user