For contributors — how XLOG compiles and runs arithmetic internally. If you only
need the surface language (syntax, precedence, built-ins, worked examples), read
the user-facing arithmetic syntax reference in the language reference instead.
AST Representation
The parser represents an arithmetic expression as an abstract syntax tree (AST) — a tree where each node is one operation or value.ArithExpr is that tree type,
and IsExpr wraps a single is binding (a fresh variable plus the expression
that computes it).
Type Inference Rules
Before lowering, every expression node gets a scalar type. The rules below are applied bottom-up over the tree. Most binary operations require both sides to share a type; a few (likepow and cast) fix the result type regardless of the
inputs.
Type mismatches are rejected during inference with a source-located diagnostic
that directs users to
cast() when needed.
Lowering to RIR
Lowering turns the type-checked tree into a query-plan node. XLOG’s internal query plan is the relational intermediate representation (RIR) — the form the compiler works with after parsing and before it hits the GPU. Here the lowerer converts eachIsExpr into a computed projection: it appends one new column to
the current plan, and that column holds the value of the expression.
ProjectExpr
Each column in a projection is either passed through unchanged or computed from an expression.ProjectExpr is the enum that captures that choice:
GPU Execution
Arithmetic expressions are evaluated on the GPU through the arithmetic support insideCudaKernelProvider (the component that runs XLOG kernels on CUDA).
Evaluation Strategy
The expression tree is compiled into column references and operations, its inputs are staged as GPU buffers, and the CUDA helpers apply the operations to produce one output column.Relational floating-point order
XLOG maps everyf32 and f64 bit pattern to one unsigned ordering key. The
mapping is shared by host evaluation and CUDA and matches Rust’s
f32::total_cmp and f64::total_cmp. All six comparison operators, arithmetic
min and max, probabilistic min and max, sorting, difference, and
deduplication therefore agree on one total order.
The order distinguishes negative zero from positive zero and preserves the
sign, signaling state, and payload of NaNs. Equality is equality in that total
order: two values compare equal only when their bit patterns are identical.
Consequently, -0.0 is not equal to 0.0, and a NaN compares equal to the
same NaN bit pattern. Arithmetic operations that produce a NaN normalize it to
one positive quiet-NaN bit pattern, so host and CUDA results do not depend on a
platform-specific NaN payload.
Error Handling
Arithmetic faults do not raise an error at runtime. Instead they produce special sentinel values, which flow through like any other data. The table shows what each fault yields for integer versus float columns.
Because faults become values rather than errors, filter them out explicitly when
you need to exclude them:
Scoping Rules
isbindings are body-only and cannot appear in rule heads.- The target variable must be fresh at the point of the
is. - All variables referenced by the expression must already be bound.
See Also
- GPU Execution — execution details for computed expressions
- Query Optimizer — projection and pushdown behavior