parser: reattach trailing .N to multi-token call results#572
Merged
Conversation
The greedy call-args loop in parse_call_or_atom and the nested-call expansion in parse_call_arg stopped at the leading `.` because Dot doesn't start an operand. The trailing `.N` was left dangling for the infix parser to choke on (ILO-P001 'expected declaration, got `.`'). Route every Call return site through parse_field_chain so the postfix chain reattaches to the call result the same way it does for (expr).N and xs.N. This means `spl "a.b" "." .0` and `num spl "1.2.3" ".".1` now parse without parens, matching the bare-ident and parenthesised shapes.
Pins the new shape across every public engine (VM and Cranelift JIT when the feature is on): - top-level multi-token call with trailing .N (glued and spaced) - nested call inside outer arity-1 caller (the originating repro) - safe .?N shorthand on the call result - arity-known call (`at xs 0 .1`) inside list-element context - equivalence with the parenthesised workaround - existing bare-ident and paren shapes unchanged examples/call-result-dot-index.ilo demonstrates the canonical shape with -- run / -- out assertions so the examples_engines harness picks it up as a regression test too. Notes the bare-ident-last-arg caveat inline so agents reading the example don't get surprised when `at rows i .1` glues .1 to i instead of the call result.
SPEC.md records section and ai.txt RECORDS section both now describe the new multi-token-call shape alongside the existing parenthesised and bare-ident shapes, with the bare-ident-last-arg caveat called out so agents know when to fall back to parens or bind-first.
❌ 2 Tests Failed:
View the top 2 failed test(s) by shortest run time
To view more test analytics, go to the Test Analytics Dashboard |
Collaborator
Author
|
CI checks failing are pre-existing on origin/main at my base commit (
I verified my parser change doesn't introduce the panic — Recommend either rebasing once the upstream fix lands, or merging as-is given the failures are unrelated. Happy to defer either way. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Pending P2 #12.
num spl "1.2.3" ".".1and the spaced variantspl "a.b.c" "." .0both failed ILO-P001 because the greedy call-args loop stopped at the leading.and the trailing.Nwas left dangling for the infix parser to choke on. Workaround wasnum (spl "1.2.3" ".").1. After this PR the parens become optional - the trailing.Nreattaches to the call result the same way it does for(expr).Nandxs.N.Manifesto framing: 2-3 tokens saved per call-result pick-off, and the surface becomes consistent across the three head shapes (bare ident / parens / multi-token call). Agents stop hitting the "wrap the inner call" trap.
Repro before/after
Before:
After:
What's in the diff
Expr::Callreturn site inparse_call_or_atomandparse_call_argthroughparse_field_chain. Touches the 5 sites that build a call out of greedy args (name!/name!!form, zero-arg paren-call, no-whitespace-call arity-capped list element, variadic-fmt expansion, nested arity-known call, top-level greedy call).tests/regression_call_result_dot_index.rspins the new shape on VM + Cranelift JIT, plusexamples/call-result-dot-index.iloso theexamples_enginesharness exercises it too. Both the glued (.".1) and spaced (. .1) forms are covered, along with safe.?Nand equivalence with the paren workaround. Existing bare-ident and paren shapes pinned unchanged..Nglues to the variable, not the call) so agents know when to fall back to(at rows i).1or bind-first.Test plan
cargo test --release --features cranelift --test regression_call_result_dot_index— 8 tests pass across VM + JITexamples_enginesruns the newcall-result-dot-index.iloacross all enginescargo test --release --features cranelift— only pre-existing flakes (spec_reserved_short_names_match_builtin_registryfor upstreamb64/hexdoc drift,zgunzip.iloexample missing builtin on this branch base,wr_csv_field_with_newline_is_quotedflake from shared/tmppaths) — none touched by this changecargo clippy --release --features cranelift -- -D warningscleancargo fmtcleanFollow-ups
at rows i .1glues.1toiinstead of theatresult) is documented but not fixed - lifting it requires a wider lookahead inparse_atom's Ident branch and would risk regressingxs.Nshapes. Filed as a smaller follow-up if it shows up in persona reports.