Address review: expand named arguments during command macros - #72
Merged
oflatt merged 1 commit intoSep 22, 2026
Merged
Conversation
All three correctness issues in the review share one cause: field names were
registered while parsing. egglog parses a whole program before running any of
it, so a parse-time macro sees declarations in source order, not execution
order.
Expanding in a `CommandMacro` fixes them together, because command macros run
after every preceding command has taken effect:
- A call now sees declarations pulled in by an earlier `(include ...)`, which
had not been read yet when the caller was parsed.
- Field names are recorded per `(name, arity)`, and each call resolves against
the arity the e-graph currently reports for that name, so a declaration that
has been popped or redeclared can no longer rewrite calls.
- Each `...` binds fresh variables from a fixed hint instead of the field
names, which could collide with each other ("x" at 1 and "x1" at 0 both
gave "x1"). The pinned egglog also makes `SymbolGen` collision-free, so this
no longer depends on that fix.
No parse-time macro is left: `:name` and `...` already parse as ordinary
variables, and `:name Sort` pairs already parse as a longer sort list, so the
declaration commands no longer need shadowing. That drops the `set`/`delete`/
`subsume` macros (their arguments are rewritten in place instead), makes every
implementation type private, and shares one field-name validator between
schemas and datatype variants. Named arguments are now registered on the
e-graph rather than the parser, since expansion needs the command stage.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
oflatt-claude
requested review from
saulshanabrook
and removed request for
a team
September 22, 2026 18:19
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.
Addresses the review on #57. Also merges current
maininto the branch, which had conflicts.The three correctness issues share one cause
Field names were registered while parsing. egglog parses a whole program before running any of it, so a parse-time macro sees declarations in source order, never execution order. Moving expansion into a
CommandMacro— which runs after every preceding command has taken effect — fixes all three together.[P1] Ellipsis variables could collide. Each
...now mints fresh variables from a fixed hint, the way wildcard parsing does, instead of from the field names (hintxat count 1 and hintx1at count 0 both producedx1). Worth noting: the pinned egglog now makesSymbolGencollision-free on its own, so the reviewer's repro already passes without this change — the fixed hint removes the dependency on that fix. Regression test:tests/named-args-ellipsis-fresh.egg.[P2] Named calls failed after included declarations. A call now sees declarations pulled in by an earlier
(include ...), because the include has actually run by the time the caller is expanded. Regression test:tests/named-args-include.egg(+tests/named-args-included-defs.egg). Verified failing on the previous implementation withUnbound symbol :x.[P3] Field metadata survived scoped redeclarations. Names are recorded per
(name, arity), and every call resolves against the arity the e-graph currently reports for that name, so a declaration that has been popped or redeclared can no longer rewrite calls. Regression test:tests/named-args-scope.egg, covering both the reviewer's(push)/(pop)/different-arity case and redeclaration at the same arity. Verified failing on the previous implementation.On the storage suggestion:
extension_stateis only reachable from aUserDefinedCommand, andCommandMacro::transformreceives justsymbol_genandtype_info. Sincetype_infois itself push/pop-scoped, resolving through it gives the same guarantee without new egglog API. The registry is not itself scoped, but a stale entry is unreachable — it can only be found through an arity the live type info still reports. This is documented in the module.Succinctness
:nameand...already parse as ordinary variables, and:name Sortpairs already parse as a longer sort list, so the declaration commands no longer need shadowing. Theset/delete/subsumemacros are gone too; those store the table name beside its arguments rather than as a call, so their arguments are rewritten in place.register_named_argsis the only public item.split_fieldsvalidator is shared between schemas and datatype variants.register_named_callis gone with the rest of the parse-time path.named_args.rsdrops from 607 to 494 lines while gaining the fixes.main's pin (upstream egglog9063586), and the lockfile matches the manifest, so--lockedbuilds work.API change
register_named_argsnow takes&mut EGraphrather than&mut Parser, since expansion needs the command stage.new_experimental_egraph()registers it;experimental_parser()on its own no longer provides named arguments.Verification
make testandmake nitsboth pass: 152 nextest tests, doctests,cargo clippy --tests -- -D warnings,cargo fmt --check.🤖 Generated with Claude Code