Skip to content

refactor(syntax): generalize the macro repetition separator node - #10310

Open
orizi wants to merge 1 commit into
graph-plan/2026-08-03-macro-fixes/capture-fidelity.f1-parenthesize-expr-capturesfrom
graph-plan/2026-08-03-macro-fixes/separator-grammar.sep-grammar-thread
Open

orizi wants to merge 1 commit into
graph-plan/2026-08-03-macro-fixes/capture-fidelity.f1-parenthesize-expr-capturesfrom
graph-plan/2026-08-03-macro-fixes/separator-grammar.sep-grammar-thread

Conversation

@orizi

@orizi orizi commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

MacroRepetition.separator was OptionTerminalComma, baking the only separator
the parser currently accepts into the grammar. Replace it with
OptionMacroRepetitionSeparator, wrapping a MacroRepetitionSeparator struct
whose single token child is a TokenNode — the codegen's all-terminals enum —
so the grammar can hold any terminal as a separator.

An option must wrap a node that has a SyntaxKind, and enums do not get one
(generate_kinds_code filters NodeKind::Enum out), hence the small wrapper
struct — the same reason TokenTreeLeaf wraps TokenNode. The syntax crate is
regenerated by generate-syntax, not hand-edited.

Behavior is unchanged. The parser still accepts only TerminalComma in that
slot, and the semantic matcher and expansion still treat only a comma as a
separator, now via a single repetition_separator helper that returns None
for any other token — the same branch as "no separator" — rather than
panicking, so loosening the parser later cannot introduce a panic.
$($x:ident);* is still rejected with the same Missing macro repetition operator diagnostic. The only golden churn is in the parser partial_trees:
OptionTerminalCommaEmpty becomes OptionMacroRepetitionSeparatorEmpty, and
existing comma separators gain the MacroRepetitionSeparator level. No semantic
golden changed.

TokenTreeRepetition.separator is deliberately left as OptionTerminalComma.
The adjacent TODO(Dean): Remove TokenTreeRepetition and TokenTreeParam (it's redundant) intends to delete that node outright, so migrating it would be churn
on code slated for removal and would couple the call-site token-tree grammar to
the macro-rule grammar that TODO wants to disentangle. That refactor is
explicitly not folded in here; .add_option("TerminalComma") stays for it and
becomes dead only once it lands.

The unreachable!() on ast::MacroParamKind::Missing in macro_declaration.rs
is not made reachable by this change, so no guard was added. The accepted token
language is identical before and after, so no new tree shape is produced, and
the separator slot is structurally disjoint from ParamKind. Checked
empirically that it also stays unreachable in general: macro m { ($x:foo) => { 1 }; } reports Missing tokens. Expected a macro rule parameter kind. and the
rule is then dropped by the descendants(..).any(is_missing) filter in
priv_macro_declaration_data, so the matcher never converts a missing param
kind. That filter is unaffected here — OptionMacroRepetitionSeparatorEmpty is
a plain struct kind, not a missing kind, exactly like the
OptionTerminalCommaEmpty it replaces.

Co-Authored-By: Claude Fable 5 noreply@anthropic.com

@reviewable-StarkWare

Copy link
Copy Markdown

This change is Reviewable

orizi commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator Author

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more

This stack of pull requests is managed by Graphite. Learn more about stacking.

@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/capture-fidelity.f1-parenthesize-expr-captures branch from ed9467d to 86cbcf4 Compare August 4, 2026 08:41
@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/separator-grammar.sep-grammar-thread branch 2 times, most recently from 931afdd to be641de Compare August 4, 2026 08:56
@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/capture-fidelity.f1-parenthesize-expr-captures branch from 86cbcf4 to 03aed4c Compare August 4, 2026 08:56
@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/separator-grammar.sep-grammar-thread branch from be641de to e0049dd Compare August 5, 2026 10:54
@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/capture-fidelity.f1-parenthesize-expr-captures branch from 03aed4c to 524388b Compare August 5, 2026 10:54
@orizi
orizi marked this pull request as ready for review August 5, 2026 11:10
@cursor

cursor Bot commented Aug 5, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
Parser and semantic behavior for macro repetitions is preserved; changes are mainly AST shape and codegen with updated test goldens.

Overview
Replaces MacroRepetition’s separator in the Cairo grammar from a comma-only OptionTerminalComma to OptionMacroRepetitionSeparator, which wraps a MacroRepetitionSeparator node whose child is a generic TokenNode. That aligns the AST with codegen’s ability to represent any terminal in the separator slot, without changing what users can write today.

The parser still only accepts a comma there (with a TODO to widen parsing later) but now builds the new wrapper shape. Semantics centralizes separator handling in repetition_separator, which still treats only a comma as a real separator and maps any other token to “no separator” so future parser loosening cannot panic. Parser partial-tree goldens reflect the extra AST level; TokenTreeRepetition keeps OptionTerminalComma on purpose.

Behavior is intended to be unchanged for macro rules: matching, expansion, and diagnostics (e.g. separator with ?) stay the same.

Reviewed by Cursor Bugbot for commit ec7ba69. Bugbot is set up for automated code reviews on this repo. Configure here.

@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/separator-grammar.sep-grammar-thread branch from e0049dd to df241a0 Compare August 5, 2026 11:59
@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/capture-fidelity.f1-parenthesize-expr-captures branch from 33168c9 to 519e671 Compare August 17, 2026 18:40
@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/separator-grammar.sep-grammar-thread branch from 579ae55 to 3165739 Compare August 17, 2026 19:07
@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/capture-fidelity.f1-parenthesize-expr-captures branch from 519e671 to 1a0a27c Compare August 17, 2026 19:07
@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/separator-grammar.sep-grammar-thread branch from 3165739 to d21cca4 Compare August 23, 2026 08:43
@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/capture-fidelity.f1-parenthesize-expr-captures branch from 1a0a27c to 8ab7d32 Compare August 23, 2026 08:43
@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/separator-grammar.sep-grammar-thread branch from d21cca4 to 92a2c32 Compare August 23, 2026 08:50
@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/capture-fidelity.f1-parenthesize-expr-captures branch 2 times, most recently from a2b6efa to 5369cd5 Compare August 23, 2026 10:31
@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/separator-grammar.sep-grammar-thread branch from 92a2c32 to 206cb86 Compare August 23, 2026 10:31
@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/capture-fidelity.f1-parenthesize-expr-captures branch from 5369cd5 to ce73864 Compare August 23, 2026 11:22
@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/separator-grammar.sep-grammar-thread branch from 206cb86 to 737f5e6 Compare August 23, 2026 11:22

@orizi orizi left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@orizi+AGNT made 1 comment and resolved 1 discussion.
Reviewable status: 0 of 8 files reviewed, all discussions resolved (waiting on TomerStarkware).


crates/cairo-lang-syntax-codegen/src/cairo_spec.rs line 911 at r1 (raw file):

Previously, eytan-starkware+AGNT (Agent AGNT for eytan-starkware) wrote…

after this change OptionTerminalComma exists only for TokenTreeRepetition (l.825). move it up next to that node so it's obvious it dies together with the TODO(Dean): Remove TokenTreeRepetition.

Done - moved next to TokenTreeRepetition with a note that it goes away together with it; syntax regenerated.

@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/capture-fidelity.f1-parenthesize-expr-captures branch from ce73864 to 9601577 Compare August 23, 2026 12:03
@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/separator-grammar.sep-grammar-thread branch 2 times, most recently from 5109fa0 to 79c24e3 Compare August 25, 2026 12:30
@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/capture-fidelity.f1-parenthesize-expr-captures branch 2 times, most recently from 0e35946 to dcfcdf2 Compare August 26, 2026 19:59
@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/separator-grammar.sep-grammar-thread branch 3 times, most recently from aa2dab6 to e6cba8d Compare August 27, 2026 13:33
@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/capture-fidelity.f1-parenthesize-expr-captures branch 2 times, most recently from a8121d3 to f256911 Compare August 28, 2026 10:07
@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/separator-grammar.sep-grammar-thread branch 2 times, most recently from 9b464cf to c71ea1c Compare August 28, 2026 12:58
@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/capture-fidelity.f1-parenthesize-expr-captures branch from f256911 to 9c68261 Compare August 28, 2026 12:58
@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/capture-fidelity.f1-parenthesize-expr-captures branch from 9c68261 to c99f95d Compare September 14, 2026 04:51
@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/separator-grammar.sep-grammar-thread branch from c71ea1c to 3bf564a Compare September 14, 2026 04:51
`MacroRepetition.separator` was `OptionTerminalComma`, baking the only separator
the parser currently accepts into the grammar. Replace it with
`OptionMacroRepetitionSeparator`, wrapping a `MacroRepetitionSeparator` struct
whose single `token` child is a `TokenNode` — the codegen's all-terminals enum —
so the grammar can hold any terminal as a separator.

An option must wrap a node that has a `SyntaxKind`, and enums do not get one
(`generate_kinds_code` filters `NodeKind::Enum` out), hence the small wrapper
struct — the same reason `TokenTreeLeaf` wraps `TokenNode`. The syntax crate is
regenerated by `generate-syntax`, not hand-edited.

Behavior is unchanged. The parser still accepts only `TerminalComma` in that
slot, and the semantic matcher and expansion still treat only a comma as a
separator, now via a single `repetition_separator` helper that returns `None`
for any other token — the same branch as "no separator" — rather than
panicking, so loosening the parser later cannot introduce a panic.
`$($x:ident);*` is still rejected with the same `Missing macro repetition
operator` diagnostic. The only golden churn is in the parser partial_trees:
`OptionTerminalCommaEmpty` becomes `OptionMacroRepetitionSeparatorEmpty`, and
existing comma separators gain the `MacroRepetitionSeparator` level. No semantic
golden changed.

`TokenTreeRepetition.separator` is deliberately left as `OptionTerminalComma`.
The adjacent `TODO(Dean): Remove TokenTreeRepetition and TokenTreeParam (it's
redundant)` intends to delete that node outright, so migrating it would be churn
on code slated for removal and would couple the call-site token-tree grammar to
the macro-rule grammar that TODO wants to disentangle. That refactor is
explicitly not folded in here; `.add_option("TerminalComma")` stays for it and
becomes dead only once it lands.

The `unreachable!()` on `ast::MacroParamKind::Missing` in `macro_declaration.rs`
is not made reachable by this change, so no guard was added. The accepted token
language is identical before and after, so no new tree shape is produced, and
the separator slot is structurally disjoint from `ParamKind`. Checked
empirically that it also stays unreachable in general: `macro m { ($x:foo) => {
1 }; }` reports `Missing tokens. Expected a macro rule parameter kind.` and the
rule is then dropped by the `descendants(..).any(is_missing)` filter in
`priv_macro_declaration_data`, so the matcher never converts a missing param
kind. That filter is unaffected here — `OptionMacroRepetitionSeparatorEmpty` is
a plain struct kind, not a missing kind, exactly like the
`OptionTerminalCommaEmpty` it replaces.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/separator-grammar.sep-grammar-thread branch from 3bf564a to ec7ba69 Compare September 14, 2026 06:56
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.

3 participants