package compile

Import Path
	github.com/freeeve/gochickpeas/gql/internal/compile (on go.dev)

Dependency Relation
	imports 12 packages, and imported by one package

Involved Source Files Per-candidate predicate specialization: during one bind-chain level's candidate iteration every row slot except the level's own is fixed, so a pushed-down conjunct is a unary function of the candidate id. The dominant conjunct shape -- the fused prop-vs-const comparison -- runs as a monomorphic closure reading its hoisted typed column directly, skipping the compiled tree's dispatch and per-candidate boxing. Every pairing whose comparison semantics are not trivially same-kind boxes the column value once and routes through value.Compare, so results are exactly the general path's (missing property = failed compare = Null = prune, for all six operators). Per-row evaluation of a compiled expression, mirroring the interpreter exactly (the shared eval kernels keep the arithmetic, comparison, and function semantics identical). Expr -> CExpr lowering: hot leaves (slots, property reads) carry resolved indices/readers; correlated subqueries gain a result memo keyed on their outer reads; scalar functions with constant arguments fold at compile time; the remaining rarely-hot nodes fall back to the interpreter. Correlated-subquery decorrelation setup: recognizing a cheap bound-pair EXISTS probe, computing a subquery's outer-slot memo key, and marking a COUNT{} decorrelatable when it is a fixed linear chain between two outer-bound endpoints with no other outer dependency (evaluated once per anchor instead of a DFS per row). Split from compile.go, which holds the compiled-node types and the expression compiler. Canonical identity for a decorrelated COUNT{} side table: a byte string over the subquery's pattern and WHERE with the anchor and group variables substituted by positional markers, so two sibling subqueries differing only in what the outer query names those endpoints (BI Q8's C1(person)/C1(friend)) canonicalize identically and share one table per anchor node. Fail-closed: any construct the encoder does not cover yields no identity and the node keeps a private table -- sharing is an optimization, never a semantic commitment. Parameters encode by slot or name, which is sound because tables are shared only within one execution's Ctx, where parameter values are fixed. IN-list hoisting and slot analysis: a batch-constant list bakes to a prebuilt membership index (cInConst); a loop-invariant carried list rebuilds once per match-call (cInCarried); Slots reports the row slots a compiled expression reads for WHERE pushdown. Package compile lowers a bound expression into a CExpr whose leaves carry resolved row slots and typed Snapshot column readers, so per-row evaluation does no string hashing (the var->slot and key->column lookups happen once at stage compile). Evaluation mirrors the interpreter exactly; nodes not worth specializing fall back to it. Port of the Rust compile.rs -- the one package besides the graph seam that touches the engine directly. Whole-row predicate specialization: a comparison whose sides are property reads over typed i64 columns (optionally shifted by a constant integer or months-free duration) -- the dominant fully-bound filter shape, e.g. a temporal ordering between two pattern variables -- runs as a monomorphic closure reading both columns directly, skipping the compiled tree's dispatch and per-row boxing. A slot-vs-slot comparison flattens to one shared-kernel Compare call. Rows whose slots do not hold nodes fall back to the full tree evaluation, so results are exactly the general path's for every input.
Package-Level Type Names (total 4)
/* sort by: | */
CandBatch sweeps a whole candidate buffer for one conjunct: it clears keep[i] for every candidate that fails, touching only still-kept entries. The batch form exists for shapes whose per-candidate work is pure array arithmetic -- no closure call, no dispatch per element. func CandidateBatch(c *Compiled, slot int) (CandBatch, bool)
CandPred reports whether the conjunct holds for a node candidate bound at its specialized slot. The row carries the level's fixed outer bindings -- only the carried-list rebuild (once per match-call epoch) reads it; hot paths touch the candidate alone. func CandidatePred(c *Compiled, slot int, slots map[string]int) (CandPred, bool)
Compiled is a compiled expression bound to a snapshot; it satisfies the executor's RowEval seam. fast, when derivable, is the whole-expression monomorphic form (rowfast.go), result-identical to the tree. Eval evaluates the compiled expression against a row -- identical in result to the interpreter on the source expression. *Compiled : github.com/freeeve/gochickpeas/gql/internal/exec.RowEval func HoistCarriedIn(c *Compiled, isCarried func(int) bool) *Compiled func HoistConstIn(ctx *eval.Ctx, c *Compiled, isConst func(int) bool, sample []value.Value, slots map[string]int) *Compiled func New(ctx *eval.Ctx, e ast.Expr, slots map[string]int, g *chickpeas.Snapshot) *Compiled func CandidateBatch(c *Compiled, slot int) (CandBatch, bool) func CandidateIntSweep(c *Compiled, slot int) (IntSweep, bool) func CandidatePred(c *Compiled, slot int, slots map[string]int) (CandPred, bool) func HoistCarriedIn(c *Compiled, isCarried func(int) bool) *Compiled func HoistConstIn(ctx *eval.Ctx, c *Compiled, isConst func(int) bool, sample []value.Value, slots map[string]int) *Compiled func Slots(c *Compiled) (refs []int, hasSlow, hasWalk bool)
IntSweep bulk-filters a candidate chunk over an i64 NODE column against a folded constant: one GetMany then a hoisted compare loop -- the batch form of the cCmpPropConst per-candidate predicate for columns the windowed CandidateBatch cannot serve (narrow storage classes) and constants it declines (temporals, which fold to their epoch millis and compare through the exact int order, per constI64Val). vals/present are caller scratch of at least len(ids); keep is the running mask. Candidates must be node ids, the same contract as CandidateBatch. func CandidateIntSweep(c *Compiled, slot int) (IntSweep, bool)
Package-Level Functions (total 8)
CandidateBatch specializes c to a buffer sweep when its shape allows the columnar form: today the fused prop-vs-const comparison over an i64 column with a contiguous-presence window (SliceRange), where the filter reduces to vals[id-start] compared against a pre-encoded constant -- the dominant pushed-down filter shape over LDBC-style label-block columns. Semantics mirror the scalar predicate exactly (value.Compare's float64 partial order; out-of-window = absent = prune). ok=false keeps the scalar path.
CandidateIntSweep specializes a compiled conjunct to an IntSweep; ok=false leaves the caller on the per-candidate path.
CandidatePred specializes c when its only per-candidate dependency is the node at slot and its shape is the fused prop-vs-const comparison or a constant- or carried-list membership over the candidate's property (or over the candidate itself: a bare-variable element probes the node value directly, no read at all); ok=false keeps the general row evaluation.
ConstValue reports the expression's compile-time constant value: the bottom-up literal folding is the one authority on constness (a slot or property read never folds), so ok=false exactly when evaluation could depend on a row. slots must be the caller's real slot map -- with an empty map an unbound name folds to a null LITERAL, which would launder row-dependent expressions (coalesce(m.ts, d) folds to d) into constants.
HoistCarriedIn rewrites remaining IN nodes whose list reads only carried-in slots (loop-invariant per match-call, not batch-constant) into the per-epoch cached form. Applied after HoistConstIn so batch-constant lists keep their cheaper baked set.
HoistConstIn rewrites IN nodes whose list is invariant over the row batch (every slot it reads is batch-constant, no slow node) into a baked membership index, evaluated once against a sample row.
New compiles e against the segment's slots and snapshot. Parameters resolve at compile time (their values are constant for the execution).
Slots collects the row slots a compiled expression reads; hasSlow is set for nodes whose inner references aren't slot-resolved (interpreter fallbacks, functions, subqueries without a memo set). A memoized subquery reads exactly its memo slots, so it can push down to where its correlated bindings bind -- but hasWalk reports it separately, because the memo only bounds REPEAT cost: on every distinct correlation tuple the subquery still walks the graph, so its placement must respect walk cost, not just read placement (task 115: classify by what the predicate DOES, not by which evaluation path it takes).
Package-Level Variables (only one)
SubqueryWalks counts actual correlated-subquery graph walks (memo misses and unmemoized evaluations) -- the load-independent oracle for predicate-placement tests: a walk that runs before a shrinking op is visible as walk count, never as a row difference.