parser: clear arity error for deep prefix-binop chains#339
Merged
Conversation
A run of N prefix-binop tokens (e.g. `+++a b c`) needs N+1 leaf operands. When the input supplies only N, parse_prefix_binop used to unwind recursively until parse_atom hit EOF and returned a bare ILO-P010 "expected expression, got EOF" at line 1 col 1, leaving the agent no signal about which chain was at fault. The new prefix_chain_arity_diagnostic runs at the head of parse_prefix_binop when scan_prefix_binary_end reports the chain won't parse. It counts the leading prefix-binop run (K), then counts atom-starting tokens up to the statement boundary, and emits an ILO-P003 hint pointing at the chain start with the actual glyph (`+++`, `+*>`, etc.) and the operand shortfall. The heuristic only fires on K >= 2 to keep single-op forms like `+p2.x p2.y` and `+r with f:v 2` on the existing path, since rich postfix structure on operands can't be enumerated without re-implementing operand parsing. Unknown tokens in the operand area abort the diagnostic and fall through, so any shape this scanner can't classify keeps its current error path. `&&` / `||` are also skipped so their dedicated hint downstream still wins. Regression tests cover depths 2, 3, 4, a mixed-operator chain, and two positive shapes that must continue to parse cleanly.
Companion example for the parser fix. An agent that has hit the new ILO-P003 arity diagnostic can read this file and pick up a working template for either shape: providing K+1 operands, or binding intermediate results step by step. The example harness runs both functions across every engine, so the file also doubles as a higher-level regression that the canonical fixed forms keep evaluating to 10.
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
danieljohnmorris
added a commit
that referenced
this pull request
May 17, 2026
fifteen fixes since 0.11.5, all from rerun5/rerun6 personas plus standing asks: ListView foundation (#334), window-text-perf reshape via ListView (#336), inner-flt predicate inlining (#340), double-minus trap ILO-P021 (#331), bare-ident bang silent-nil regression (#324), Cranelift JIT span plumbing (#335), bool-prefix ternary (#330), wh prefix-cond reparse (#332), --run-engine auto-pick main (#329), subcommand helper hyphens+non-ident (#328), runtime error spans (#335), persona-diagnostic batch 3 (#327), rgxall1+ct (#333), single-line body diagnostic (#322 carry), lambda type-var defensive test (#326), N-deep prefix arity error (#339), prefix-minus span column drift (#338), doc-sync (#337).
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
qa-tester P1 rerun #6:
+++a b cand other N-prefix-with-N-operands shapes used to exit silently with a bareILO-P010 expected expression, got EOFat line 1 col 1. The agent had no signal about which chain was at fault or how to reshape it. The parser now surfaces anILO-P003pointing at the chain start with the actual glyph and the operand shortfall.Manifesto framing: every silent-EOF on a real input is a retry the agent can't avoid, because there's no information to act on. A focused arity message lets the next call land first time, which is exactly the token-cost win the language is here for.
Repro
Before:
After:
What's in the diff
parser: detect deep prefix-binop chains with too few operands— addsprefix_chain_arity_diagnosticat the head ofparse_prefix_binop, gated onscan_prefix_binary_endreturning None so valid shapes (+a b,++a b c,+++a b c d,+*a b c) stay on the existing path. The detector is conservative: only fires on K >= 2 leading prefix-binops, skips&&/||(their dedicated hint still wins), and aborts on any unknown token in the operand area rather than risk a false positive. Counts unary wrappers (!~^$-) and atom postfix (.field,[i],(),!,with ...) so it doesn't miscount rich operands. Regression tests cover depths 2, 3, 4, a mixed-operator chain, and two positive shapes that must continue to parse cleanly.examples: prefix-chain-arity shows the K+1 operand rule— companion.ilofile so an agent that hits the new diagnostic has an in-context template for either fix (provide K+1 operands or bind intermediate results). Runs across every engine via the existing examples harness.Test plan
cargo test --release --features craneliftcleancargo clippy --release --features cranelift --all-targets -- -D warningscleancargo fmt --checkclean+a b,++a b c,+++a b c d,+*a b c,&!x y,+p2.x p2.y) unchanged&&x yand||x ystill hit their dedicated hint, not the new onedeeparityanddeepbindacross all enginesFollow-ups
+ashapes on the existing ILO-P010 path. If a future feedback round shows+a(missing second operand) is also a friction source, the same helper can drop the gate once operand-postfix accounting handles every shapeparse_operanddoes.