Skip to content

v2 parse: a '-' that begins a line after an operand refuses (NewlineBeforeDualRoleOperator), as the seed refuses it (PR2a, stacked on #12773) - #12881

Merged
gunbai-bot[bot] merged 26 commits into
mainfrom
session/calm-fox-43-newline-refusal
Oct 1, 2026
Merged

gunbai-bot[bot] merged 26 commits into
mainfrom
session/calm-fox-43-newline-refusal

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

Stacked on #12773 (base: its branch). Discharges the trigger of the #12769 row, and is the production consumer of #12773's RefuseOnMatch / AfterLineBreak arms and its stream layout.

The defect, now on main

- is both infix (subtraction) and prefix (negation), and the dag grammar has no statement terminator. So x followed by a line - 1 is either one subtraction or two statements. The seed refuses it as ambiguous (v1.compiler.parse is_ambiguous_prefix_infix_newline_boundary, whose dual-role set is exactly -). v2 read it silently as one subtraction. Since #12817 made block forms operands of binary_expr, a block statement followed by a - line merges the same way: silent wrongness, below the floor.

The change

v2.extdeps.languages.dag dag_grammar_additive_expr_helper: at every additive continuation, the first alternative is
RefuseOnMatch { AfterLineBreak { - }, NewlineBeforeDualRoleOperator }.

  • A - preceded by a line break refuses the parse at the -, with a typed reason from the closed v2.std.parse_refusal_reason vocabulary (new variant NewlineBeforeDualRoleOperator).
  • A same-line - falls through to subtraction.
  • Every expression reaches this continuation, so the rule holds for every statement form, matching the seed's rule.

Controls (v2.test.parse.newline_dual_role_operator_parse), green on a remote run

  • x ⏎ - 1 refuses with NewlineBeforeDualRoleOperator at the - (bytes 51..52).
  • match w {..} ⏎ - n refuses at the - (bytes 101..102).
  • x - 1 on one line parses and normalizes.
  • Emit side (DESIGN §4, one grammar both ways): the refusal is ingest-only (RefuseOnMatch derives no tree, and emit reads formal productions). What emit must guarantee is that it never writes what ingest refuses. Emitted text breaks a line only where a token class's emit transform is EmitLineBreaks, and no dag token class has one, so the dag emitter can never write a line-break-preceded -. no_dag_token_class_emits_a_line_break_holds reds the moment a dag class gains a line-breaking transform.

Mutation (test.claim.long.newline_dual_role_operator_mutation_witness_test), green

  • The witness rebuilds the live dag grammar with every RefuseOnMatch arm replaced by a never-matching terminal.
  • It asserts that such arms exist and that every one is the newline refusal. There are several because the additive row is a helper inlined at each operand position of the comparison and equality rows, but it is one authored row.
  • Under the mutant both next-line forms parse again (the silent merge returns); under the live grammar both refuse; the same-line form parses under both.

Census

Over the 190 corpus files with a block-headed operand site, run with v2.compiler.parse_acceptance_census: 0 refuse with NewlineBeforeDualRoleOperator. A static scan finds no block-headed statement followed by a - line in dag/ or src/v2. So nothing in the tree changes meaning; the construct becomes unwritable from here on.

Rung

The #12769 class goes from silent wrongness to structurally guaranteed: no Accepted program contains a line-break-preceded dual-role - at an operand boundary.

🤖 Generated with Claude Code

gunbc-ci-auto-heal and others added 22 commits September 30, 2026 10:58
…fuseOnMatch / AfterLineBreak grammar arms, controls

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… question is a lookup (review 73189)

The gap question folded over the whole source per question: O(tokens x source). StreamLayout pairs
the source with a line-break-before answer for every token, derived in one walk over source and
tokens by its only constructor; a line feed inside a token is not layout. The digest reads the
source through the layout.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…r (floor budget: 97k steps vs 72.3k)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… not -)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… those, not by every character (floor budget)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…221)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…rk (review 73234)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…at lexing); digest renamed to what it covers

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…d: emitted as host String)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…eceded token (review 73282)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…on (NewlineBeforeDualRoleOperator); controls, emit control, mutation witness

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…additive row is inlined, so arms > 1)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…t (no lookup per token; floor budget)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…h returns (emit-build)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…source); value = the octet the gap begins

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Base automatically changed from session/calm-fox-43-layout-model to main October 1, 2026 10:50
gunbc-ci-auto-heal and others added 4 commits October 1, 2026 10:55
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…only (floor new-witness budget)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…m producers (no per-claim preparation); move to the floor

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…licate of the controls; smaller block source (floor budget)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@gunbai-bot
gunbai-bot Bot added this pull request to the merge queue Oct 1, 2026
Merged via the queue into main with commit a4ca162 Oct 1, 2026
4 checks passed
@gunbai-bot
gunbai-bot Bot deleted the session/calm-fox-43-newline-refusal branch October 1, 2026 14:31
gunbai-bot Bot pushed a commit that referenced this pull request Oct 1, 2026
…12881); enrolled evidence named

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants