From 11e41ecea39362822efd383e16ec54e5121a9be6 Mon Sep 17 00:00:00 2001 From: Hojun-Cho Date: Tue, 2 Jun 2026 22:18:19 +0900 Subject: [PATCH] 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). --- Makefile | 6 +- lib/ww/ast.ww | 146 ++++++++++++++------------- lib/ww/asttest.ww | 110 ++++++++++++++++++++ selfhost/cmd/w6c/main.combined.ww | 146 ++++++++++++++------------- selfhost/cmd/wwdump/main.combined.ww | 146 ++++++++++++++------------- test/wcc/905_nkname_run.c | 57 +++++++++++ 6 files changed, 403 insertions(+), 208 deletions(-) create mode 100644 lib/ww/asttest.ww create mode 100644 test/wcc/905_nkname_run.c diff --git a/Makefile b/Makefile index e5ed3e88..a1e0d740 100644 --- a/Makefile +++ b/Makefile @@ -443,7 +443,7 @@ TESTS = $(BIN)/test_smoke $(BIN)/test_lex $(BIN)/test_parse $(BIN)/test_check \ $(BIN)/test_sort_run \ $(BIN)/test_bufio_run $(BIN)/test_random_run \ $(BIN)/test_asserttyped_gap \ - $(BIN)/test_ascii_run $(BIN)/test_tok_run + $(BIN)/test_ascii_run $(BIN)/test_tok_run $(BIN)/test_nkname_run $(BIN)/test_smoke: test/wcc/000_smoke.c $(LIB)/libwcc.a | $(BIN) $(CC) $(CFLAGS) $(INCS) -o $@ $< -L$(LIB) -lwcc @@ -1512,6 +1512,10 @@ $(BIN)/test_tok_run: test/wcc/904_tok_run.c $(BIN)/ww $(BIN)/w6c \ $(BIN)/w6a $(BIN)/w6l $(LIB)/libwwrt.a | $(BIN) $(CC) $(CFLAGS) -o $@ $< +$(BIN)/test_nkname_run: test/wcc/905_nkname_run.c $(BIN)/ww $(BIN)/w6c \ + $(BIN)/w6a $(BIN)/w6l $(LIB)/libwwrt.a | $(BIN) + $(CC) $(CFLAGS) -o $@ $< + $(BIN)/test_decimal_run: test/wcc/922_decimal_run.c $(BIN)/ww $(BIN)/w6c \ $(BIN)/w6a $(BIN)/w6l $(LIB)/libwwrt.a | $(BIN) $(CC) $(CFLAGS) -o $@ $< diff --git a/lib/ww/ast.ww b/lib/ww/ast.ww index fdd24c27..e6e6ac18 100644 --- a/lib/ww/ast.ww +++ b/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 "?"; }; diff --git a/lib/ww/asttest.ww b/lib/ww/asttest.ww new file mode 100644 index 00000000..8cb4652b --- /dev/null +++ b/lib/ww/asttest.ww @@ -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; +}; diff --git a/selfhost/cmd/w6c/main.combined.ww b/selfhost/cmd/w6c/main.combined.ww index 6b5e66da..12363069 100644 --- a/selfhost/cmd/w6c/main.combined.ww +++ b/selfhost/cmd/w6c/main.combined.ww @@ -7769,75 +7769,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 "?"; }; diff --git a/selfhost/cmd/wwdump/main.combined.ww b/selfhost/cmd/wwdump/main.combined.ww index 33dc8caa..03b105ec 100644 --- a/selfhost/cmd/wwdump/main.combined.ww +++ b/selfhost/cmd/wwdump/main.combined.ww @@ -7769,75 +7769,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 "?"; }; diff --git a/test/wcc/905_nkname_run.c b/test/wcc/905_nkname_run.c new file mode 100644 index 00000000..4f760c0f --- /dev/null +++ b/test/wcc/905_nkname_run.c @@ -0,0 +1,57 @@ +/* + * 905_nkname_run — execute the lib/ww nkname @test fixture under the + * C-side `ww run` driver and assert exit 0. + * + * Same thin-wrapper shape as 904_tok_run / 904_ascii_run: asttest.ww + * carries its own `export fn main()` that drives the @test fn and + * signals which case failed via the exit code. This pins nkname's + * if-ladder -> switch fold (every nkind + the unknown-kind fallback), + * which the 990_selfhost wwdump diff only covers for kinds that appear + * in its corpus. + * + * Unlike 904_tok_run, the fixture imports `ast` (package ww), whose + * printer references tok's tkind/tokname, so the run needs + * `-I lib/ww/lex` to resolve that transitive import. + */ +#include +#include +#include +#include + +static int +runwait(const char *cmd) +{ + int rc = system(cmd); + if (rc == -1) return -1; + if (WIFEXITED(rc)) return WEXITSTATUS(rc); + return 1; +} + +int +main(void) +{ + const char *bin = getenv("BIN"); + if (!bin) bin = "out/bin"; + char absbin[1024]; + if (bin[0] != '/') { + char cwd[1024]; + if (getcwd(cwd, sizeof cwd) == NULL) return 1; + snprintf(absbin, sizeof absbin, "%s/%s", cwd, bin); + bin = absbin; + } + char cwd[1024]; + if (getcwd(cwd, sizeof cwd) == NULL) return 1; + + const char *src = "lib/ww/asttest.ww"; + char path[1024], inc[1024], cmd[3072]; + snprintf(path, sizeof path, "%s/%s", cwd, src); + snprintf(inc, sizeof inc, "%s/lib/ww/lex", cwd); + snprintf(cmd, sizeof cmd, "%s/ww run -I %s %s", bin, inc, path); + int rc = runwait(cmd); + if (rc != 0) { + fprintf(stderr, "nkname_run FAIL: %s exited %d\n", src, rc); + return 1; + } + printf("nkname_run: %s ok\n", src); + return 0; +}