Skip to content

Commit 50c9a96

Browse files
olwangclaude
andcommitted
refactor(selfhost): name the shared token/word/symbol id tables; dedup top-level dispatch
Addresses the self-host code-review findings: - Medium (magic ids): replace the raw numeric tables threaded through scan/parser/check with named constants — TOK_* (token kinds), SYM_* (symbol token codes), WORD_* (declaration-keyword ids), defined once in scan.rss. All ~140 wid:/code:/kind sites now reference a name. Raw character-code compares inside the low-level scanners are left as-is (they pair with adjacent char literals; they are not the shared table). - Medium (dup dispatch): extract the identical top-level classification (isPub/isFeatures/isProfile/isSum/isNativeMod/isTypeAlias/isConst) that the parser and checker drivers each computed inline into a shared classify_top(...) -> TopClass in scan.rss, so the two drivers can no longer drift as declaration forms are added. - Low (Eof fallback): lexer.rss kind_name now maps TOK_EOF explicitly and returns "UnknownKind" for unrecognized ids (was: any unknown -> "Eof"). - Low (stale comments): drop the "none of the 15 rejects" counts in scan.rss (corpus is 556 files; the count is not part of the contract). Byte-for-byte parity preserved: lexer/parser/checker corpus parity all green over 556 files (32.8s), perf unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 2be2341 commit 50c9a96

4 files changed

Lines changed: 228 additions & 131 deletions

File tree

selfhost/check.rss

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ fn dotted_name_text(toks: read List<Tok>, i: read Int) -> String {
4242
let mut j = i + 1
4343
let mut going = true
4444
while going {
45-
let dot = at_symbol(toks: read toks, i: read j, code: read 46)
45+
let dot = at_symbol(toks: read toks, i: read j, code: read SYM_DOT)
4646
let nextIdent = is_ident_tok(toks: read toks, i: read (j + 1))
4747
if dot && nextIdent {
4848
out = String.concat(left: read out, right: read ".")
@@ -58,10 +58,10 @@ fn dotted_name_text(toks: read List<Tok>, i: read Int) -> String {
5858
// Index of the name token for a type decl (after optional pub, opaque, kind kw).
5959
fn type_name_start(toks: read List<Tok>, i: read Int) -> Int {
6060
let mut j = i
61-
if at_ident(toks: read toks, i: read j, wid: read 13) {
61+
if at_ident(toks: read toks, i: read j, wid: read WORD_PUB) {
6262
j = j + 1
6363
}
64-
if at_ident(toks: read toks, i: read j, wid: read 5) {
64+
if at_ident(toks: read toks, i: read j, wid: read WORD_OPAQUE) {
6565
j = j + 1
6666
}
6767
j = j + 1
@@ -71,7 +71,7 @@ fn type_name_start(toks: read List<Tok>, i: read Int) -> Int {
7171
// Index of the name token for a sum decl (after optional pub, sum kw).
7272
fn sum_name_start(toks: read List<Tok>, i: read Int) -> Int {
7373
let mut j = i
74-
if at_ident(toks: read toks, i: read j, wid: read 13) {
74+
if at_ident(toks: read toks, i: read j, wid: read WORD_PUB) {
7575
j = j + 1
7676
}
7777
j = j + 1
@@ -83,15 +83,15 @@ fn fn_name_start(toks: read List<Tok>, i: read Int) -> Int {
8383
let mut j = i
8484
let mut attrs = true
8585
while attrs {
86-
if at_symbol(toks: read toks, i: read j, code: read 35) {
86+
if at_symbol(toks: read toks, i: read j, code: read SYM_HASH) {
8787
j = j + 5
8888
} else {
8989
attrs = false
9090
}
9191
}
9292
let mut mods = true
9393
while mods {
94-
let isMod = at_ident(toks: read toks, i: read j, wid: read 13) || at_ident(toks: read toks, i: read j, wid: read 14) || at_ident(toks: read toks, i: read j, wid: read 9)
94+
let isMod = at_ident(toks: read toks, i: read j, wid: read WORD_PUB) || at_ident(toks: read toks, i: read j, wid: read WORD_ASYNC) || at_ident(toks: read toks, i: read j, wid: read WORD_NATIVE)
9595
if isMod {
9696
j = j + 1
9797
} else {
@@ -106,7 +106,7 @@ fn fn_name_start(toks: read List<Tok>, i: read Int) -> Int {
106106
fn find_body_open(toks: read List<Tok>, i: read Int, end: read Int) -> Int {
107107
let mut k = i
108108
while k < end {
109-
if at_symbol(toks: read toks, i: read k, code: read 123) {
109+
if at_symbol(toks: read toks, i: read k, code: read SYM_LBRACE) {
110110
return k
111111
}
112112
k = k + 1
@@ -126,7 +126,7 @@ fn body_has_duplicate_field(toks: read List<Tok>, ob: read Int, close: read Int)
126126
let mut brace = 0
127127
let mut k = ob + 1
128128
while k < close {
129-
let isColon = at_symbol(toks: read toks, i: read k, code: read 58)
129+
let isColon = at_symbol(toks: read toks, i: read k, code: read SYM_COLON)
130130
let atTop = paren == 0 && br == 0 && ang == 0 && brace == 0
131131
if isColon && atTop && is_ident_tok(toks: read toks, i: read (k - 1)) {
132132
let name = tk_text(toks: read toks, i: read (k - 1))
@@ -135,27 +135,27 @@ fn body_has_duplicate_field(toks: read List<Tok>, ob: read Int, close: read Int)
135135
}
136136
Set.insert<String>(set: mut seen, value: read name)
137137
}
138-
if at_symbol(toks: read toks, i: read k, code: read 40) {
138+
if at_symbol(toks: read toks, i: read k, code: read SYM_LPAREN) {
139139
paren = paren + 1
140-
} else if at_symbol(toks: read toks, i: read k, code: read 41) {
140+
} else if at_symbol(toks: read toks, i: read k, code: read SYM_RPAREN) {
141141
if paren > 0 {
142142
paren = paren - 1
143143
}
144-
} else if at_symbol(toks: read toks, i: read k, code: read 91) {
144+
} else if at_symbol(toks: read toks, i: read k, code: read SYM_LBRACKET) {
145145
br = br + 1
146-
} else if at_symbol(toks: read toks, i: read k, code: read 93) {
146+
} else if at_symbol(toks: read toks, i: read k, code: read SYM_RBRACKET) {
147147
if br > 0 {
148148
br = br - 1
149149
}
150-
} else if at_symbol(toks: read toks, i: read k, code: read 60) {
150+
} else if at_symbol(toks: read toks, i: read k, code: read SYM_LANGLE) {
151151
ang = ang + 1
152-
} else if at_symbol(toks: read toks, i: read k, code: read 62) {
152+
} else if at_symbol(toks: read toks, i: read k, code: read SYM_RANGLE) {
153153
if ang > 0 {
154154
ang = ang - 1
155155
}
156-
} else if at_symbol(toks: read toks, i: read k, code: read 123) {
156+
} else if at_symbol(toks: read toks, i: read k, code: read SYM_LBRACE) {
157157
brace = brace + 1
158-
} else if at_symbol(toks: read toks, i: read k, code: read 125) {
158+
} else if at_symbol(toks: read toks, i: read k, code: read SYM_RBRACE) {
159159
if brace > 0 {
160160
brace = brace - 1
161161
}
@@ -181,16 +181,17 @@ fn main() -> Unit {
181181
while running {
182182
if i >= ntok {
183183
running = false
184-
} else if tk_kind(toks: read toks, i: read i) == 8 {
184+
} else if tk_kind(toks: read toks, i: read i) == TOK_EOF {
185185
running = false
186186
} else {
187-
let isPub = at_ident(toks: read toks, i: read i, wid: read 13)
188-
let isFeatures = at_ident(toks: read toks, i: read i, wid: read 17) && at_symbol(toks: read toks, i: read (i + 1), code: read 58)
189-
let isProfile = at_ident(toks: read toks, i: read i, wid: read 16) && at_symbol(toks: read toks, i: read (i + 1), code: read 58)
190-
let isSum = at_ident(toks: read toks, i: read i, wid: read 6) || (isPub && at_ident(toks: read toks, i: read (i + 1), wid: read 6))
191-
let isNativeMod = at_ident(toks: read toks, i: read i, wid: read 9) && at_ident(toks: read toks, i: read (i + 1), wid: read 10)
192-
let isTypeAlias = at_ident(toks: read toks, i: read i, wid: read 11) || (isPub && at_ident(toks: read toks, i: read (i + 1), wid: read 11))
193-
let isConst = at_ident(toks: read toks, i: read i, wid: read 12) || (isPub && at_ident(toks: read toks, i: read (i + 1), wid: read 12))
187+
let cls = classify_top(toks: read toks, i: read i)
188+
let isPub = cls.isPub
189+
let isFeatures = cls.isFeatures
190+
let isProfile = cls.isProfile
191+
let isSum = cls.isSum
192+
let isNativeMod = cls.isNativeMod
193+
let isTypeAlias = cls.isTypeAlias
194+
let isConst = cls.isConst
194195
if isFeatures {
195196
i = declaration_line_end(toks: read toks, start: read i)
196197
} else if isProfile {
@@ -230,14 +231,14 @@ fn main() -> Unit {
230231
Set.insert<String>(set: mut types, value: read name)
231232
i = r
232233
}
233-
} else if at_ident(toks: read toks, i: read i, wid: read 7) {
234+
} else if at_ident(toks: read toks, i: read i, wid: read WORD_PROTOCOL) {
234235
let r = parse_protocol_decl(toks: read toks, i: read i)
235236
if r < 0 {
236237
running = false
237238
} else {
238239
i = r
239240
}
240-
} else if at_ident(toks: read toks, i: read i, wid: read 8) {
241+
} else if at_ident(toks: read toks, i: read i, wid: read WORD_IMPL) {
241242
let r = parse_impl_decl(toks: read toks, i: read i)
242243
if r < 0 {
243244
running = false
@@ -265,14 +266,14 @@ fn main() -> Unit {
265266
} else {
266267
i = r
267268
}
268-
} else if at_ident(toks: read toks, i: read i, wid: read 10) {
269+
} else if at_ident(toks: read toks, i: read i, wid: read WORD_MODULE) {
269270
let r = parse_module_decl(toks: read toks, i: read i)
270271
if r < 0 {
271272
i = i + 1
272273
} else {
273274
i = r
274275
}
275-
} else if at_ident(toks: read toks, i: read i, wid: read 15) {
276+
} else if at_ident(toks: read toks, i: read i, wid: read WORD_USE) {
276277
let r = parse_use_decl(toks: read toks, i: read i)
277278
if r < 0 {
278279
i = i + 1

selfhost/lexer.rss

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,17 @@
1111

1212
// Map a Tok.kind int to the canonical KIND name.
1313
fn kind_name(k: read Int) -> String {
14-
if k == 1 { return "Ident" }
15-
if k == 2 { return "Number" }
16-
if k == 3 { return "String" }
17-
if k == 4 { return "InterpolatedString" }
18-
if k == 5 { return "MultilineString" }
19-
if k == 6 { return "Keyword" }
20-
if k == 7 { return "Symbol" }
21-
if k == 9 { return "Char" }
22-
if k == 10 { return "Unknown" }
23-
return "Eof"
14+
if k == TOK_IDENT { return "Ident" }
15+
if k == TOK_NUMBER { return "Number" }
16+
if k == TOK_STRING { return "String" }
17+
if k == TOK_INTERP { return "InterpolatedString" }
18+
if k == TOK_MULTILINE { return "MultilineString" }
19+
if k == TOK_KEYWORD { return "Keyword" }
20+
if k == TOK_SYMBOL { return "Symbol" }
21+
if k == TOK_EOF { return "Eof" }
22+
if k == TOK_CHAR { return "Char" }
23+
if k == TOK_UNKNOWN { return "Unknown" }
24+
return "UnknownKind"
2425
}
2526

2627
fn main() -> Unit {

selfhost/parser.rss

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -71,23 +71,24 @@ fn main() -> Unit {
7171
while running {
7272
if i >= ntok {
7373
running = false
74-
} else if tk_kind(toks: read toks, i: read i) == 8 {
74+
} else if tk_kind(toks: read toks, i: read i) == TOK_EOF {
7575
running = false
7676
} else {
77-
let isPub = at_ident(toks: read toks, i: read i, wid: read 13)
78-
let isFeatures = at_ident(toks: read toks, i: read i, wid: read 17) && at_symbol(toks: read toks, i: read (i + 1), code: read 58)
79-
let isProfile = at_ident(toks: read toks, i: read i, wid: read 16) && at_symbol(toks: read toks, i: read (i + 1), code: read 58)
80-
let isSum = at_ident(toks: read toks, i: read i, wid: read 6) || (isPub && at_ident(toks: read toks, i: read (i + 1), wid: read 6))
81-
let isNativeMod = at_ident(toks: read toks, i: read i, wid: read 9) && at_ident(toks: read toks, i: read (i + 1), wid: read 10)
82-
let isTypeAlias = at_ident(toks: read toks, i: read i, wid: read 11) || (isPub && at_ident(toks: read toks, i: read (i + 1), wid: read 11))
83-
let isConst = at_ident(toks: read toks, i: read i, wid: read 12) || (isPub && at_ident(toks: read toks, i: read (i + 1), wid: read 12))
77+
let cls = classify_top(toks: read toks, i: read i)
78+
let isPub = cls.isPub
79+
let isFeatures = cls.isFeatures
80+
let isProfile = cls.isProfile
81+
let isSum = cls.isSum
82+
let isNativeMod = cls.isNativeMod
83+
let isTypeAlias = cls.isTypeAlias
84+
let isConst = cls.isConst
8485
if isFeatures {
8586
let fstart = i + 2
8687
let fend = declaration_line_end(toks: read toks, start: read fstart)
8788
let mut k = fstart
8889
let mut ferr = -1
8990
while k < fend {
90-
if at_symbol(toks: read toks, i: read k, code: read 44) {
91+
if at_symbol(toks: read toks, i: read k, code: read SYM_COMMA) {
9192
k = k + 1
9293
} else {
9394
if is_feature_tok(toks: read toks, i: read k) {
@@ -96,7 +97,7 @@ fn main() -> Unit {
9697
}
9798
} else {
9899
let kd = tk_kind(toks: read toks, i: read k)
99-
if ferr < 0 && kd != 8 && kd != -1 {
100+
if ferr < 0 && kd != TOK_EOF && kd != -1 {
100101
ferr = k
101102
}
102103
}
@@ -130,7 +131,7 @@ fn main() -> Unit {
130131
} else {
131132
i = r
132133
}
133-
} else if at_ident(toks: read toks, i: read i, wid: read 7) {
134+
} else if at_ident(toks: read toks, i: read i, wid: read WORD_PROTOCOL) {
134135
let r = parse_protocol_decl(toks: read toks, i: read i)
135136
if r < 0 {
136137
errLine = tk_line(toks: read toks, i: read i)
@@ -139,7 +140,7 @@ fn main() -> Unit {
139140
} else {
140141
i = r
141142
}
142-
} else if at_ident(toks: read toks, i: read i, wid: read 8) {
143+
} else if at_ident(toks: read toks, i: read i, wid: read WORD_IMPL) {
143144
let r = parse_impl_decl(toks: read toks, i: read i)
144145
if r < 0 {
145146
errLine = tk_line(toks: read toks, i: read i)
@@ -175,14 +176,14 @@ fn main() -> Unit {
175176
} else {
176177
i = r
177178
}
178-
} else if at_ident(toks: read toks, i: read i, wid: read 10) {
179+
} else if at_ident(toks: read toks, i: read i, wid: read WORD_MODULE) {
179180
let r = parse_module_decl(toks: read toks, i: read i)
180181
if r < 0 {
181182
i = i + 1
182183
} else {
183184
i = r
184185
}
185-
} else if at_ident(toks: read toks, i: read i, wid: read 15) {
186+
} else if at_ident(toks: read toks, i: read i, wid: read WORD_USE) {
186187
let r = parse_use_decl(toks: read toks, i: read i)
187188
if r < 0 {
188189
i = i + 1

0 commit comments

Comments
 (0)