Repository navigation
t27b: which calls lower as the .len field, decided by specs/tri/t27b/lencall.t27 #7524
Description
Port slice of #6198 (under #6063 and #5980).
cli/t27b/src/lower/lencall.rs decides which call t27b lowers as the .len field (W570: t27c's Zig backend prints x.len() and len(x) as the field x.len). That decision is a pure classification over the call's name bytes, its child count, the parser's method mark, and whether a fn named len is declared:
- a method call
lenwith exactly one child: the receiver is that child; - a no-argument call whose name is a dotted path ending in
.len(a.b.len()), every segment non-empty ASCII letters/digits/_, the first not starting with a digit: the receiver is the path; - a free
len(x)with one argument when no fnlenis declared or poisoned: the receiver isx.
This moves that decision into specs/tri/t27b/lencall.t27 (tests take their values from the current Rust), mounts its t27c gen-rust output gen/rust/tri/t27b/lencall.rs, and leaves only the node building in the hand-written file.
Known gen-rust limit hit on the way: a slice parameter lowers to an owned Vec<u8> (a []const u8 one to &'static str, #7449), so the glue passes c.name.as_bytes().to_vec().
Done when: the t27b lab corpus of the head matches the master base (pass, blocked and mismatch counts identical, mismatch 0), cargo test -p t27b passes, and t27c test-report specs/tri/t27b/lencall.t27 shows 6 of 6 non-vacuous passes.
Boundary
specs/tri/t27b/lencall.t27cli/t27b/src/lower/lencall.rsgen/rust/tri/t27b/lencall.rs
User Scenarios
- Given the t27b compiler's lowering logic for
.lenfield calls resides in hand-written Rust, when the classification rules are expressed inspecs/tri/t27b/lencall.t27andt27c gen-rustproducesgen/rust/tri/t27b/lencall.rs, thencli/t27b/src/lower/lencall.rsdelegates to the generated code and retains only node construction. - Given a call
a.b.len()where each segment is non-empty ASCII letters/digits/underscore and the first segment does not start with a digit, when the spec classifies it as a dotted-path.lencall with zero arguments, then the receiver is the full patha.b. - Given a free call
len(x)with one argument and no function namedlendeclared or poisoned in scope, when the spec classifies it as a candidate for.lenlowering, then the receiver isx.
Requirements
- FR-001: The spec
specs/tri/t27b/lencall.t27MUST encode the three classification rules for.lenlowering: method calllenwith one child, dotted-path.lencall with zero arguments, and freelen(x)with one argument when nolenfunction is declared or poisoned. - FR-002: The
t27c gen-rustoutputgen/rust/tri/t27b/lencall.rsMUST provide the pure classification function that returns the receiver node orNone. - FR-003: The hand-written
cli/t27b/src/lower/lencall.rsMUST call the generated classification function and perform only the node building (wrapping the receiver in a field-access node). - FR-004: The glue code in the hand-written file MUST convert the call name to
Vec<u8>viac.name.as_bytes().to_vec()to satisfy the generated function's ownedVec<u8>parameter requirement.
Success Criteria
t27c test-report specs/tri/t27b/lencall.t27exits withexit 0and reports "6 of 6 non-vacuous passes"cargo test -p t27bexits withexit 0- The t27b lab corpus run shows pass, blocked, and mismatch counts identical to master base with mismatch count 0
gen/rust/tri/t27b/lencall.rsexists and is produced byt27c gen-rust specs/tri/t27b/lencall.t27
Activity
Merge master into #7530 (after #7535 and #7537)
Merge claude/t27b-lencall-7524 into master 927b1ef (from master's side)
Merge claude/t27b-lencall-7524 into master b8cb93f (from master's side)
Merge claude/t27b-lencall-7524 into master 1f2448e (from master's side)
Merge master 4d7d2d3 into the #7765 lane, keeping both sides (Closes #…