Skip to content

Disjunction (OR) in rule bodies - #2

Closed
oflatt-claude wants to merge 1 commit into
mainfrom
disjunction
Closed

Disjunction (OR) in rule bodies#2
oflatt-claude wants to merge 1 commit into
mainfrom
disjunction

Conversation

@oflatt-claude

Copy link
Copy Markdown
Owner

Adds disjunction to rule queries:

(rule ((OR ((edge x y))
           ((edge y x))))          ; symmetric closure
      ((connected x y)))

Each branch of an OR is a parenthesized list of facts (a conjunctive subquery); the rule matches when any branch matches. Only variables bound in every branch may be used in the actions.

Status: draft — establishes the contract, backend is being rewritten

This PR currently lands the syntax, semantics, behavioral tests, and design doc. The current backend is a parse-time rule-splitting prototype (it distributes the body into the cartesian product of branch choices, one plain rule per combination).

Per review, rule-splitting is not the target — it has combinatorial blowup and redundant (idempotent) firing. The implementation will move to native execution:

  • Strategy B — materialized union subquery: compile OR to a derived relation R_or(V) = ⋃ᵢ π_V(branchᵢ) over the common variables V, materialized via the existing hypertree-decomposition path in core-relations/src/free_join/plan.rs, then joined as one atom. No blowup, auto-dedup.
  • Strategy C — native union node in the free-join executor: streaming, no materialization; more invasive.

See docs/disjunction-design.md for the full comparison, the seminaive/incremental-maintenance considerations, and code references.

What's here now

  • src/ast/parse.rs — parse (OR ...) and expand a body; also fixes a latent todo!() when a fail sub-command expands to several commands.
  • tests/disjunction.rs — 6 behavioral tests (symmetric closure, cartesian product, nested OR, single-branch, branch-local-var rejection, empty-OR rejection). These are implementation-independent and will guard the B/C rewrite.
  • docs/disjunction-design.md — syntax, semantics, and efficient-execution design.
  • CHANGELOG.md — feature entry.

Tests

  • tests/disjunction.rs: 6/6 pass
  • full .egg harness: 747/747 pass (desugar, 32-thread, proof treatments)
  • make nits: clean

🤖 Generated with Claude Code

Introduce `(OR (branch) (branch) ...)` in rule queries, where each branch is a
parenthesized list of facts (a conjunctive subquery); the rule matches when any
branch matches. Only variables bound in every branch may appear in the actions.

This commit establishes the surface syntax, semantics, behavioral tests, and a
design doc. The current backend is a parse-time rule-splitting prototype that
distributes a body into the cartesian product of branch choices; per review it
will be replaced by a materialized-union subquery (design doc Strategy B) so the
disjunction is executed natively without rule blowup or redundant firing.

- src/ast/parse.rs: parse and expand `OR`; handle multi-command `fail` expansion
- tests/disjunction.rs: 6 behavioral tests (semantics + rejection cases)
- docs/disjunction-design.md: syntax, semantics, and efficient-execution design
- CHANGELOG.md: feature entry

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@oflatt-claude

Copy link
Copy Markdown
Owner Author

Superseded by #7 (the chosen implementation: correlated + seminaive fused OR). Kept the exploration history here; closing to leave the two deliverables (#7 + the encoding change) as the live PRs.

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.

2 participants