Skip to content

Commit 97b4e44

Browse files
olwangclaude
andcommitted
feat(selfhost): AST producer — statement_end line-continuation → 286/576
Ported parser/scan.rs statement_end into stmt_end (the boundary primitive used by every statement arm): a top-level `;` terminates; a line starting with `.`/`?` (postfix chain) or beginning with / following a continuation operator (`| & + * / % ^`, SH-017) continues the statement; generic `<>` now tracked as angle depth. `< > - = !` are excluded so a wrapped chain can't swallow a genuine new statement. Previously stmt_end cut every wrapped statement at the newline. Corpus reach: 280 -> 286 / 576 byte-exact, still 0 run-failures. Floor -> 286. New sample continuation.rss; all 21 samples byte-exact. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent a3bcdc2 commit 97b4e44

3 files changed

Lines changed: 45 additions & 5 deletions

File tree

crates/rsscript/src/selfhost_parity.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1522,7 +1522,7 @@ const AST_SAMPLE_MIN: usize = 6;
15221522
/// Floor for `ast_parity_corpus` — the number of corpus files whose rss AST dump
15231523
/// already matches the oracle byte-for-byte. Ratchets up as the producer's
15241524
/// coverage grows; a drop signals a regression. (Full parity = files.len().)
1525-
const AST_CORPUS_PARITY_FLOOR: usize = 280;
1525+
const AST_CORPUS_PARITY_FLOOR: usize = 286;
15261526

15271527
/// Step-2 measurement gate (ignored by default): how many corpus files the rss
15281528
/// producer reproduces byte-for-byte. Not full parity yet — this ratchets a floor

selfhost/astdump.rss

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -982,23 +982,56 @@ fn emit_type_ref(toks: read List<Tok>, i: read Int, tag: read String, eff: read
982982

983983
// Statement end: first token on a strictly-later line at bracket depth 0 (simple
984984
// line model; operator-continuation and postfix chains are a documented gap).
985+
// Statement boundary, mirroring parser/scan.rs statement_end. A statement ends at
986+
// the first token on a strictly-later line at bracket+angle depth 0, EXCEPT: a
987+
// top-level `;` terminates immediately; a line starting with `.`/`?` (postfix) or
988+
// with/after a continuation operator (`| & + * / % ^`) continues the statement.
985989
fn stmt_end(toks: read List<Tok>, start: read Int, limit: read Int) -> Int {
986-
let ln = tk_line(toks: read toks, i: read start)
990+
let mut line = tk_line(toks: read toks, i: read start)
987991
let mut depth = 0
992+
let mut angle = 0
993+
let mut postfixLine = -1
988994
let mut i = start + 1
989995
while i < limit {
996+
if depth == 0 && angle == 0 && at_symbol(toks: read toks, i: read i, code: read SYM_SEMI) {
997+
return i
998+
}
999+
if depth == 0 && angle == 0 && tk_line(toks: read toks, i: read i) > line {
1000+
if postfixLine == tk_line(toks: read toks, i: read i) {
1001+
// still on a postfix-continuation line — keep scanning.
1002+
} else if is_stmt_postfix(toks: read toks, i: read i) {
1003+
postfixLine = tk_line(toks: read toks, i: read i)
1004+
} else if is_cont_op(toks: read toks, i: read i) || is_cont_op(toks: read toks, i: read (i - 1)) {
1005+
line = tk_line(toks: read toks, i: read i)
1006+
} else {
1007+
return i
1008+
}
1009+
}
9901010
if at_symbol(toks: read toks, i: read i, code: read SYM_LPAREN) || at_symbol(toks: read toks, i: read i, code: read SYM_LBRACE) || at_symbol(toks: read toks, i: read i, code: read SYM_LBRACKET) {
9911011
depth = depth + 1
9921012
} else if at_symbol(toks: read toks, i: read i, code: read SYM_RPAREN) || at_symbol(toks: read toks, i: read i, code: read SYM_RBRACE) || at_symbol(toks: read toks, i: read i, code: read SYM_RBRACKET) {
993-
depth = depth - 1
994-
} else if depth == 0 && tk_line(toks: read toks, i: read i) > ln {
995-
return i
1013+
if depth > 0 { depth = depth - 1 }
1014+
} else if depth == 0 && at_symbol(toks: read toks, i: read i, code: read SYM_LANGLE) && is_generic_angle(toks: read toks, start: read start, end: read limit, open: read i) {
1015+
angle = angle + 1
1016+
} else if depth == 0 && angle > 0 && at_symbol(toks: read toks, i: read i, code: read SYM_RANGLE) {
1017+
angle = angle - 1
9961018
}
9971019
i = i + 1
9981020
}
9991021
return limit
10001022
}
10011023

1024+
fn is_stmt_postfix(toks: read List<Tok>, i: read Int) -> Bool {
1025+
return at_symbol(toks: read toks, i: read i, code: read SYM_QUESTION) || at_symbol(toks: read toks, i: read i, code: read SYM_DOT)
1026+
}
1027+
1028+
// Continuation operators (SH-017): `| & + * / % ^` — a statement-level expression
1029+
// wraps across a newline when a line begins with, or ends before, one of these.
1030+
// `< > - = !` are deliberately excluded (see scan.rs).
1031+
fn is_cont_op(toks: read List<Tok>, i: read Int) -> Bool {
1032+
return at_symbol(toks: read toks, i: read i, code: read SYM_PIPE) || at_symbol(toks: read toks, i: read i, code: read SYM_AMP) || at_symbol(toks: read toks, i: read i, code: read SYM_PLUS) || at_symbol(toks: read toks, i: read i, code: read SYM_STAR) || at_symbol(toks: read toks, i: read i, code: read SYM_SLASH) || at_symbol(toks: read toks, i: read i, code: read SYM_PERCENT) || at_symbol(toks: read toks, i: read i, code: read SYM_CARET)
1033+
}
1034+
10021035
// First top-level standalone `=` (assignment, not == != <= >=) in [start, end), or -1.
10031036
fn top_assign(toks: read List<Tok>, start: read Int, end: read Int) -> Int {
10041037
let mut depth = 0
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
fn calc(a: read Int, b: read Int) -> Int {
2+
let total = a
3+
+ b
4+
+ a
5+
return total
6+
+ b
7+
}

0 commit comments

Comments
 (0)