diff --git a/Makefile b/Makefile index c3fe4f73..e5ed3e88 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_ascii_run $(BIN)/test_tok_run $(BIN)/test_smoke: test/wcc/000_smoke.c $(LIB)/libwcc.a | $(BIN) $(CC) $(CFLAGS) $(INCS) -o $@ $< -L$(LIB) -lwcc @@ -1508,6 +1508,10 @@ $(BIN)/test_ascii_run: test/wcc/904_ascii_run.c $(BIN)/ww $(BIN)/w6c \ $(BIN)/w6a $(BIN)/w6l $(LIB)/libwwrt.a | $(BIN) $(CC) $(CFLAGS) -o $@ $< +$(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_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/lex/tok.ww b/lib/ww/lex/tok.ww index f8b40bb9..024dbc8a 100644 --- a/lib/ww/lex/tok.ww +++ b/lib/ww/lex/tok.ww @@ -202,102 +202,104 @@ export fn kwlookup(p: *u8, n: i32) tkind = { // the C tokname()'s output exactly so wwdump output diffs cleanly. export fn tokname(k: tkind) str = { - if (k == tkind.TK_NONE) { return ""; }; - if (k == tkind.TK_EOF) { return "EOF"; }; - if (k == tkind.TK_ERR) { return "ERR"; }; - if (k == tkind.TK_IDENT) { return "IDENT"; }; - if (k == tkind.TK_INT) { return "INT"; }; - if (k == tkind.TK_FLOAT) { return "FLOAT"; }; - if (k == tkind.TK_RUNE) { return "RUNE"; }; - if (k == tkind.TK_STR) { return "STR"; }; + switch (k) { + case tkind.TK_NONE: return ""; + case tkind.TK_EOF: return "EOF"; + case tkind.TK_ERR: return "ERR"; + case tkind.TK_IDENT: return "IDENT"; + case tkind.TK_INT: return "INT"; + case tkind.TK_FLOAT: return "FLOAT"; + case tkind.TK_RUNE: return "RUNE"; + case tkind.TK_STR: return "STR"; - if (k == tkind.TK_FN) { return "fn"; }; - if (k == tkind.TK_LET) { return "let"; }; - if (k == tkind.TK_DEF) { return "def"; }; - if (k == tkind.TK_IF) { return "if"; }; - if (k == tkind.TK_ELSE) { return "else"; }; - if (k == tkind.TK_FOR) { return "for"; }; - if (k == tkind.TK_SWITCH) { return "switch"; }; - if (k == tkind.TK_CASE) { return "case"; }; - if (k == tkind.TK_RETURN) { return "return"; }; - if (k == tkind.TK_USE) { return "import"; }; - if (k == tkind.TK_TYPE) { return "type"; }; - if (k == tkind.TK_STRUCT) { return "struct"; }; - if (k == tkind.TK_DEFER) { return "defer"; }; - if (k == tkind.TK_BREAK) { return "break"; }; - if (k == tkind.TK_CONTINUE) { return "continue"; }; - if (k == tkind.TK_EXPORT) { return "export"; }; - if (k == tkind.TK_PROC) { return "proc"; }; - if (k == tkind.TK_CHAN) { return "chan"; }; - if (k == tkind.TK_NIL) { return "nil"; }; - if (k == tkind.TK_TRUE) { return "true"; }; - if (k == tkind.TK_FALSE) { return "false"; }; - if (k == tkind.TK_AS) { return "as"; }; - if (k == tkind.TK_IS) { return "is"; }; - if (k == tkind.TK_VOID) { return "void"; }; - if (k == tkind.TK_YIELD) { return "yield"; }; - if (k == tkind.TK_STATIC) { return "static"; }; - if (k == tkind.TK_MATCH) { return "match"; }; - if (k == tkind.TK_CONST) { return "const"; }; - if (k == tkind.TK_UNDER) { return "_"; }; - if (k == tkind.TK_ENUM) { return "enum"; }; - if (k == tkind.TK_MODULE) { return "package"; }; + case tkind.TK_FN: return "fn"; + case tkind.TK_LET: return "let"; + case tkind.TK_DEF: return "def"; + case tkind.TK_IF: return "if"; + case tkind.TK_ELSE: return "else"; + case tkind.TK_FOR: return "for"; + case tkind.TK_SWITCH: return "switch"; + case tkind.TK_CASE: return "case"; + case tkind.TK_RETURN: return "return"; + case tkind.TK_USE: return "import"; + case tkind.TK_TYPE: return "type"; + case tkind.TK_STRUCT: return "struct"; + case tkind.TK_DEFER: return "defer"; + case tkind.TK_BREAK: return "break"; + case tkind.TK_CONTINUE: return "continue"; + case tkind.TK_EXPORT: return "export"; + case tkind.TK_PROC: return "proc"; + case tkind.TK_CHAN: return "chan"; + case tkind.TK_NIL: return "nil"; + case tkind.TK_TRUE: return "true"; + case tkind.TK_FALSE: return "false"; + case tkind.TK_AS: return "as"; + case tkind.TK_IS: return "is"; + case tkind.TK_VOID: return "void"; + case tkind.TK_YIELD: return "yield"; + case tkind.TK_STATIC: return "static"; + case tkind.TK_MATCH: return "match"; + case tkind.TK_CONST: return "const"; + case tkind.TK_UNDER: return "_"; + case tkind.TK_ENUM: return "enum"; + case tkind.TK_MODULE: return "package"; - if (k == tkind.TK_LPAREN) { return "("; }; - if (k == tkind.TK_RPAREN) { return ")"; }; - if (k == tkind.TK_LBRACE) { return "{"; }; - if (k == tkind.TK_RBRACE) { return "}"; }; - if (k == tkind.TK_LBRACK) { return "["; }; - if (k == tkind.TK_RBRACK) { return "]"; }; - if (k == tkind.TK_COMMA) { return ","; }; - if (k == tkind.TK_SEMI) { return ";"; }; - if (k == tkind.TK_COLON) { return ":"; }; - if (k == tkind.TK_DOT) { return "."; }; - if (k == tkind.TK_ELLIPSIS) { return "..."; }; - if (k == tkind.TK_DOTDOT) { return ".."; }; - if (k == tkind.TK_AT) { return "@"; }; - if (k == tkind.TK_QUESTION) { return "?"; }; + case tkind.TK_LPAREN: return "("; + case tkind.TK_RPAREN: return ")"; + case tkind.TK_LBRACE: return "{"; + case tkind.TK_RBRACE: return "}"; + case tkind.TK_LBRACK: return "["; + case tkind.TK_RBRACK: return "]"; + case tkind.TK_COMMA: return ","; + case tkind.TK_SEMI: return ";"; + case tkind.TK_COLON: return ":"; + case tkind.TK_DOT: return "."; + case tkind.TK_ELLIPSIS: return "..."; + case tkind.TK_DOTDOT: return ".."; + case tkind.TK_AT: return "@"; + case tkind.TK_QUESTION: return "?"; - if (k == tkind.TK_ASSIGN) { return "="; }; - if (k == tkind.TK_PLUSEQ) { return "+="; }; - if (k == tkind.TK_MINUSEQ) { return "-="; }; - if (k == tkind.TK_STAREQ) { return "*="; }; - if (k == tkind.TK_SLASHEQ) { return "/="; }; - if (k == tkind.TK_PERCENTEQ) { return "%="; }; - if (k == tkind.TK_AMPEQ) { return "&="; }; - if (k == tkind.TK_PIPEEQ) { return "|="; }; - if (k == tkind.TK_CARETEQ) { return "^="; }; - if (k == tkind.TK_LSHIFTEQ) { return "<<="; }; - if (k == tkind.TK_RSHIFTEQ) { return ">>="; }; + case tkind.TK_ASSIGN: return "="; + case tkind.TK_PLUSEQ: return "+="; + case tkind.TK_MINUSEQ: return "-="; + case tkind.TK_STAREQ: return "*="; + case tkind.TK_SLASHEQ: return "/="; + case tkind.TK_PERCENTEQ: return "%="; + case tkind.TK_AMPEQ: return "&="; + case tkind.TK_PIPEEQ: return "|="; + case tkind.TK_CARETEQ: return "^="; + case tkind.TK_LSHIFTEQ: return "<<="; + case tkind.TK_RSHIFTEQ: return ">>="; - if (k == tkind.TK_PLUS) { return "+"; }; - if (k == tkind.TK_MINUS) { return "-"; }; - if (k == tkind.TK_STAR) { return "*"; }; - if (k == tkind.TK_SLASH) { return "/"; }; - if (k == tkind.TK_PERCENT) { return "%"; }; - if (k == tkind.TK_AMP) { return "&"; }; - if (k == tkind.TK_PIPE) { return "|"; }; - if (k == tkind.TK_CARET) { return "^"; }; - if (k == tkind.TK_TILDE) { return "~"; }; - if (k == tkind.TK_LSHIFT) { return "<<"; }; - if (k == tkind.TK_RSHIFT) { return ">>"; }; + case tkind.TK_PLUS: return "+"; + case tkind.TK_MINUS: return "-"; + case tkind.TK_STAR: return "*"; + case tkind.TK_SLASH: return "/"; + case tkind.TK_PERCENT: return "%"; + case tkind.TK_AMP: return "&"; + case tkind.TK_PIPE: return "|"; + case tkind.TK_CARET: return "^"; + case tkind.TK_TILDE: return "~"; + case tkind.TK_LSHIFT: return "<<"; + case tkind.TK_RSHIFT: return ">>"; - if (k == tkind.TK_EQ) { return "=="; }; - if (k == tkind.TK_NEQ) { return "!="; }; - if (k == tkind.TK_LT) { return "<"; }; - if (k == tkind.TK_LE) { return "<="; }; - if (k == tkind.TK_GT) { return ">"; }; - if (k == tkind.TK_GE) { return ">="; }; + case tkind.TK_EQ: return "=="; + case tkind.TK_NEQ: return "!="; + case tkind.TK_LT: return "<"; + case tkind.TK_LE: return "<="; + case tkind.TK_GT: return ">"; + case tkind.TK_GE: return ">="; - if (k == tkind.TK_AND) { return "&&"; }; - if (k == tkind.TK_OR) { return "||"; }; - if (k == tkind.TK_NOT) { return "!"; }; + case tkind.TK_AND: return "&&"; + case tkind.TK_OR: return "||"; + case tkind.TK_NOT: return "!"; - if (k == tkind.TK_LARROW) { return "<-"; }; - if (k == tkind.TK_ARROW) { return "->"; }; - if (k == tkind.TK_FATARROW) { return "=>"; }; + case tkind.TK_LARROW: return "<-"; + case tkind.TK_ARROW: return "->"; + case tkind.TK_FATARROW: return "=>"; - if (k == tkind.TK_LAST) { return ""; }; + case tkind.TK_LAST: return ""; + }; return ""; }; diff --git a/lib/ww/lex/toktest.ww b/lib/ww/lex/toktest.ww new file mode 100644 index 00000000..55ce77f8 --- /dev/null +++ b/lib/ww/lex/toktest.ww @@ -0,0 +1,178 @@ +// toktest — functional-equivalence pin for [[tokname]] and +// [[kwlookup]] after the if-ladder → switch fold (struct fold S1). +// Run with `ww run -I lib/ww/lex lib/ww/lex/toktest.ww`. +// +// tokname is checked against every tkind value (the full ladder the +// switch replaced, plus the unknown-kind fallback); kwlookup is +// checked against every keyword it recognises plus a non-keyword. +// A non-zero exit pinpoints the failing row (signalled + 10), same +// convention as asciitest. `package main` + bare `import tok/lex` +// mirrors wwdump (the only other external lex consumer). + +package main; + +import os; +import tok; +import lex; + +let signalled: i32 = 0; +fn fail() void = { os.exit(signalled + 10); }; + +fn checkname(k: tkind, want: str) void = { + if (tokname(k) != want) { fail(); }; +}; + +// One row per tkind value — same string the if-ladder returned. The +// final row pins the unknown-kind fallback (""). +@test fn tokname_cases() void = { + signalled = 100; checkname(tkind.TK_NONE, ""); + signalled = 101; checkname(tkind.TK_EOF, "EOF"); + signalled = 102; checkname(tkind.TK_ERR, "ERR"); + signalled = 103; checkname(tkind.TK_IDENT, "IDENT"); + signalled = 104; checkname(tkind.TK_INT, "INT"); + signalled = 105; checkname(tkind.TK_FLOAT, "FLOAT"); + signalled = 106; checkname(tkind.TK_RUNE, "RUNE"); + signalled = 107; checkname(tkind.TK_STR, "STR"); + + signalled = 108; checkname(tkind.TK_FN, "fn"); + signalled = 109; checkname(tkind.TK_LET, "let"); + signalled = 110; checkname(tkind.TK_DEF, "def"); + signalled = 111; checkname(tkind.TK_IF, "if"); + signalled = 112; checkname(tkind.TK_ELSE, "else"); + signalled = 113; checkname(tkind.TK_FOR, "for"); + signalled = 114; checkname(tkind.TK_SWITCH, "switch"); + signalled = 115; checkname(tkind.TK_CASE, "case"); + signalled = 116; checkname(tkind.TK_RETURN, "return"); + signalled = 117; checkname(tkind.TK_USE, "import"); + signalled = 118; checkname(tkind.TK_TYPE, "type"); + signalled = 119; checkname(tkind.TK_STRUCT, "struct"); + signalled = 120; checkname(tkind.TK_DEFER, "defer"); + signalled = 121; checkname(tkind.TK_BREAK, "break"); + signalled = 122; checkname(tkind.TK_CONTINUE, "continue"); + signalled = 123; checkname(tkind.TK_EXPORT, "export"); + signalled = 124; checkname(tkind.TK_PROC, "proc"); + signalled = 125; checkname(tkind.TK_CHAN, "chan"); + signalled = 126; checkname(tkind.TK_NIL, "nil"); + signalled = 127; checkname(tkind.TK_TRUE, "true"); + signalled = 128; checkname(tkind.TK_FALSE, "false"); + signalled = 129; checkname(tkind.TK_AS, "as"); + signalled = 130; checkname(tkind.TK_IS, "is"); + signalled = 131; checkname(tkind.TK_VOID, "void"); + signalled = 132; checkname(tkind.TK_YIELD, "yield"); + signalled = 133; checkname(tkind.TK_STATIC, "static"); + signalled = 134; checkname(tkind.TK_MATCH, "match"); + signalled = 135; checkname(tkind.TK_CONST, "const"); + signalled = 136; checkname(tkind.TK_UNDER, "_"); + signalled = 137; checkname(tkind.TK_ENUM, "enum"); + signalled = 138; checkname(tkind.TK_MODULE, "package"); + + signalled = 139; checkname(tkind.TK_LPAREN, "("); + signalled = 140; checkname(tkind.TK_RPAREN, ")"); + signalled = 141; checkname(tkind.TK_LBRACE, "{"); + signalled = 142; checkname(tkind.TK_RBRACE, "}"); + signalled = 143; checkname(tkind.TK_LBRACK, "["); + signalled = 144; checkname(tkind.TK_RBRACK, "]"); + signalled = 145; checkname(tkind.TK_COMMA, ","); + signalled = 146; checkname(tkind.TK_SEMI, ";"); + signalled = 147; checkname(tkind.TK_COLON, ":"); + signalled = 148; checkname(tkind.TK_DOT, "."); + signalled = 149; checkname(tkind.TK_ELLIPSIS, "..."); + signalled = 150; checkname(tkind.TK_DOTDOT, ".."); + signalled = 151; checkname(tkind.TK_AT, "@"); + signalled = 152; checkname(tkind.TK_QUESTION, "?"); + + signalled = 153; checkname(tkind.TK_ASSIGN, "="); + signalled = 154; checkname(tkind.TK_PLUSEQ, "+="); + signalled = 155; checkname(tkind.TK_MINUSEQ, "-="); + signalled = 156; checkname(tkind.TK_STAREQ, "*="); + signalled = 157; checkname(tkind.TK_SLASHEQ, "/="); + signalled = 158; checkname(tkind.TK_PERCENTEQ, "%="); + signalled = 159; checkname(tkind.TK_AMPEQ, "&="); + signalled = 160; checkname(tkind.TK_PIPEEQ, "|="); + signalled = 161; checkname(tkind.TK_CARETEQ, "^="); + signalled = 162; checkname(tkind.TK_LSHIFTEQ, "<<="); + signalled = 163; checkname(tkind.TK_RSHIFTEQ, ">>="); + + signalled = 164; checkname(tkind.TK_PLUS, "+"); + signalled = 165; checkname(tkind.TK_MINUS, "-"); + signalled = 166; checkname(tkind.TK_STAR, "*"); + signalled = 167; checkname(tkind.TK_SLASH, "/"); + signalled = 168; checkname(tkind.TK_PERCENT, "%"); + signalled = 169; checkname(tkind.TK_AMP, "&"); + signalled = 170; checkname(tkind.TK_PIPE, "|"); + signalled = 171; checkname(tkind.TK_CARET, "^"); + signalled = 172; checkname(tkind.TK_TILDE, "~"); + signalled = 173; checkname(tkind.TK_LSHIFT, "<<"); + signalled = 174; checkname(tkind.TK_RSHIFT, ">>"); + + signalled = 175; checkname(tkind.TK_EQ, "=="); + signalled = 176; checkname(tkind.TK_NEQ, "!="); + signalled = 177; checkname(tkind.TK_LT, "<"); + signalled = 178; checkname(tkind.TK_LE, "<="); + signalled = 179; checkname(tkind.TK_GT, ">"); + signalled = 180; checkname(tkind.TK_GE, ">="); + + signalled = 181; checkname(tkind.TK_AND, "&&"); + signalled = 182; checkname(tkind.TK_OR, "||"); + signalled = 183; checkname(tkind.TK_NOT, "!"); + + signalled = 184; checkname(tkind.TK_LARROW, "<-"); + signalled = 185; checkname(tkind.TK_ARROW, "->"); + signalled = 186; checkname(tkind.TK_FATARROW, "=>"); + + signalled = 187; checkname(tkind.TK_LAST, ""); + + // Unknown kind → the post-switch fallback. TK_LAST is the highest + // named value (87); 88 is out of band, exercising the "" tail. + signalled = 188; checkname(88: tkind, ""); +}; + +fn checkkw(s: str, want: tkind) void = { + if (kwlookup(s.ptr, s.len) != want) { fail(); }; +}; + +// Every keyword kwlookup recognises (mirrors the streqn ladder), plus +// non-keywords that must fall through to TK_NONE. +@test fn kwlookup_cases() void = { + signalled = 200; checkkw("as", tkind.TK_AS); + signalled = 201; checkkw("break", tkind.TK_BREAK); + signalled = 202; checkkw("case", tkind.TK_CASE); + signalled = 203; checkkw("chan", tkind.TK_CHAN); + signalled = 204; checkkw("const", tkind.TK_CONST); + signalled = 205; checkkw("continue", tkind.TK_CONTINUE); + signalled = 206; checkkw("def", tkind.TK_DEF); + signalled = 207; checkkw("defer", tkind.TK_DEFER); + signalled = 208; checkkw("else", tkind.TK_ELSE); + signalled = 209; checkkw("enum", tkind.TK_ENUM); + signalled = 210; checkkw("export", tkind.TK_EXPORT); + signalled = 211; checkkw("false", tkind.TK_FALSE); + signalled = 212; checkkw("fn", tkind.TK_FN); + signalled = 213; checkkw("for", tkind.TK_FOR); + signalled = 214; checkkw("if", tkind.TK_IF); + signalled = 215; checkkw("is", tkind.TK_IS); + signalled = 216; checkkw("let", tkind.TK_LET); + signalled = 217; checkkw("import", tkind.TK_USE); + signalled = 218; checkkw("match", tkind.TK_MATCH); + signalled = 219; checkkw("nil", tkind.TK_NIL); + signalled = 220; checkkw("package", tkind.TK_MODULE); + signalled = 221; checkkw("proc", tkind.TK_PROC); + signalled = 222; checkkw("return", tkind.TK_RETURN); + signalled = 223; checkkw("static", tkind.TK_STATIC); + signalled = 224; checkkw("struct", tkind.TK_STRUCT); + signalled = 225; checkkw("switch", tkind.TK_SWITCH); + signalled = 226; checkkw("true", tkind.TK_TRUE); + signalled = 227; checkkw("type", tkind.TK_TYPE); + signalled = 228; checkkw("void", tkind.TK_VOID); + signalled = 229; checkkw("yield", tkind.TK_YIELD); + + // Non-keywords fall through to TK_NONE — an ordinary identifier and + // a near-miss prefix of a real keyword. + signalled = 230; checkkw("xyzzy", tkind.TK_NONE); + signalled = 231; checkkw("fns", tkind.TK_NONE); +}; + +export fn main() i32 = { + signalled = 1; tokname_cases(); + signalled = 2; kwlookup_cases(); + return 0; +}; diff --git a/selfhost/cmd/w6c/main.combined.ww b/selfhost/cmd/w6c/main.combined.ww index f48bfbcf..6b5e66da 100644 --- a/selfhost/cmd/w6c/main.combined.ww +++ b/selfhost/cmd/w6c/main.combined.ww @@ -6579,102 +6579,104 @@ export fn kwlookup(p: *u8, n: i32) tkind = { // the C tokname()'s output exactly so wwdump output diffs cleanly. export fn tokname(k: tkind) str = { - if (k == tkind.TK_NONE) { return ""; }; - if (k == tkind.TK_EOF) { return "EOF"; }; - if (k == tkind.TK_ERR) { return "ERR"; }; - if (k == tkind.TK_IDENT) { return "IDENT"; }; - if (k == tkind.TK_INT) { return "INT"; }; - if (k == tkind.TK_FLOAT) { return "FLOAT"; }; - if (k == tkind.TK_RUNE) { return "RUNE"; }; - if (k == tkind.TK_STR) { return "STR"; }; + switch (k) { + case tkind.TK_NONE: return ""; + case tkind.TK_EOF: return "EOF"; + case tkind.TK_ERR: return "ERR"; + case tkind.TK_IDENT: return "IDENT"; + case tkind.TK_INT: return "INT"; + case tkind.TK_FLOAT: return "FLOAT"; + case tkind.TK_RUNE: return "RUNE"; + case tkind.TK_STR: return "STR"; - if (k == tkind.TK_FN) { return "fn"; }; - if (k == tkind.TK_LET) { return "let"; }; - if (k == tkind.TK_DEF) { return "def"; }; - if (k == tkind.TK_IF) { return "if"; }; - if (k == tkind.TK_ELSE) { return "else"; }; - if (k == tkind.TK_FOR) { return "for"; }; - if (k == tkind.TK_SWITCH) { return "switch"; }; - if (k == tkind.TK_CASE) { return "case"; }; - if (k == tkind.TK_RETURN) { return "return"; }; - if (k == tkind.TK_USE) { return "import"; }; - if (k == tkind.TK_TYPE) { return "type"; }; - if (k == tkind.TK_STRUCT) { return "struct"; }; - if (k == tkind.TK_DEFER) { return "defer"; }; - if (k == tkind.TK_BREAK) { return "break"; }; - if (k == tkind.TK_CONTINUE) { return "continue"; }; - if (k == tkind.TK_EXPORT) { return "export"; }; - if (k == tkind.TK_PROC) { return "proc"; }; - if (k == tkind.TK_CHAN) { return "chan"; }; - if (k == tkind.TK_NIL) { return "nil"; }; - if (k == tkind.TK_TRUE) { return "true"; }; - if (k == tkind.TK_FALSE) { return "false"; }; - if (k == tkind.TK_AS) { return "as"; }; - if (k == tkind.TK_IS) { return "is"; }; - if (k == tkind.TK_VOID) { return "void"; }; - if (k == tkind.TK_YIELD) { return "yield"; }; - if (k == tkind.TK_STATIC) { return "static"; }; - if (k == tkind.TK_MATCH) { return "match"; }; - if (k == tkind.TK_CONST) { return "const"; }; - if (k == tkind.TK_UNDER) { return "_"; }; - if (k == tkind.TK_ENUM) { return "enum"; }; - if (k == tkind.TK_MODULE) { return "package"; }; + case tkind.TK_FN: return "fn"; + case tkind.TK_LET: return "let"; + case tkind.TK_DEF: return "def"; + case tkind.TK_IF: return "if"; + case tkind.TK_ELSE: return "else"; + case tkind.TK_FOR: return "for"; + case tkind.TK_SWITCH: return "switch"; + case tkind.TK_CASE: return "case"; + case tkind.TK_RETURN: return "return"; + case tkind.TK_USE: return "import"; + case tkind.TK_TYPE: return "type"; + case tkind.TK_STRUCT: return "struct"; + case tkind.TK_DEFER: return "defer"; + case tkind.TK_BREAK: return "break"; + case tkind.TK_CONTINUE: return "continue"; + case tkind.TK_EXPORT: return "export"; + case tkind.TK_PROC: return "proc"; + case tkind.TK_CHAN: return "chan"; + case tkind.TK_NIL: return "nil"; + case tkind.TK_TRUE: return "true"; + case tkind.TK_FALSE: return "false"; + case tkind.TK_AS: return "as"; + case tkind.TK_IS: return "is"; + case tkind.TK_VOID: return "void"; + case tkind.TK_YIELD: return "yield"; + case tkind.TK_STATIC: return "static"; + case tkind.TK_MATCH: return "match"; + case tkind.TK_CONST: return "const"; + case tkind.TK_UNDER: return "_"; + case tkind.TK_ENUM: return "enum"; + case tkind.TK_MODULE: return "package"; - if (k == tkind.TK_LPAREN) { return "("; }; - if (k == tkind.TK_RPAREN) { return ")"; }; - if (k == tkind.TK_LBRACE) { return "{"; }; - if (k == tkind.TK_RBRACE) { return "}"; }; - if (k == tkind.TK_LBRACK) { return "["; }; - if (k == tkind.TK_RBRACK) { return "]"; }; - if (k == tkind.TK_COMMA) { return ","; }; - if (k == tkind.TK_SEMI) { return ";"; }; - if (k == tkind.TK_COLON) { return ":"; }; - if (k == tkind.TK_DOT) { return "."; }; - if (k == tkind.TK_ELLIPSIS) { return "..."; }; - if (k == tkind.TK_DOTDOT) { return ".."; }; - if (k == tkind.TK_AT) { return "@"; }; - if (k == tkind.TK_QUESTION) { return "?"; }; + case tkind.TK_LPAREN: return "("; + case tkind.TK_RPAREN: return ")"; + case tkind.TK_LBRACE: return "{"; + case tkind.TK_RBRACE: return "}"; + case tkind.TK_LBRACK: return "["; + case tkind.TK_RBRACK: return "]"; + case tkind.TK_COMMA: return ","; + case tkind.TK_SEMI: return ";"; + case tkind.TK_COLON: return ":"; + case tkind.TK_DOT: return "."; + case tkind.TK_ELLIPSIS: return "..."; + case tkind.TK_DOTDOT: return ".."; + case tkind.TK_AT: return "@"; + case tkind.TK_QUESTION: return "?"; - if (k == tkind.TK_ASSIGN) { return "="; }; - if (k == tkind.TK_PLUSEQ) { return "+="; }; - if (k == tkind.TK_MINUSEQ) { return "-="; }; - if (k == tkind.TK_STAREQ) { return "*="; }; - if (k == tkind.TK_SLASHEQ) { return "/="; }; - if (k == tkind.TK_PERCENTEQ) { return "%="; }; - if (k == tkind.TK_AMPEQ) { return "&="; }; - if (k == tkind.TK_PIPEEQ) { return "|="; }; - if (k == tkind.TK_CARETEQ) { return "^="; }; - if (k == tkind.TK_LSHIFTEQ) { return "<<="; }; - if (k == tkind.TK_RSHIFTEQ) { return ">>="; }; + case tkind.TK_ASSIGN: return "="; + case tkind.TK_PLUSEQ: return "+="; + case tkind.TK_MINUSEQ: return "-="; + case tkind.TK_STAREQ: return "*="; + case tkind.TK_SLASHEQ: return "/="; + case tkind.TK_PERCENTEQ: return "%="; + case tkind.TK_AMPEQ: return "&="; + case tkind.TK_PIPEEQ: return "|="; + case tkind.TK_CARETEQ: return "^="; + case tkind.TK_LSHIFTEQ: return "<<="; + case tkind.TK_RSHIFTEQ: return ">>="; - if (k == tkind.TK_PLUS) { return "+"; }; - if (k == tkind.TK_MINUS) { return "-"; }; - if (k == tkind.TK_STAR) { return "*"; }; - if (k == tkind.TK_SLASH) { return "/"; }; - if (k == tkind.TK_PERCENT) { return "%"; }; - if (k == tkind.TK_AMP) { return "&"; }; - if (k == tkind.TK_PIPE) { return "|"; }; - if (k == tkind.TK_CARET) { return "^"; }; - if (k == tkind.TK_TILDE) { return "~"; }; - if (k == tkind.TK_LSHIFT) { return "<<"; }; - if (k == tkind.TK_RSHIFT) { return ">>"; }; + case tkind.TK_PLUS: return "+"; + case tkind.TK_MINUS: return "-"; + case tkind.TK_STAR: return "*"; + case tkind.TK_SLASH: return "/"; + case tkind.TK_PERCENT: return "%"; + case tkind.TK_AMP: return "&"; + case tkind.TK_PIPE: return "|"; + case tkind.TK_CARET: return "^"; + case tkind.TK_TILDE: return "~"; + case tkind.TK_LSHIFT: return "<<"; + case tkind.TK_RSHIFT: return ">>"; - if (k == tkind.TK_EQ) { return "=="; }; - if (k == tkind.TK_NEQ) { return "!="; }; - if (k == tkind.TK_LT) { return "<"; }; - if (k == tkind.TK_LE) { return "<="; }; - if (k == tkind.TK_GT) { return ">"; }; - if (k == tkind.TK_GE) { return ">="; }; + case tkind.TK_EQ: return "=="; + case tkind.TK_NEQ: return "!="; + case tkind.TK_LT: return "<"; + case tkind.TK_LE: return "<="; + case tkind.TK_GT: return ">"; + case tkind.TK_GE: return ">="; - if (k == tkind.TK_AND) { return "&&"; }; - if (k == tkind.TK_OR) { return "||"; }; - if (k == tkind.TK_NOT) { return "!"; }; + case tkind.TK_AND: return "&&"; + case tkind.TK_OR: return "||"; + case tkind.TK_NOT: return "!"; - if (k == tkind.TK_LARROW) { return "<-"; }; - if (k == tkind.TK_ARROW) { return "->"; }; - if (k == tkind.TK_FATARROW) { return "=>"; }; + case tkind.TK_LARROW: return "<-"; + case tkind.TK_ARROW: return "->"; + case tkind.TK_FATARROW: return "=>"; - if (k == tkind.TK_LAST) { return ""; }; + case tkind.TK_LAST: return ""; + }; return ""; }; diff --git a/selfhost/cmd/wwdump/main.combined.ww b/selfhost/cmd/wwdump/main.combined.ww index 20379ff1..33dc8caa 100644 --- a/selfhost/cmd/wwdump/main.combined.ww +++ b/selfhost/cmd/wwdump/main.combined.ww @@ -6579,102 +6579,104 @@ export fn kwlookup(p: *u8, n: i32) tkind = { // the C tokname()'s output exactly so wwdump output diffs cleanly. export fn tokname(k: tkind) str = { - if (k == tkind.TK_NONE) { return ""; }; - if (k == tkind.TK_EOF) { return "EOF"; }; - if (k == tkind.TK_ERR) { return "ERR"; }; - if (k == tkind.TK_IDENT) { return "IDENT"; }; - if (k == tkind.TK_INT) { return "INT"; }; - if (k == tkind.TK_FLOAT) { return "FLOAT"; }; - if (k == tkind.TK_RUNE) { return "RUNE"; }; - if (k == tkind.TK_STR) { return "STR"; }; + switch (k) { + case tkind.TK_NONE: return ""; + case tkind.TK_EOF: return "EOF"; + case tkind.TK_ERR: return "ERR"; + case tkind.TK_IDENT: return "IDENT"; + case tkind.TK_INT: return "INT"; + case tkind.TK_FLOAT: return "FLOAT"; + case tkind.TK_RUNE: return "RUNE"; + case tkind.TK_STR: return "STR"; - if (k == tkind.TK_FN) { return "fn"; }; - if (k == tkind.TK_LET) { return "let"; }; - if (k == tkind.TK_DEF) { return "def"; }; - if (k == tkind.TK_IF) { return "if"; }; - if (k == tkind.TK_ELSE) { return "else"; }; - if (k == tkind.TK_FOR) { return "for"; }; - if (k == tkind.TK_SWITCH) { return "switch"; }; - if (k == tkind.TK_CASE) { return "case"; }; - if (k == tkind.TK_RETURN) { return "return"; }; - if (k == tkind.TK_USE) { return "import"; }; - if (k == tkind.TK_TYPE) { return "type"; }; - if (k == tkind.TK_STRUCT) { return "struct"; }; - if (k == tkind.TK_DEFER) { return "defer"; }; - if (k == tkind.TK_BREAK) { return "break"; }; - if (k == tkind.TK_CONTINUE) { return "continue"; }; - if (k == tkind.TK_EXPORT) { return "export"; }; - if (k == tkind.TK_PROC) { return "proc"; }; - if (k == tkind.TK_CHAN) { return "chan"; }; - if (k == tkind.TK_NIL) { return "nil"; }; - if (k == tkind.TK_TRUE) { return "true"; }; - if (k == tkind.TK_FALSE) { return "false"; }; - if (k == tkind.TK_AS) { return "as"; }; - if (k == tkind.TK_IS) { return "is"; }; - if (k == tkind.TK_VOID) { return "void"; }; - if (k == tkind.TK_YIELD) { return "yield"; }; - if (k == tkind.TK_STATIC) { return "static"; }; - if (k == tkind.TK_MATCH) { return "match"; }; - if (k == tkind.TK_CONST) { return "const"; }; - if (k == tkind.TK_UNDER) { return "_"; }; - if (k == tkind.TK_ENUM) { return "enum"; }; - if (k == tkind.TK_MODULE) { return "package"; }; + case tkind.TK_FN: return "fn"; + case tkind.TK_LET: return "let"; + case tkind.TK_DEF: return "def"; + case tkind.TK_IF: return "if"; + case tkind.TK_ELSE: return "else"; + case tkind.TK_FOR: return "for"; + case tkind.TK_SWITCH: return "switch"; + case tkind.TK_CASE: return "case"; + case tkind.TK_RETURN: return "return"; + case tkind.TK_USE: return "import"; + case tkind.TK_TYPE: return "type"; + case tkind.TK_STRUCT: return "struct"; + case tkind.TK_DEFER: return "defer"; + case tkind.TK_BREAK: return "break"; + case tkind.TK_CONTINUE: return "continue"; + case tkind.TK_EXPORT: return "export"; + case tkind.TK_PROC: return "proc"; + case tkind.TK_CHAN: return "chan"; + case tkind.TK_NIL: return "nil"; + case tkind.TK_TRUE: return "true"; + case tkind.TK_FALSE: return "false"; + case tkind.TK_AS: return "as"; + case tkind.TK_IS: return "is"; + case tkind.TK_VOID: return "void"; + case tkind.TK_YIELD: return "yield"; + case tkind.TK_STATIC: return "static"; + case tkind.TK_MATCH: return "match"; + case tkind.TK_CONST: return "const"; + case tkind.TK_UNDER: return "_"; + case tkind.TK_ENUM: return "enum"; + case tkind.TK_MODULE: return "package"; - if (k == tkind.TK_LPAREN) { return "("; }; - if (k == tkind.TK_RPAREN) { return ")"; }; - if (k == tkind.TK_LBRACE) { return "{"; }; - if (k == tkind.TK_RBRACE) { return "}"; }; - if (k == tkind.TK_LBRACK) { return "["; }; - if (k == tkind.TK_RBRACK) { return "]"; }; - if (k == tkind.TK_COMMA) { return ","; }; - if (k == tkind.TK_SEMI) { return ";"; }; - if (k == tkind.TK_COLON) { return ":"; }; - if (k == tkind.TK_DOT) { return "."; }; - if (k == tkind.TK_ELLIPSIS) { return "..."; }; - if (k == tkind.TK_DOTDOT) { return ".."; }; - if (k == tkind.TK_AT) { return "@"; }; - if (k == tkind.TK_QUESTION) { return "?"; }; + case tkind.TK_LPAREN: return "("; + case tkind.TK_RPAREN: return ")"; + case tkind.TK_LBRACE: return "{"; + case tkind.TK_RBRACE: return "}"; + case tkind.TK_LBRACK: return "["; + case tkind.TK_RBRACK: return "]"; + case tkind.TK_COMMA: return ","; + case tkind.TK_SEMI: return ";"; + case tkind.TK_COLON: return ":"; + case tkind.TK_DOT: return "."; + case tkind.TK_ELLIPSIS: return "..."; + case tkind.TK_DOTDOT: return ".."; + case tkind.TK_AT: return "@"; + case tkind.TK_QUESTION: return "?"; - if (k == tkind.TK_ASSIGN) { return "="; }; - if (k == tkind.TK_PLUSEQ) { return "+="; }; - if (k == tkind.TK_MINUSEQ) { return "-="; }; - if (k == tkind.TK_STAREQ) { return "*="; }; - if (k == tkind.TK_SLASHEQ) { return "/="; }; - if (k == tkind.TK_PERCENTEQ) { return "%="; }; - if (k == tkind.TK_AMPEQ) { return "&="; }; - if (k == tkind.TK_PIPEEQ) { return "|="; }; - if (k == tkind.TK_CARETEQ) { return "^="; }; - if (k == tkind.TK_LSHIFTEQ) { return "<<="; }; - if (k == tkind.TK_RSHIFTEQ) { return ">>="; }; + case tkind.TK_ASSIGN: return "="; + case tkind.TK_PLUSEQ: return "+="; + case tkind.TK_MINUSEQ: return "-="; + case tkind.TK_STAREQ: return "*="; + case tkind.TK_SLASHEQ: return "/="; + case tkind.TK_PERCENTEQ: return "%="; + case tkind.TK_AMPEQ: return "&="; + case tkind.TK_PIPEEQ: return "|="; + case tkind.TK_CARETEQ: return "^="; + case tkind.TK_LSHIFTEQ: return "<<="; + case tkind.TK_RSHIFTEQ: return ">>="; - if (k == tkind.TK_PLUS) { return "+"; }; - if (k == tkind.TK_MINUS) { return "-"; }; - if (k == tkind.TK_STAR) { return "*"; }; - if (k == tkind.TK_SLASH) { return "/"; }; - if (k == tkind.TK_PERCENT) { return "%"; }; - if (k == tkind.TK_AMP) { return "&"; }; - if (k == tkind.TK_PIPE) { return "|"; }; - if (k == tkind.TK_CARET) { return "^"; }; - if (k == tkind.TK_TILDE) { return "~"; }; - if (k == tkind.TK_LSHIFT) { return "<<"; }; - if (k == tkind.TK_RSHIFT) { return ">>"; }; + case tkind.TK_PLUS: return "+"; + case tkind.TK_MINUS: return "-"; + case tkind.TK_STAR: return "*"; + case tkind.TK_SLASH: return "/"; + case tkind.TK_PERCENT: return "%"; + case tkind.TK_AMP: return "&"; + case tkind.TK_PIPE: return "|"; + case tkind.TK_CARET: return "^"; + case tkind.TK_TILDE: return "~"; + case tkind.TK_LSHIFT: return "<<"; + case tkind.TK_RSHIFT: return ">>"; - if (k == tkind.TK_EQ) { return "=="; }; - if (k == tkind.TK_NEQ) { return "!="; }; - if (k == tkind.TK_LT) { return "<"; }; - if (k == tkind.TK_LE) { return "<="; }; - if (k == tkind.TK_GT) { return ">"; }; - if (k == tkind.TK_GE) { return ">="; }; + case tkind.TK_EQ: return "=="; + case tkind.TK_NEQ: return "!="; + case tkind.TK_LT: return "<"; + case tkind.TK_LE: return "<="; + case tkind.TK_GT: return ">"; + case tkind.TK_GE: return ">="; - if (k == tkind.TK_AND) { return "&&"; }; - if (k == tkind.TK_OR) { return "||"; }; - if (k == tkind.TK_NOT) { return "!"; }; + case tkind.TK_AND: return "&&"; + case tkind.TK_OR: return "||"; + case tkind.TK_NOT: return "!"; - if (k == tkind.TK_LARROW) { return "<-"; }; - if (k == tkind.TK_ARROW) { return "->"; }; - if (k == tkind.TK_FATARROW) { return "=>"; }; + case tkind.TK_LARROW: return "<-"; + case tkind.TK_ARROW: return "->"; + case tkind.TK_FATARROW: return "=>"; - if (k == tkind.TK_LAST) { return ""; }; + case tkind.TK_LAST: return ""; + }; return ""; }; diff --git a/test/wcc/904_tok_run.c b/test/wcc/904_tok_run.c new file mode 100644 index 00000000..e832fbf5 --- /dev/null +++ b/test/wcc/904_tok_run.c @@ -0,0 +1,52 @@ +/* + * 904_tok_run — execute the lib/ww/lex tokname/kwlookup @test fixture + * under the C-side `ww run` driver and assert exit 0. + * + * Same thin-wrapper shape as 904_ascii_run / 967_bytes_run: toktest.ww + * carries its own `export fn main()` that drives the @test fns and + * signals which case failed via the exit code. This pins tokname's + * if-ladder -> switch fold (every tkind + the unknown-kind fallback), + * which the 990_selfhost wwdump diff only covers for kinds that appear + * in its corpus. + */ +#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/lex/toktest.ww"; + char path[1024], cmd[2048]; + snprintf(path, sizeof path, "%s/%s", cwd, src); + snprintf(cmd, sizeof cmd, "%s/ww run %s", bin, path); + int rc = runwait(cmd); + if (rc != 0) { + fprintf(stderr, "tok_run FAIL: %s exited %d\n", src, rc); + return 1; + } + printf("tok_run: %s ok\n", src); + return 0; +}