Skip to content

refactor(program): the resolved where vocabulary lives beside the nodes a consumer dispatches on - #321

Closed
FBumann wants to merge 2 commits into
feat/mask-statefulfrom
feat/where-vocabulary
Closed

refactor(program): the resolved where vocabulary lives beside the nodes a consumer dispatches on#321
FBumann wants to merge 2 commits into
feat/mask-statefulfrom
feat/where-vocabulary

Conversation

@FBumann

@FBumann FBumann commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Prompt: "Changing what lives in .root?" / "I think we should do both."

Note

The following content was generated by AI.

The resolved where-node classes, their unions and the question functions (atoms, names_read, dims_read) move from where_parser into program, so a consumer dispatches on masks and expressions out of one module. where_parser keeps the grammar, parse_where and the Unresolved* nodes resolution rewrites away, importing the four node classes it constructs from program — the dependency inverts, and stays acyclic.

program.WhereNode is the resolved-only union (the old one carried the Unresolved* members); parse_where's docstring says its annotation is the type a tree has once resolution types every leaf. That forced honest internal signatures in resolution.py: the error paths that return a node unresolved now say so, with one _resolved_child helper carrying the invariant that a tree rebuilt over an unresolved node never escapes resolve_where/resolve_expression.

A line held here, superseded two PRs up the stack: the free atoms/names_read/dims_read stay public at this point because a consumer holding a synthetic predicate (a NotNode complement, an AndNode conjunction it built itself) has no Mask to ask. #324 removes the reason — leaves carry their own dims, so Mask(root) wraps any resolved predicate — and retires the free functions, on the same reviewer's proposal. The NameDims alias this PR gives dims_read's mapping goes with them, so this PR should land only with the rest of the stack.

Stacked on #319.

Verified

pixi run ci exit 0 in this worktree: lint clean (pyrefly 0 errors), 931 passed (930 + one new pin: the connectives parse_where builds are identical class objects to program's), mkdocs build --strict builds, 27 TeX documents compile. Both import orders smoke-tested (where_parser first and program first). schema/ and tests/typesetting/golden/ byte-identical — nothing that renders or validates changed behaviour, only where the classes live.

The failing-first guard for this PR is structural: tests/test_public_surface.py asserts program.__all__ equals every top-level public definition in both directions, so the move without the 19 new __all__ entries fails it.

Deliberately not done: per-atom dims on the node classes (nothing asks yet), and any behaviour change — a consumer's isinstance answers exactly as before, only the import path moved. Breaking for importers of math_spec.where_parser's resolved names, described here rather than in the title per the refused breaking-marker rule; a consumer bumping across this should sweep every where_parser import wholesale, since the re-imported connectives keep resolving on the old path by accident while the leaf classes raise.

@read-the-docs-community

read-the-docs-community Bot commented Sep 1, 2026

Copy link
Copy Markdown

…es a consumer dispatches on

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D59sEp5d7CecJAwrzACbRh
@FBumann
FBumann force-pushed the feat/where-vocabulary branch from 587dfef to 9f28164 Compare September 1, 2026 14:15
…s a name, NameDims

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D59sEp5d7CecJAwrzACbRh
@FBumann

FBumann commented Sep 1, 2026

Copy link
Copy Markdown
Contributor Author

Note

The following content was generated by AI.

Superseded by #327, which combines the reviewed stack into a single diff on the maintainer's call. The review history — two consumer reviews and one consolidated agent review, with mutation tables — lives in this stack's bodies; the tree at #327 is byte-identical to the stack's top.

@FBumann FBumann closed this Sep 1, 2026
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.

1 participant