Skip to content

Finalize Expression's concrete builder combinators (keep the class extendable) - #102

Merged
MidnightDesign merged 1 commit into
masterfrom
97-finalize-expressions-concrete-builder-combinators-keep-the-class-extendable
Jul 23, 2026
Merged

Finalize Expression's concrete builder combinators (keep the class extendable)#102
MidnightDesign merged 1 commit into
masterfrom
97-finalize-expressions-concrete-builder-combinators-keep-the-class-extendable

Conversation

@MidnightDesign

Copy link
Copy Markdown
Contributor

Closes #97. Scoped for the 0.3.0 breaking release.

What

Finalize the 17 concrete builder combinators on Expressioneq, neq, add, subtract, multiply, divide, modulo, gt, lt, gte, lte, or_, and_, not, call, matchesType, isSubtypeOf. These are fixed algorithms that assemble the closed, @internal-constructed node set, so a subclass has no legitimate reason to override them.

The class stays abstract (not final) and its four extension-point methods — location, evaluate, equals, getType — stay abstract and overridable. Subclassing Expression to add a custom node still works exactly as before; only the combinators are locked.

Return types are left untouched — narrowing them to self and collapsing Eq/Gt is the separate #92.

Changes

  • src/Expression.phpfinal on the 17 concrete combinators.
  • tests/unit/ExpressionFinalizationTest.php (new) — reflection guard test matching the repo's structural-invariant style (see InternalAnnotationConsistencyTest): asserts the class stays open/abstract, every combinator is final, and each extension point stays abstract and overridable.
  • UPGRADING.md — API-changes note documenting the structural break.

BC impact

Structural break: finalizing previously-published methods. Correct for a 0.MINOR bump; the Roave checker will flag it as expected (it can't run in a worktree, so it isn't run here).

Verification

  • phpunit — 1152 tests pass (22 new)
  • psalm, phpstan — no errors
  • php-cs-fixer, composer-require-checker — clean
  • infection-diff (CI's 100% MSI gate on changed lines) — 16/16 mutations killed, Covered MSI 100%

🤖 Generated with Claude Code

The 17 concrete builder combinators (eq, neq, add, subtract, multiply,
divide, modulo, gt, lt, gte, lte, or_, and_, not, call, matchesType,
isSubtypeOf) are fixed algorithms that assemble the closed, internal
node set. A subclass has no legitimate reason to override them, so
finalize them. The class stays abstract/open and its four extension-point
methods (location, evaluate, equals, getType) stay overridable, so
subclassing to add a node still works.

Add a reflection guard test pinning the invariant, and document the
structural break in UPGRADING.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QUqJ7TWSpSRT1fVinWVRPf
@MidnightDesign
MidnightDesign merged commit 4fa6486 into master Jul 23, 2026
25 checks passed
@MidnightDesign
MidnightDesign deleted the 97-finalize-expressions-concrete-builder-combinators-keep-the-class-extendable branch July 23, 2026 14:44
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.

Finalize Expression's concrete builder combinators (keep the class extendable)

1 participant