Repository navigation
Chained hops folded: mask-risc GatherChain, Quack Filter::Chain, glove out(r1).out(r2) (D-CMH-G1-7) - #1522
Chained hops folded: mask-risc GatherChain, Quack Filter::Chain, glove out(r1).out(r2) (D-CMH-G1-7)#1522AdaWorldAPI wants to merge 5 commits into
Conversation
MaskOp::GatherChain { lane, chain, under, dst } with Program::chains:
dst[i] holds when the key lane[i] leads through every hop of the named
chain, each hop's reached row live in its resident foreign plane, passing
its HopTests read in place, and the hop's next lane keying the following
hop. No mask over any hop table is built and no program feeds another;
the op realises through ndarray::simd::mask_gather_chain_u32[_under].
Gather could only test a target through a plane over the target's table,
so a depth-2 predicate needed a depth-1 mask built first and a Keep fed
into another program's Gather, the shape the ScatterOrU32 survival
condition forbids.
- validate: chain exists, non-empty, <= MAX_CHAIN_HOPS hops,
<= MAX_HOP_TESTS tests, next on every hop but the last, planes and
U32 lanes long enough (ChainOutOfRange / ChainShape / LenMismatch),
so the facade's shape panics are unreachable.
- executor builds the facade chain on the stack (L1 holds; test).
- oracle walks the chain from the IR, never through the facade.
- tests/chain.rs: executor, oracle and a fixture row loop agree, gated
and ungated, across tile boundaries; one bare hop equals Gather;
eight refusals identical on both paths.
- exhaustive matches in quack and glove-parity extended.
Needs AdaWorldAPI/ndarray#358 (mask_gather_chain_u32).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011BMJnDBAfzcuQh5HeT39Rh
Filter::Chain { fk, hops: Vec<ChainHop> } — the chained semijoin, hops
each a RESIDENT plane, in-place tests and the key onward. gate_walk turns
it into Node::GatherChain; index_chains moves the hops into the program's
chain table; both emitters (in place and fused) emit one
MaskOp::GatherChain carrying the gate. NULL fk follows Semijoin (FALSE,
not UNKNOWN).
Test: two hops, a test at each depth, an out-of-range key and a dead
partner row; both lowerings emit exactly one GatherChain with both hops
and no Gather, and the count matches a per-row reading of the filter.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011BMJnDBAfzcuQh5HeT39Rh
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011BMJnDBAfzcuQh5HeT39Rh
|
Warning Review limit reachedYour organization has reached its usage spending cap. Adjust your spending cap in the billing tab. Next included review available in 19 minutes. View limit details
Warning Billing warning: we have not been able to collect payment for this subscription for more than 72 hours. Please update the payment method or pay any pending invoices in Billing to avoid service interruption. Comment |
Path (1..=MAX_PATH relations, Copy) and Cond::ReachesPath / ViaPath for a
path two relations or longer. Preparation walks each relation on the
previous one's target glove; every condition on a maximal path and on its
prefixes binds into ONE BoundCond::Chain (Filter::Chain, one
MaskOp::GatherChain): hop k's live plane, the tests the conditions put
on it, and the next key, which must be a proven Code field the call
supplies as a foreign lane (NoForeignLane otherwise). One-relation paths
no chain extends keep their semijoin / EqU32Via leaves unchanged. Every
target universe along the path is checked at the call. R2IL names the
missing GATHER.
Gremlin: out after out extends the path (SecondHop is gone; PathTooDeep
past MAX_PATH); has after it is a ViaPath; dedup, values, min/max after a
path of two are refused. The text form and the awareness graph carry the
path.
tests/two_hop.rs: line -billed_to-> partner -located_in-> region against
a row loop over the text at n in {1,64,65,4097}, tests at either hop,
negated, with a local condition; the lowering is one chain with the hop-1
test folded in; composer, text form and awareness; refusals. The
relation.rs SecondHop pin is re-pinned: a second hop now composes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011BMJnDBAfzcuQh5HeT39Rh
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011BMJnDBAfzcuQh5HeT39Rh
|
CI on this PR (clippy, member-tests, parity, cats, dir-sim) is red because this branch calls ndarray#358 is green on every check. Once it merges, a re-run here builds against the new primitive; locally the full suites already pass against it. Nothing to fix in this PR until then. Generated by Claude Code |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3eaf15f370
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if let Cond::Via { | ||
| field, | ||
| literal, | ||
| negate, | ||
| .. | ||
| } = *c |
There was a problem hiding this comment.
Handle one-hop ViaPath conditions
When a caller constructs Cond::ViaPath with Path::of(&[rel]), this branch emits only the relation-liveness check because it recognizes Cond::Via but not Cond::ViaPath, silently dropping the field comparison and returning extra rows. This is a representable public input—Path explicitly accepts lengths starting at one—so bind a one-hop ViaPath like Via or reject it during preparation.
Useful? React with 👍 / 👎.
|
I'm closing this without merging. It models chained hops as per-row key reads, and the graph has no foreign keys: a hop is a coordinate range, and chained hops are the intersection of ranges. D-TELEPORT-0 (#1484) had already measured this gather shape as speeding up work rather than eliminating it. The branch is kept as Generated by Claude Code |
…#1522 closed) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011BMJnDBAfzcuQh5HeT39Rh
Depends on AdaWorldAPI/ndarray#358 (
mask_gather_chain_u32[_under]). CI checks out ndarraymasterwith no pin, so this PR's CI goes green only after #358 merges.What
Chained hops are folded hops.
out(r1).out(r2)…over functional relations becomes ONE op. Each hop is one more aperture in the same pass, and the only thing materialized is the op's destination over the anchor table's rows. No mask over any hop table exists, and no program feeds another.mask-risc
New op
MaskOp::GatherChain { lane, chain, under, dst }. The chain it names lives in the new fieldProgram::chains: Vec<Vec<Hop>>.Each
Hopnames a resident foreign plane (live), up to 8HopTests read in place at the row the key reached, and anextkey lane (present on every hop except the last).The executor runs the op through
ndarray::simd::mask_gather_chain_u32[_under].The facade chain is built on the stack, bounded by
MAX_CHAIN_HOPS/MAX_HOP_TESTS= 8, so L1 holds:executestill allocates nothing.Validation runs before the facade and refuses:
ChainOutOfRange);ChainShape): empty, over the caps, ornextplaced wrong;This makes the facade's shape panics unreachable.
The oracle walks the chain from the IR and never calls the facade.
Quack
Filter::Chain { fk, hops }.GatherChain, with the gate baked in.Semijoin: the leaf is FALSE.Glove / composer (plan §11)
Pathtype (1..=MAX_PATHrelations) and new conditionsCond::ReachesPath/Cond::ViaPath. One-hop conditions are unchanged.Codefield the call supplies; otherwise preparation returnsNoForeignLane.GATHER.outafteroutextends the path; pastMAX_PATHit is refused withPathTooDeep, which replacesSecondHop.hasafter that is aViaPath.dedup,valuesandmin/maxafter a path of two are refused.Why a new op:
Gathercan test a target only through a plane over the target's table. A depth-2 predicate would therefore need a depth-1 mask built first, with one program'sKeepfeeding another program'sGather. That is the shape theScatterOrU32survival condition forbids. #1521 built exactly that shape and is closed.Tests
mask-risc/tests/chain.rs: the executor, the oracle and a fixture row loop all agree, gated and ungated, across tile boundaries; one bare hop equalsGather; eight refusals behave the same on both paths.no_alloc.rs: 1000 gated two-hop executes allocate 0 bytes.GatherChainand match a per-row reading of the filter.glove-parity/tests/two_hop.rscoversline -billed_to-> partner -located_in-> region:tests/relation.rs: the oldSecondHoprefusal now composes.negate; validation no longer checks thenextshape.negate; emits a plainGather; oracle stops at depth 1.cargo clippy -D warningsis clean on mask-risc, Quack and glove-parity, andcargo fmtis clean. The full suites of all three are green locally.Board: STATUS_BOARD row D-CMH-G1-7, entry
2026-10-12-chained-hops-folded.md, plan §11.Open
The M:N hop through two edge tables (run-level OR) still needs a decision.
🤖 Generated with Claude Code
https://claude.ai/code/session_011BMJnDBAfzcuQh5HeT39Rh