ddn.df.expr
The typed, inspectable expression layer of ddn.df (ADR-2026-10-24-16, amended 2026-10-29): composable column computations as a tagged-struct AST - column references, literals, unary/binary operators, aggregations, casts, conditionals, aliases and window (over) wrappers - evaluated against a DataFrame by a tree interpreter that reuses the existing eager kernels, including the scalar-literal fast dispatch. No new computation paths: results are bitwise-identical to the eager chains.
Structure is inspectable without evaluating data: kind, children, dependencies and resolve(schema) expose the tree, its column dependencies and its dtype/nullability/cardinality metadata. Construction is schema-free and non-throwing for unknown columns (they surface at collection); structural misuse - aggregations over computed expressions, aggregates mixed with row expressions - is rejected at construction.
Aggregations (col("v").sum() and friends) evaluate standalone as global length-1 reductions through the Series aggregation kernels; wrapped in .over(keys) they dispatch to the partitioned-aggregate kernels (dtype-preserving). A bare col("v").over(keys) keeps the historical per-partition first-row scatter with FLOAT64 output - the compatibility form. The list collect aggregation has no expression form (it needs the grouping context).
Copyright
Types 7
The kind of one expression AST node.
The value space of a literal node.
One literal value: the kind discriminator plus the payload slots (only the active kind's slot is meaningful).
The row cardinality an expression produces: a broadcastable length-1 result (SCALAR), one value per input row (ROW), a global length-1 reduction (AGGREGATE) or a partitioned aggregate scattered back to input rows (WINDOW).
One named column of an input schema: a name and dtype pair.
The resolved metadata of one expression against an input schema.
A typed, deferred column computation: an inspectable AST. Constructed with col(name) or lit(value), composed with D's operators (`*`, `+`, `>`, ...) and comparison/logic methods (.gt, .and, ...), aggregated (.sum(), .quantile(q), ...), cast (.castTo), renamed (.rename) and wrapped in windows (.over), then evaluated against a frame - reusing the eager kernels, no new computation paths. The output name defaults to a rendering of the tree.
string labelThe expression's output name (rendered from the tree shape).private ExprKind _kindprivate Expr[] _childrenprivate string _nameprivate LiteralValue _literalprivate string _opprivate AggKind _aggprivate double _aggParamprivate DataType _castTargetprivate bool _castStrictprivate string[] _keysbool isWindow() const @safe pure nothrowWhether the tree contains an `over` window (blocking for streaming; see ADR-2026-10-24-18).bool isAggregate() const @safe pure nothrowWhether the tree holds an aggregation outside an `over` wrapper: a length-1 reduction. Row-wise plan operations reject such expressions, and they may only combine with scalars or other aggregates.string[] dependencies() @safe pureThe input columns the expression references (unique, in first appearance order), without evaluating any data. `over` keys are dependencies of their own.ExprInfo resolve(DataFrame df) @safeResolves the expression against a frame's schema (column names and dtypes only; no data is touched).ExprInfo resolve(scope ColumnSchema[] schema) @safeResolves the expression against an explicit input schema: the output dtype, conservative nullability, row cardinality and column dependencies. This is the inspection entry the plan layer and the op...Series evaluate(DataFrame df) @trustedEvaluates the expression against a frame: a tree walk that dispatches each node to the eager kernels.Expr rename(string name) @safeRenames the output (an alias node; evaluation renames the child's result).Expr castTo(DataType target, bool strict = true) @safeCasts the output to a target dtype (the eager `castTo`: strict by default; out-of-range and unsupported casts throw at evaluation).Expr over(string[] keys...) @safePartitions the frame by keys and evaluates the expression per partition, scattering each partition's result back to every input row of that partition (the `over` semantics of ADR-2026-10-24-17). Th...Expr when(Expr a, Expr b) @safeSelects between two branches by this BOOLEAN expression (the eager `when` kernel: promoted branches; length-1 operands broadcast to the common height at evaluation).string outputName() @safe pure nothrowThe column name evaluation produces for this expression (the kernels' naming rule): literals are `"lit"`, column references carry their column name, unary/cast results and when branches carry their...bool aggSpec(out AggSpec spec) @safe pure nothrowConverts this expression (through alias chains) to the eager aggregation specification it maps to: the aggregation's kind, parameter and column, with the outermost alias label as the output name. T...Series evaluateAgg(DataFrame df)bool isTotal() @safe pure nothrowWhether the expression is provably total: direct column references and literals only. These produce the same values (or the same absence) on any row subset, so plan rewrites may move row-dependent ...bool isColumnRefOf(string name) @safe pure nothrowWhether this expression is the identity reference of `name`.Functions 23
bool exprEq(Expr a, Expr b) @safe pure nothrowStructural equality of two expressions: same shape, same payload and same labels, recursively over the children. Deterministic trees built the same way compare equal; the comparison is exact (a NaN...size_t columnRefCount(Expr e, string name) @safe pure nothrowThe number of direct column references to `name` in the tree - the positions an inline substitution would replace. `over` partition keys reference columns by name without a reference node and are N...bool overKeyRef(Expr e, string name) @safe pure nothrowWhether any `over` node in the tree partitions by `name`: such a key reads the materialised column and cannot take an inlined expression in its place, so fusion rules must stand down.Expr substRef(Expr e, string name, Expr repl) @safeReplaces every direct column reference to `name` with `repl`, rebuilding the surrounding nodes through the same construction paths a hand-written tree takes (labels included; the replacement is ins...Series scalarColumnBinary(string op, Series scalar, Series column,
bool scalarOnLeft, out bool handled)Series scalarTypedBinary(T)(string op, Series scalar,
Series column, bool scalarOnLeft, ref bool handled)Series overExpr(DataFrame df, Expr inner, string[] keys,
string label) @trustedEvaluates an expression per partition and scatters back to input rows (the bare-expression `over` implementation). Each partition's rows form a sub-frame; the expression evaluates on it; the first ...Expr col(string name) @safeCreates a column-reference expression: evaluates to the named column's Series against a frame.bool aggPayload(in Expr e, out AggKind kind, out double param,
out string column) @safe pure nothrow