Syntax Guide for CJC Version 0.1.1

A comprehensive reference for CJC-Lang’s language features, compiler infrastructure, and quantum computing extensions.

CJC-Lang
syntax
compilers
scientific-computing
quantum
The complete syntax guide for CJC-Lang v0.1.1 — covering core language constructs, 287+ builtins, the dual-engine compiler pipeline, quantum simulation extensions, and deterministic numerical computing.
Author

Adam Ezzat

Published

April 2, 2026

Modified

April 2, 2026

🕑 ~45 min read
21Rust crates
287+builtins
6,500+tests passing
What’s New in v0.1.1

CJC-Lang v0.1.1 adds Quantum Hardening Phase 3 (Jordan-Wigner, Suzuki-Trotter, Zero-Noise Extrapolation), AST Evolution v0.3 (visitor trait, metrics, validation), MIR Evolution v0.3 (schedule metadata, reduction analysis, SSA loop overlay), and MPS enhancements (canonical forms, SWAP networks). This guide covers every language feature and builtin available as of this release.


Part 1 — The Language

CJC-Lang is a statically-aware, dynamically-typed language for deterministic scientific computing. If you’ve written Rust, Python, or R, the syntax will feel familiar. This section covers every construct the language supports.

Functions

Every function parameter requires a type annotation. Return types are optional but recommended.

fn add(a: i64, b: i64) -> i64 {
    a + b
}

fn greet(name: String) {
    print("Hello, " + name);
}

Functions are first-class values. You can pass them as arguments:

fn apply(f: fn(i64) -> i64, x: i64) -> i64 {
    f(x)
}

fn double(x: i64) -> i64 { x * 2 }

fn main() -> i64 {
    apply(double, 21)
}

Recursive functions work as expected:

fn factorial(n: i64) -> i64 {
    if n <= 1 { return 1; }
    n * factorial(n - 1)
}

fn main() -> i64 { factorial(10) }

Generic functions use angle-bracket syntax with optional trait bounds:

fn identity<T>(x: T) -> T { x }

fn my_max<T>(a: T, b: T) -> T {
    if a > b { a } else { b }
}

fn wrap<T>(x: T) -> T { x }
fn apply_generic<T>(x: T) -> T { wrap(x) }

Variables

Immutable by default. Use let mut for mutation.

let x: i64 = 42
let pi = 3.14159
let name = "CJC-Lang"

let mut count = 0
count = count + 1

CJC-Lang supports type inference, but you can always be explicit:

let a: f64 = 1.0
let b: bool = true
let c: String = "hello"
let d: i64 = 99

Primitive Types

Type Description Example
i64 64-bit signed integer 42, -7
f64 64-bit floating point 3.14, 1e-6
bool Boolean true, false
String UTF-8 string "hello"
ByteSlice Raw byte sequence b"hello"
Any Dynamic/polymorphic type Used for generic dispatch

Control Flow

if/else

if works as both a statement and an expression:

// Statement form
if x > 0 {
    print("positive");
} else {
    print("non-positive");
}

// Expression form — both branches must return compatible types
let abs_x = if x >= 0 { x } else { -x };

Note: no parentheses around the condition. Braces are always required.

while loops

let mut sum = 0;
let mut i = 1;
while i <= 100 {
    sum = sum + i;
    i = i + 1;
}

for loops

for iterates over ranges using start..end (exclusive upper bound):

let mut total = 0;
for i in 1..11 {
    total = total + i;
}

break and continue

Both work inside while and for loops:

for i in 0..10 {
    if i == 4 { break; }
    print(i);
}

let mut i = 0;
while i < 5 {
    i = i + 1;
    if i == 3 { continue; }
    print(i);
}

Pattern Matching

CJC-Lang has full structural pattern matching with match expressions:

// Match on integers
let x = 99;
let label = match x {
    1 => "one",
    2 => "two",
    _ => "other",
};

// Match on enums
enum Color { Red, Green, Blue }

fn classify(c: Color) -> i64 {
    match c {
        Red   => 1,
        Green => 2,
        _     => 3,
    }
}

Pattern matching supports destructuring:

// Option type
let x = Some(42);
let val = match x {
    Some(v) => v,
    None    => 0,
};

// Result type
let r = Ok(3.14);
match r {
    Ok(v)  => print(v),
    Err(e) => print("error"),
}

Structs

struct Point { x: f64, y: f64 }

let p = Point { x: 1.5, y: 2.5 };
print(p.x + p.y);

Structs can have methods via impl blocks:

struct Circle { radius: f64 }

impl Circle {
    fn area(c: Circle) -> f64 {
        3.14159 * c.radius * c.radius
    }
}

let c = Circle { radius: 5.0 };
print(Circle::area(c));

Generic structs:

struct Pair<T, U> { first: T, second: U }

Enums

enum Shape {
    Circle(f64),
    Rectangle(f64, f64),
    Triangle(f64, f64, f64),
}

enum Option<T> { None, Some(T) }

Traits

trait Numeric: Add + Mul {
    fn zero() -> Self;
    fn one() -> Self;
}

impl<T> Vec<T> : Iterable {
    fn len(self: Vec<T>) -> i64 { 0 }
}

Closures

Closures use |args| body syntax with mandatory type annotations on parameters:

let f = |x: f64| x * x;
let add = |x: f64, y: f64| x + y;

print(f(3.0));
print(add(1.0, 2.0));

Closures capture variables from their enclosing scope. CJC performs capture analysis during HIR lowering to determine what each closure needs.

Arrays

Arrays are ordered, dynamically-typed collections:

let nums = [1, 2, 3, 4, 5];
let mixed = [1, "hello", 3.14, true];

// Array operations — note: array_push returns a NEW array
let extended = array_push(nums, 6);
let length = array_len(extended);
let first = array_get(nums, 0);
let sliced = array_slice(nums, 1, 3);

array_push(arr, val) does not mutate arr. It returns a new array. Always reassign: arr = array_push(arr, val);

Strings

let s = "hello world";
let upper = str_upper(s);
let lower = str_lower(s);
let trimmed = str_trim("  padded  ");
let parts = str_split("a,b,c", ",");
let joined = str_join(["a", "b", "c"], "-");
let sub = str_contains(s, "world");

Formatted strings use f"..." syntax:

let name = "CJC-Lang";
let version = "0.1.1";
print(f"Welcome to {name} v{version}");

Byte Slices

For low-level data processing:

let data: ByteSlice = b"name,age,score\nAlice,30,95.5";
let rows = data.split_byte(b'\n');
let header = rows[0];
let fields = header.split_byte(b',');

Compound Assignments

CJC recognizes +=, -=, *=, /= operators:

let mut x = 10;
x += 5;
x -= 3;
x *= 2;
x /= 4;

Pipe Operator

The |> operator chains function calls left-to-right:

data |> filter(predicate) |> map(transform)

nogc Blocks

Mark functions as allocation-free for performance-critical paths. The NoGC verifier statically checks that no GC-triggering operations occur inside:

nogc fn fast_multiply(x: f64, y: f64) -> f64 {
    x * y
}

The MIR pipeline includes a NoGC verification pass that performs call-graph analysis with a may_gc fixpoint computation. If any reachable function allocates, the verifier rejects the program.


Part 2 — The Compiler Pipeline

CJC compiles through a multi-stage pipeline. Understanding it helps you reason about error messages, optimization, and the dual-engine execution model.

Source → Lexer → Parser → AST → [TypeChecker] → HIR → MIR → [Optimize] → Exec

Stage 1: Lexer

The lexer (cjc-lexer) converts source text into a flat token stream. It recognizes all CJC-Lang keywords, operators (including |>, +=, @), literals (integers, floats, strings, byte strings), and identifiers.

let (tokens, diags) = Lexer::new(src).tokenize();

Stage 2: Parser

A Pratt parser (cjc-parser) builds the AST from tokens. It handles operator precedence, expression vs. statement disambiguation, and produces structured error diagnostics.

let (program, diags) = cjc_parser::parse_source(src);

The parser recognizes 35 expression kinds, 9 statement kinds, 11 declaration kinds, and 9 pattern kinds.

Stage 3: AST

The AST (cjc-ast) is a tree of typed nodes. As of v0.1.1, the AST layer includes:

  • Visitor trait (visit module) — read-only traversal covering all node variants with walk_* functions
  • Metrics (metrics module) — single-pass structural statistics: node counts, depth, operator frequencies, feature flags
  • Validation (validate module) — structural checks: break/continue outside loops, duplicate params, empty match, unreachable code after return, nesting depth limits
  • Inspect (inspect module) — deterministic text dumps: dump_ast_summary, dump_ast_metrics, dump_validation_report, dump_expr_tree
  • Node utilities (node_utils module) — helper methods like Expr::child_count, is_literal, Block::is_empty, Program::has_main_function

Stage 4: HIR (High-level IR)

HIR lowering (cjc-hir) desugars the AST. for loops become while loops over ranges. Closures get capture analysis. The HIR is closer to the execution model while still being readable.

Stage 5: MIR (Mid-level IR)

MIR (cjc-mir) is a register-based intermediate representation. HIR lowers to MIR instructions that operate on virtual registers.

The MIR layer in v0.1.1 includes:

  • Optimizer — constant folding, strength reduction, dead code elimination (DCE), common subexpression elimination (CSE), loop-invariant code motion (LICM)
  • SSA construction — Cytron’s minimal SSA algorithm with 6 optimization passes
  • Loop analysis — enriched LoopInfo with is_countable, trip_count_hint, num_exits, schedule metadata
  • Reduction analysis — enriched ReductionInfo with accumulator_semantics (Plain, Kahan, Binned, RuntimeDefined)
  • Schedule metadata — descriptive execution hints (SequentialStrict, DescriptiveTiled, DescriptiveVectorized, etc.) that are non-semantic
  • SSA loop overlay — maps SSA definitions to loops, identifies loop-carried variables, cross-references reductions with SSA accumulators
  • Legality verifier — schedule consistency checks, reduction metadata cross-validation
  • NoGC verifier — call-graph may_gc fixpoint analysis

Stage 6: Execution (Dual Engine)

CJC-Lang has two execution engines that must produce identical results:

Engine Module Entry Point Description
v1 cjc-eval Interpreter::new(seed).exec(&program) AST tree-walk interpreter
v2 cjc-mir-exec run_program_with_executor(&program, seed) MIR register-machine executor

The MIR executor also supports an optimized mode:

cjcl run program.cjcl --mir-opt

Parity tests in the test suite verify that both engines produce bit-identical output for every supported program.

Diagnostics

CJC-Lang uses structured error codes (E0xxx-E8xxx) via the cjc-diag crate. Diagnostics carry source spans, severity levels, and optional fix suggestions.


Part 3 — Determinism Architecture

Determinism is CJC-Lang’s defining architectural constraint. Every design decision flows from one requirement: same seed in, same bits out, every time, on every platform.

How CJC Achieves Determinism

Component Mechanism
RNG SplitMix64 with explicit seed threading — no global state
Collections BTreeMap/BTreeSet everywhere — never HashMap/HashSet
Floating-point sums Kahan summation or BinnedAccumulator — never naive reduction
SIMD No FMA (fused multiply-add) — mul_fixed throughout
Complex arithmetic mul_fixed for all complex multiplications
Iteration Vec-based storage with deterministic ordering
Parallelism Results identical regardless of thread count

Kahan Summation

Naive floating-point addition loses precision as terms accumulate. CJC-Lang uses compensated summation everywhere:

// Under the hood, CJC-Lang's runtime uses Kahan summation:
// sum = 0.0, compensation = 0.0
// for each term:
//   y = term - compensation
//   t = sum + y
//   compensation = (t - sum) - y
//   sum = t

This matters for scientific workloads where you’re summing millions of terms. The result is the same whether you sum them on a laptop or a cluster.

BinnedAccumulator

For even higher-precision requirements, CJC-Lang provides binned accumulators that partition the floating-point range into bins, accumulate within each bin, then combine — guaranteeing reproducible results even under reordering.

SplitMix64

All randomness in CJC-Lang flows through a seeded SplitMix64 generator. There is no global RNG state. Every function that needs randomness takes an explicit seed parameter:

let samples = q_sample(circuit, 1000, 42);
let measurement = q_measure(circuit, 42);

Part 4 — Builtin Functions

CJC-Lang ships with 287+ builtin functions registered in cjc-runtime. These are available without imports in every CJC-Lang program.

Mathematics

Function Description
abs(x) Absolute value
sqrt(x) Square root
pow(base, exp) Exponentiation
log(x) Natural logarithm
log2(x), log10(x) Base-2 and base-10 logarithm
exp(x) Euler’s number raised to x
sin(x), cos(x), tan(x) Trigonometric functions
asin(x), acos(x), atan(x) Inverse trigonometric
sinh(x), cosh(x), tanh(x) Hyperbolic functions
floor(x), ceil(x), round(x) Rounding
min(a, b), max(a, b) Minimum and maximum
clamp(x, lo, hi) Clamp to range
gcd(a, b), lcm(a, b) Greatest common divisor, least common multiple
factorial(n) Factorial
fibonacci(n) Fibonacci number

Statistics

Function Description
mean(arr) Arithmetic mean
median(arr) Median
variance(arr) Sample variance
std_dev(arr) Standard deviation
percentile(arr, p) p-th percentile
quantile(arr, q) Quantile
correlation(x, y) Pearson correlation
covariance(x, y) Covariance
skewness(arr) Skewness
kurtosis(arr) Kurtosis
zscore(arr) Z-score normalization
mann_whitney(x, y) Mann-Whitney U test
percent_rank(arr) Percent rank
ntile(arr, n) N-tile grouping
case_when(conds, vals, default) Conditional value selection

Arrays

Function Description
array_len(arr) Length
array_push(arr, val) Append (returns new array)
array_pop(arr) Remove last element (returns new array)
array_get(arr, idx) Get element at index
array_set(arr, idx, val) Set element (returns new array)
array_slice(arr, start, end) Subsequence
array_contains(arr, val) Membership test
array_reverse(arr) Reverse
array_sort(arr) Sort (deterministic)
array_map(arr, f) Map function over elements
array_filter(arr, f) Filter by predicate
array_reduce(arr, f, init) Left fold
array_flatten(arr) Flatten nested arrays
array_zip(a, b) Zip two arrays
array_unique(arr) Remove duplicates (deterministic)

Strings

Function Description
str_len(s) Length
str_upper(s), str_lower(s) Case conversion
str_trim(s) Strip whitespace
str_split(s, delim) Split by delimiter
str_join(arr, delim) Join array with delimiter
str_contains(s, sub) Substring test
str_replace(s, old, new) Replace occurrences
str_starts_with(s, prefix) Prefix test
str_ends_with(s, suffix) Suffix test
str_char_at(s, idx) Character at index
str_substring(s, start, end) Substring extraction

Tensor Operations

Function Description
Tensor.from_vec(data, shape) Create tensor from flat data + shape
t.shape() Get shape
t.sum() Sum all elements
t.mean() Mean of all elements
t.transpose() Transpose
t.matmul(other) Matrix multiplication
t.layer_norm(gamma, beta) Layer normalization
t.linear(weights, bias) Linear transform
t.split_heads(n) Split into attention heads
t.merge_heads() Merge attention heads
t.softmax() Softmax activation
t.relu() ReLU activation

Tensor operations use SIMD acceleration internally but never use FMA, preserving bit-identical results.

I/O

Function Description
print(val) Print to stdout
read_file(path) Read file contents
write_file(path, content) Write file
to_string(val) Convert to string representation

Automatic Differentiation

CJC-Lang has built-in AD support via cjc-ad:

Function Description
dual(value, derivative) Create forward-mode dual number
grad(f, x) Compute gradient
jacobian(f, x) Compute Jacobian matrix

Forward-mode uses dual numbers; reverse-mode uses a deterministic tape with gradient graphs.


Part 5 — DataFrame Operations

CJC-Lang includes a tidyverse-inspired DataFrame library (cjc-data) for tabular data manipulation:

let df = dataframe([
    column("name", ["Alice", "Bob", "Charlie"]),
    column("age", [30, 25, 35]),
    column("score", [95.5, 87.3, 91.2]),
]);

// Filter, transform, aggregate
df |> filter(col("age") > 25)
   |> mutate("grade", col("score") / 10.0)
   |> group_by(col("grade"))
   |> summarize("avg_age", mean(col("age")))

Key operations:

Operation Description
filter(predicate) Row selection
select(columns...) Column selection
mutate(name, expr) Add/transform column
group_by(column) Group rows
summarize(name, agg) Aggregate within groups
join(other, on) Join two DataFrames
arrange(column) Sort by column

Part 6 — Visualization

The cjc-vizor crate provides grammar-of-graphics visualization:

let p = vizor_plot(categories, values);
let p = p.geom_bar();
let p = p.title("Quarterly Results");
let p = p.size(800, 500);
p.render();

Vizor supports bar charts, line plots, scatter plots, histograms, and heatmaps with configurable aesthetics (color, size, shape, faceting).


Part 7 — Quantum Computing Extensions

CJC-Lang v0.1.1 includes a comprehensive quantum simulation framework (cjc-quantum) with 45+ quantum builtins. The framework spans five simulation backends, each suited to different qubit scales and circuit types.

Circuit Simulation (Statevector, up to ~26 qubits)

Full statevector simulation for small circuits:

// Create a Bell state
let c = qubits(2);
let c = q_h(c, 0);
let c = q_cx(c, 0, 1);

// Measure
let probs = q_probs(c);
print(probs);

// Sample 1000 shots
let results = q_sample(c, 1000, 42);

Available gates:

Gate Function Description
H q_h(c, qubit) Hadamard
X, Y, Z q_x, q_y, q_z Pauli gates
S, T q_s, q_t Phase gates
Rx, Ry, Rz q_rx(c, q, angle) Rotation gates
CNOT q_cx(c, ctrl, tgt) Controlled-NOT
CZ q_cz(c, ctrl, tgt) Controlled-Z
SWAP q_swap(c, q1, q2) SWAP
Toffoli q_toffoli(c, c1, c2, tgt) Three-qubit controlled-controlled-NOT

MPS Simulation (up to 50+ qubits)

Matrix Product State simulation trades exactness for scalability via bond dimension truncation:

// 50-qubit GHZ state
let mps = mps_new(50, 16);
let mps = mps_h(mps, 0);
for i in 0..49 {
    mps = mps_cnot(mps, i, i + 1);
}

// Measure Z expectation on qubit 25
let z = mps_z_expectation(mps, 25);

// Compute Heisenberg energy
let energy = mps_energy(mps, "heisenberg");

New in v0.1.1 — MPS canonical forms and SWAP networks:

Function Description
mps_left_canonicalize(mps) Left-canonical form via SVD sweep
mps_right_canonicalize(mps) Right-canonical form via SVD sweep
mps_mixed_canonicalize(mps, center) Mixed-canonical form with orthogonality center
mps_swap(mps, q1, q2) Arbitrary-distance 2-qubit gates via SWAP network

Canonical forms use sign-stabilized SVD to preserve bit-identical determinism.

Stabilizer Simulation (up to 1000+ qubits)

The CHP (Clifford) simulator efficiently handles Clifford circuits:

let s = stabilizer_new(100);
let s = stabilizer_h(s, 0);
for i in 0..99 {
    s = stabilizer_cnot(s, i, i + 1);
}
let outcome = stabilizer_measure(s, 50, 42);

Stabilizer simulation runs in O(n^2) time and O(n^2) memory for n qubits — enabling circuits that are impossible with statevector simulation.

Density Matrix (Mixed States and Noise)

For simulating open quantum systems with decoherence:

let dm = density_new(2);
let dm = density_gate(dm, "H", 0);
let dm = density_cnot(dm, 0, 1);

// Apply noise
let dm = density_depolarize(dm, 0, 0.01);
let dm = density_dephase(dm, 1, 0.02);

// Diagnostics
print(density_purity(dm));
print(density_entropy(dm));

Jordan-Wigner Fermion Hamiltonians (New in v0.1.1)

Map fermionic creation/annihilation operators to qubit Pauli strings. Pre-built molecular Hamiltonians for quantum chemistry:

// H2 molecule Hamiltonian
let h = q_fermion_h2();
print(q_fermion_n_terms(h));

// LiH molecule Hamiltonian
let h = q_fermion_lih();

// Compute expectation value against a circuit
let c = qubits(4);
let c = q_h(c, 0);
let c = q_cx(c, 0, 1);
let energy = q_fermion_expectation(h, c);

The Jordan-Wigner transformation maps: \(a^\dagger_j = \frac{X_j - iY_j}{2} \otimes Z_{j-1} \otimes \cdots \otimes Z_0\)

All Pauli terms are stored in Vec (not HashMap) for deterministic iteration. Expectation values use Kahan summation.

Suzuki-Trotter Time Evolution (New in v0.1.1)

Simulate quantum dynamics via product formula decomposition:

// Time-evolve a state under H2 Hamiltonian
let h = q_fermion_h2();
let c = qubits(4);
let c = q_h(c, 0);

// 2nd-order Trotter with 100 steps, evolving for time=1.0
let final_state = q_trotter_evolve(h, c, 1.0, 100, 2);

// Error bound for the approximation
let error = q_trotter_error(h, 1.0, 100, 2);
  • Order 1: Lie-Trotter — \(e^{-i(A+B)t} \approx (e^{-iAt/n} e^{-iBt/n})^n\)
  • Order 2: Strang splitting — symmetric product formula with \(O(\Delta t^3)\) local error

Diagonal Pauli strings (containing only I and Z) are optimized to O(N) phase rotations, skipping the O(N^2) general path.

Zero-Noise Extrapolation (New in v0.1.1)

Mitigate quantum hardware noise by extrapolating to the zero-noise limit:

// Richardson extrapolation from noisy measurements
let scales = [1.0, 2.0, 3.0];
let noisy_values = [-0.95, -0.82, -0.61];

let result = q_zne_mitigate(scales, noisy_values);
// result[0] = mitigated value (extrapolated to zero noise)
// result[1] = Richardson coefficients

// Simple linear extrapolation (2 points)
let clean = q_zne_linear(1.0, -0.95, 2.0, -0.82);

// Noise scaling
let scaled_p = q_scale_noise(0.01, 3.0, "depolarizing");

Richardson extrapolation solves a Vandermonde system with partial pivoting. For polynomial noise models of degree \(d\), using \(d+1\) scale factors gives exact recovery.

VQE (Variational Quantum Eigensolver)

let energy = vqe_heisenberg(8, 16, 0.01, 100, 42);

QAOA (Quantum Approximate Optimization)

let graph = qaoa_graph_cycle(6);
let result = qaoa_maxcut(graph, 16, 2, 0.05, 50, 42);

DMRG (Density Matrix Renormalization Group)

let energy = dmrg_heisenberg(20, 32, 10, 1e-8);

QEC (Quantum Error Correction)

let rate = qec_logical_error_rate(3, 0.01, 1000, 42);

QML (Quantum Machine Learning)

Data re-uploading quantum neural network:

let result = qml_train(4, 3, 2, 16, 0.01, 50, 42, samples, labels);
let accuracy = result[0];
let loss_history = result[1];

Dual-Mode Backend

Every quantum feature has two backends:

  1. Rust backend — optimized, compiled, fast
  2. Pure CJC backend — inspectable, AD-compatible, modifiable

Pass "pure" to constructor functions to use the pure backend. Operations automatically detect which backend a state uses.


Part 8 — Complete Examples

Example 1: Numerical Integration

fn trapz(f: fn(f64) -> f64, a: f64, b: f64, n: i64) -> f64 {
    let h = (b - a) / n;
    let mut sum = (f(a) + f(b)) / 2.0;
    for i in 1..n {
        sum = sum + f(a + i * h);
    }
    sum * h
}

fn main() -> f64 {
    let area = trapz(|x: f64| x * x, 0.0, 1.0, 1000);
    print(f"Integral of x^2 from 0 to 1 = {area}");
    area
}

Example 2: Transformer Forward Pass

let batch    = 1;
let seq_len  = 4;
let model_dim = 8;
let num_heads = 2;
let head_dim  = model_dim / num_heads;

let input_data = [
    0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8,
    0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9,
    0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
    0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1
];
let x = Tensor.from_vec(input_data, [1, 4, 8]);

let x_norm = x.layer_norm(gamma, beta);
let Q = x_norm.linear(Wq, bias_zero);
let K = x_norm.linear(Wk, bias_zero);
let V = x_norm.linear(Wv, bias_zero);

let Q_heads = Q.split_heads(num_heads);
let K_heads = K.split_heads(num_heads);
let V_heads = V.split_heads(num_heads);

let attn_out = attention(Q_heads, K_heads, V_heads);
let attn_merged = attn_out.merge_heads();
let attn_proj = attn_merged.linear(Wo, bias_zero);

let x2 = x + attn_proj;
print("Transformer block output shape:", x2.shape());

Example 3: CSV ETL Pipeline

let csv_data: ByteSlice = b"name,age,score\nAlice,30,95.5\nBob,25,87.3\nCharlie,35,91.2";

let rows = csv_data.split_byte(b'\n');
let header = rows[0];
let header_fields = header.split_byte(b',');
print(header_fields);

let mut total_score = 0.0;
let mut count = 0;
for i in 1..rows.len() {
    let fields = rows[i].split_byte(b',');
    let name = fields[0];
    let score = fields[2];
    total_score = total_score + score;
    count = count + 1;
}
print(f"Average score: {total_score / count}");

Example 4: Quantum Chemistry

// Build H2 Hamiltonian and compute ground state energy estimate
let h = q_fermion_h2();
print(f"H2 Hamiltonian has {q_fermion_n_terms(h)} Pauli terms");

// Prepare a trial state
let c = qubits(4);
let c = q_ry(c, 0, 0.5);
let c = q_ry(c, 1, -0.3);
let c = q_cx(c, 0, 2);
let c = q_cx(c, 1, 3);

// Compute energy
let energy = q_fermion_expectation(h, c);
print(f"Trial energy: {energy}");

// Time evolution
let evolved = q_trotter_evolve(h, c, 0.5, 50, 2);
print("Evolution complete");

// Mitigate noise from hypothetical hardware
let scales = [1.0, 1.5, 2.0];
let noisy = [-1.05, -0.92, -0.71];
let mitigated = q_zne_mitigate(scales, noisy);
print(f"Mitigated energy: {mitigated[0]}");

Example 5: Statistical Analysis

let data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0];

print(f"Mean: {mean(data)}");
print(f"Std Dev: {std_dev(data)}");
print(f"Median: {median(data)}");
print(f"Skewness: {skewness(data)}");
print(f"Kurtosis: {kurtosis(data)}");

let groups = ntile(data, 4);
print(f"Quartile groups: {groups}");

let ranks = percent_rank(data);
print(f"Percent ranks: {ranks}");

// Non-parametric test
let x = [1.0, 2.0, 3.0, 4.0, 5.0];
let y = [2.0, 3.0, 4.0, 5.0, 6.0];
let test = mann_whitney(x, y);
print(f"p-value: {test.p_value}");

Part 9 — CLI Reference

CJC-Lang ships as a single binary with 29 subcommands across three tiers.

File Format Compatibility

Not every command operates on .cjcl source files. Here’s what each command reads:

CJC-Lang source only (.cjcl): run, proof, emit, explain, gc, nogc, audit, precision, parity, test, bench, mem, trace, lock, check

CJC + other formats (read-only):

Command Formats
doctor .cjcl, .snap (binary), .csv/.tsv, plus metadata on all files for size warnings
ci .cjcl only (reimplements parse + type checks, does not run full doctor)
view Directory metadata, .cjcl source for effect annotations, .snap binary for hashes
inspect Dispatches on extension: .snap (binary decode), .csv/.tsv (schema), .cjcl (source), anything else (generic: size + hash)
seek Traverses any directory; reads any file’s content for --contains

Non-CJC-Lang formats exclusively:

Command Formats
flow .csv/.tsv or stdin
schema .csv/.tsv
patch .csv/.tsv or stdin
drift Any two files (auto-detects .csv/.tsv for structured diff, otherwise text diff)

Core Commands

Command Description
cjcl run file.cjcl Execute a program (AST tree-walk interpreter)
cjcl run file.cjcl --mir-opt Execute via MIR engine with optimizations (CF + DCE)
cjcl run file.cjcl --mir-mono Execute with MIR monomorphization
cjcl lex file.cjcl Show token stream
cjcl parse file.cjcl Parse and pretty-print AST
cjcl check file.cjcl Type-check without executing
cjcl repl Interactive REPL (supports :ast, :mir, :type, :env, :seed meta-commands)

Global Flags (for core commands)

Flag Description
--seed N Set RNG seed (default: 42)
--reproducible Enable reproducibility mode
--time Print execution time
--mir-opt Enable MIR optimizations
--mir-mono Enable MIR monomorphization
--multi-file Enable multi-file module resolution
--color / --no-color Force color output on/off
--diagnostic-format rich\|short Diagnostic output format

Phase 1 CLI Suite — Data & Pipeline Tools

cjcl view [path] — Deterministic directory listing

Lists directory contents with file kinds, sizes, and effect annotations. Output is sorted deterministically. Hash display is off by default for cleaner output; opt in with --hash when you need content-addressable verification.

Flags: -r, --recursive | --hash | --no-effects | --no-size | --no-header | --plain / --json / --table / --color

$ cjcl view examples/

  examples/ (17 entries)

┌───────────────────────────────────────────┬──────┬───────────┬─────────┐
│ Name                                      │ Kind │ Size      │ Effects │
├───────────────────────────────────────────┼──────┼───────────┼─────────┤
│ examples/chess_replay.html                │ file │ 17.9 KiB  │ -       │
│ examples/chess_rl_dashboard.html          │ file │ 11.4 KiB  │ -       │
│ examples/etl_csv_parse.cjcl               │ cjcl │ 774 B     │ -       │
│ examples/nlp_tokenize.cjcl                │ cjcl │ 766 B     │ -       │
│ examples/transformer_forward.cjcl         │ cjcl │ 5.7 KiB   │ -       │
│ examples/vizor_bar.cjcl                   │ cjcl │ 439 B     │ -       │
│ ...                                       │      │           │         │
└───────────────────────────────────────────┴──────┴───────────┴─────────┘

cjcl proof <file.cjcl> — Determinism & reproducibility profiler

Runs a program multiple times and verifies that stdout, exit status, and GC behavior are identical across runs. Supports testing across multiple seeds to catch seed-dependent nondeterminism.

Flags: -n, --runs <N> | --seed <N> | --seeds <N,M,...> | -v, --verbose | --plain / --json / --color

$ cjcl proof fibonacci.cjcl

[proof] Running 3 iterations with seed 42...
55
55
55

┌──────────────────────────┬────────┐
│ Check                    │ Status │
├──────────────────────────┼────────┤
│ stdout identical         │ PASS   │
│ exit status identical    │ PASS   │
│ GC collections identical │ PASS   │
└──────────────────────────┴────────┘

Verdict: PASS (3 runs, seed=42)

Multi-seed mode tests reproducibility across different RNG seeds in a single invocation:

$ cjcl proof fibonacci.cjcl --seeds 42,99,256

cjcl flow [file.csv] — Streaming computation engine

Applies aggregation operations to CSV columns using O(1) memory per column. Uses Kahan summation for numerically stable sums and Welford’s algorithm for online variance. Reads from stdin if no file is given.

Flags: -d, --delimiter <c> | --tsv | --no-header | --op <ops> (sum, mean, min, max, count, var, std) | -c, --columns <cols> | --precision <N> | --plain / --json / --color

$ cjcl flow data.csv --op sum

┌────────┬───────────┐
│ Column │ sum       │
├────────┼───────────┤
│ a      │ 12.000000 │
│ b      │ 15.000000 │
│ c      │ 18.000000 │
└────────┴───────────┘
(3 rows processed)

cjcl patch <file.csv> — Type-aware data transformation

Apply transforms like rename, drop, impute, and replace to CSV data.

Transforms: --nan-fill <value> | --impute <column> | --replace <col> <from> <to> | --drop <column> | --rename <old> <new> | --fill-empty <col> <value>

Flags: -d, --delimiter <c> | --tsv | --no-header | -o, --output <file> | --plain / --json / --color

$ cjcl patch data.csv --rename a x

x,b,c
1,2,3
4,5,6
7,8,9
patched 3 rows

cjcl seek [path] [pattern] — Deterministic file discovery

Find files by type, content, or size with deterministic ordering.

Flags: -t, --type <ext> | --contains <text> | --min-size <size> | --max-size <size> | --max-depth <N> | --count | --plain / --json / --color

$ cjcl seek examples/ --type cjc

examples/etl_csv_parse.cjcl
examples/nlp_tokenize.cjcl
examples/nlp_vocab_count.cjcl
examples/piml_demo.cjcl
examples/pinn_demo.cjcl
examples/transformer_forward.cjcl
examples/vizor_bar.cjcl
...
11 files found

cjcl drift <a> <b> — Mathematical and data diff engine

Compares two files cell-by-cell with optional numeric tolerance. Auto-detects mode from file extension, or specify explicitly.

Modes: --text | --numeric | --csv

Flags: -e, --tolerance <N> | --precision <N> | --max-diffs <N> | -d, --delimiter <c> | --plain / --json / --color

$ cjcl drift a.csv b.csv --csv

┌──────────────────┬──────────┐
│ Metric           │ Value    │
├──────────────────┼──────────┤
│ Rows (A)         │ 3        │
│ Rows (B)         │ 3        │
│ Cell differences │ 1        │
│ NaN divergences  │ 0        │
│ Max deviation    │ 1.000000 │
│ Frobenius norm   │ 1.000000 │
└──────────────────┴──────────┘

First differences:
  [3,3]: "6" → "7"

cjcl forge <action> — Content-addressable pipeline runner

Runs a program, hashes the output, and caches the result. Re-running with the same source skips execution.

Actions: run <file.cjcl> | verify <file.cjcl> <hash> | list | show <hash-prefix> | clean

Flags: --seed <N> | --cache-dir <path> | -v, --verbose | --plain / --json / --color

$ cjcl forge run fibonacci.cjcl

55
┌──────────┬──────────────────────────────────────────────────────────────────┐
│ Property │ Value                                                            │
├──────────┼──────────────────────────────────────────────────────────────────┤
│ Source   │ fibonacci.cjcl                                                    │
│ Seed     │ 42                                                               │
│ SHA-256  │ 02d20bbd7e394ad5999a4cebabac9619732c343a4cac99470c03e23ba2bdc2bc │
│ Artifact │ .cjcl-forge/02d20bbd...bdc2bc.artifact                            │
└──────────┴──────────────────────────────────────────────────────────────────┘
forged

Phase 2 CLI Suite — Analysis & Diagnostics

cjcl inspect <file> — Deep file inspection

Analyzes .cjcl, .csv, .snap, or generic files. For CJC-Lang source, reports parse results, function signatures, and structural statistics.

Flags: --no-stats | --no-hash | --preview <N> | --plain / --json / --color

$ cjcl inspect fibonacci.cjcl

┌──────────────┬────────────────┐
│ Property     │ Value          │
├──────────────┼────────────────┤
│ File         │ fibonacci.cjcl  │
│ Type         │ cjcl source    │
│ Size         │ 192 B          │
│ Lines        │ 10             │
│ Parse errors │ 0              │
│ Functions    │ 2              │
│ Structs      │ 0              │
│ Let bindings │ 0              │
└──────────────┴────────────────┘

Functions:
  fn fibonacci(n: i64)
  fn main()

cjcl schema <file.csv> — CSV/TSV schema inference

Infers column types, null counts, unique values, and numeric ranges from CSV data.

Flags: -d, --delimiter <c> | --tsv | --no-header | --no-uniques | --sample <N> | --plain / --json / --color

$ cjcl schema data.csv

Schema for `data.csv` (3 rows sampled):

┌────────┬──────┬───────┬───────┬────────┬────────┬────────┐
│ Column │ Type │ Nulls │ Total │ Unique │ Min    │ Max    │
├────────┼──────┼───────┼───────┼────────┼────────┼────────┤
│ a      │ int  │ 0     │ 3     │ 3      │ 1.0000 │ 7.0000 │
│ b      │ int  │ 0     │ 3     │ 3      │ 2.0000 │ 8.0000 │
│ c      │ int  │ 0     │ 3     │ 3      │ 3.0000 │ 9.0000 │
└────────┴──────┴───────┴───────┴────────┴────────┴────────┘

cjcl trace <file.cjcl> — Deterministic execution tracing

Traces parse time, execution time, AST structure, and runtime behavior.

Flags: --seed <N> | --ast | --no-output | -v, --verbose | --plain / --json / --color

$ cjcl trace fibonacci.cjcl

[trace] Tracing `fibonacci.cjcl`...

┌────────────┬──────────┐
│ Phase      │ Detail   │
├────────────┼──────────┤
│ Parse time │ 0.120 ms │
│ Exec time  │ 1.022 ms │
│ Seed       │ 42       │
│ Status     │ OK       │
└────────────┴──────────┘

┌──────────────┬───────┐
│ AST Element  │ Count │
├──────────────┼───────┤
│ Functions    │ 2     │
│ Structs      │ 0     │
│ Let bindings │ 0     │
│ Statements   │ 0     │
│ Decorators   │ 0     │
└──────────────┴───────┘

┌────────────────┬───────┐
│ Runtime        │ Value │
├────────────────┼───────┤
│ Output lines   │ 1     │
│ GC collections │ 0     │
└────────────────┴───────┘

cjcl mem <file.cjcl> — Runtime memory visibility

Profiles GC collections, heap object counts, output size, and execution time. Supports NoGC pre-verification and executor selection.

Flags: --seed <N> | -n, --runs <N> | -v, --verbose | --nogc | --mir | --eval | --plain / --json / --color

$ cjcl mem fibonacci.cjcl

[mem] Memory profile for `fibonacci.cjcl` (1 run, seed=42)

┌───────────────────────┬──────────┐
│ Metric                │ Value    │
├───────────────────────┼──────────┤
│ GC collections (avg)  │ 0.00     │
│ GC stable across runs │ true     │
│ GC heap objects (max) │ 0        │
│ Output lines          │ 1        │
│ Output bytes          │ 2        │
│ Avg exec time         │ 755.0 us │
└───────────────────────┴──────────┘

cjcl bench <file.cjcl> — Performance benchmarking

Runs warmup iterations, then measured iterations with statistical analysis. Reports mean, median, min, max, standard deviation, coefficient of variation, P95, and throughput.

Flags: --seed <N> | -n, --runs <N> | --warmup <N> | -v, --verbose | --nogc | --mir | --eval | --plain / --json / --color

$ cjcl bench fibonacci.cjcl

[bench] Benchmarking `fibonacci.cjcl` (1 warmup + 10 measured runs, seed=42)

┌──────────────┬─────────────────┐
│ Metric       │ Value           │
├──────────────┼─────────────────┤
│ Parse time   │ 129.0 us        │
│ Mean         │ 647.8 us        │
│ Median       │ 628.5 us        │
│ Min          │ 438.0 us        │
│ Max          │ 808.0 us        │
│ Std dev      │ 111.6 us        │
│ CV           │ 17.2%           │
│ P95          │ 808.0 us        │
│ Throughput   │ 1543.7 runs/sec │
└──────────────┴─────────────────┘

cjcl pack <file.cjcl> — Reproducible packaging

Bundles source files and their referenced artifacts (.snap, .csv, .tsv, .json) into a content-addressed package with manifest hashes.

Flags: -o, --output <dir> | --include <file> (repeatable) | --dry-run | --plain / --json / --color

$ cjcl pack fibonacci.cjcl --dry-run

Dry run — would create `fibonacci.pack`:

┌───────────────┬───────┬──────────────────┐
│ File          │ Size  │ Hash             │
├───────────────┼───────┼──────────────────┤
│ fibonacci.cjcl │ 192 B │ 3402c8cc3d398ba2 │
└───────────────┴───────┴──────────────────┘
Total: 1 files, 192 B
Manifest hash: fce3865dd0fb4816

cjcl doctor [path] — Project diagnostics and health checks

Scans a directory for CJC source files, snap files, and CSV data. Reports parse errors, type issues, corrupt snap files, ragged CSV rows, nondeterministic patterns, and large files.

Flags: -v, --verbose | --fix | --strict (exit non-zero on warnings, useful for CI) | --plain / --json / --color

$ cjcl doctor examples/

[doctor] Diagnosing `examples/`...

┌──────────────────┬───────┐
│ Category         │ Count │
├──────────────────┼───────┤
│ CJC source files │ 11    │
│ Snap files       │ 0     │
│ CSV/TSV files    │ 0     │
│ Total files      │ 17    │
└──────────────────┴───────┘

  [WARN] examples/etl_csv_parse.cjcl — 3 type issue(s)
  [WARN] examples/transformer_forward.cjcl — 50 type issue(s)
  ...

┌──────────┬───────┐
│ Severity │ Count │
├──────────┼───────┤
│ Warnings │ 9     │
└──────────┴───────┘

OK (with warnings)

Phase 3 CLI Suite — Compiler Visibility & Verification

cjcl emit <file.cjcl> — Dump intermediate representations

Dumps the compiler’s internal representation at any pipeline stage: AST (parsed source), HIR (desugared form), or MIR (register-machine IR). Use --opt to see the MIR after constant folding and dead code elimination, or --diff to compare both side by side.

Flags: -s, --stage <S> (ast, hir, mir) | --opt | --diff | --plain / --json / --color

$ cjcl emit fibonacci.cjcl --stage ast

=== fibonacci.cjcl (AST) ===

fn fibonacci(n: i64) -> i64 {
    if (n <= 1) {
        return n;
    }
    return (fibonacci((n - 1)) + fibonacci((n - 2)));
}
fn main() -> i64 {
    let result = fibonacci(10);
    print(result);
    result
}
$ cjcl emit fibonacci.cjcl --stage mir

=== fibonacci.cjcl (MIR) ===

fn fibonacci(n: i64) -> i64:
  if (n <= 1):
    return n
  return (fibonacci((n - 1)) + fibonacci((n - 2)))

fn main() -> void:
  print(fibonacci(10))

cjcl explain <file.cjcl> — Show desugared/lowered forms

Lowers the source to HIR and displays function signatures, struct definitions, NoGC annotations, and decorators. Use --verbose to see the full HIR body for each function.

Flags: -v, --verbose | --plain / --json / --color

$ cjcl explain fibonacci.cjcl

[explain] Explaining `fibonacci.cjcl`...

fn fibonacci(n: i64)
  body: 2 statements

fn main()
  body: 2 statements + tail expression

┌────────────────┬───────┐
│ Element        │ Count │
├────────────────┼───────┤
│ Functions      │ 2     │
│ Structs        │ 0     │
│ NoGC functions │ 0     │
│ Total items    │ 2     │
└────────────────┴───────┘

cjcl gc <file.cjcl> — GC analysis & allocation timeline

Dedicated garbage collection analysis. Runs the program multiple times and reports GC pause count, peak/average heap objects, allocation timeline, and GC stability across runs.

Flags: --seed <N> | -n, --runs <N> | -v, --verbose | --plain / --json / --color

$ cjcl gc fibonacci.cjcl

[gc] GC analysis for `fibonacci.cjcl` (3 runs, seed=42)

┌────────────────────────┬─────────────────────┐
│ Metric                 │ Value               │
├────────────────────────┼─────────────────────┤
│ GC pause count (total) │ 0                   │
│ GC collections (avg)   │ 0.00                │
│ GC collections (min)   │ 0                   │
│ GC collections (max)   │ 0                   │
│ GC stable across runs  │ yes                 │
│ Peak heap objects      │ 0                   │
│ Avg heap objects       │ 0.0                 │
│ COW copies             │ 0 (not yet tracked) │
│ Avg exec time          │ 825.3 us            │
└────────────────────────┴─────────────────────┘

Allocation timeline:
┌─────┬────┬───────────┬──────────────┬──────────────┬───────────┐
│ Run │ GC │ Heap Objs │ Output Lines │ Output Bytes │ Time (us) │
├─────┼────┼───────────┼──────────────┼──────────────┼───────────┤
│ 1   │ 0  │ 0         │ 1            │ 2            │ 816       │
│ 2   │ 0  │ 0         │ 1            │ 2            │ 1006      │
│ 3   │ 0  │ 0         │ 1            │ 2            │ 394       │
└─────┴────┴───────────┴──────────────┴──────────────┴───────────┘

STABLE — GC behavior is deterministic across 3 runs.

cjc nogc <file.cjcl> — NoGC static verification

Verifies that all nogc functions in the program are free of GC allocations. Lists every function with its annotation status and per-function PASS/FAIL. Exit code 1 if any violations are found.

Flags: -v, --verbose | --plain / --json / --color

$ cjcl nogc fibonacci.cjcl

[nogc] NoGC verification for `fibonacci.cjcl`

┌───────────┬─────────┬────────┐
│ Function  │ #[nogc] │ Status │
├───────────┼─────────┼────────┤
│ fibonacci │ no      │ PASS   │
│ main      │ no      │ PASS   │
└───────────┴─────────┴────────┘

Verdict: PASS (2 functions, 0 #[nogc])

cjc audit <file.cjcl> — Numerical hygiene analysis

Static analysis of CJC-Lang source for floating-point anti-patterns. Catches common numerical issues before they become silent precision bugs.

Patterns detected: naive summation in loops (suggests kahan_sum() or binned_sum()), float equality comparison (suggests approx_eq), division without zero-guard, catastrophic cancellation.

Flags: -v, --verbose | --plain / --json / --color

$ cjcl audit naive_sum.cjcl

[audit] Auditing `naive_sum.cjcl`...

  [WARN] line 1: naive summation: `total = total + ...` in loop
         suggestion: use `kahan_sum()` or `binned_sum()`
  [WARN] line 1: naive summation: `i = i + ...` in loop
         suggestion: use `kahan_sum()` or `binned_sum()`

┌────────────────┬───────┐
│ Metric         │ Count │
├────────────────┼───────┤
│ Warnings       │ 4     │
│ Info           │ 0     │
│ Total findings │ 4     │
└────────────────┴───────┘

A clean program reports no findings:

$ cjcl audit fibonacci.cjcl

[audit] Auditing `fibonacci.cjcl`...

CLEAN — no numerical hygiene issues found

cjc precision <file.cjcl> — Precision analysis

Runs the program, captures all numeric output, and compares each f64 value against its f32-truncated approximation. Reports per-value relative error and an overall stability verdict.

Flags: --seed <N> | --plain / --json / --color

$ cjcl precision fibonacci.cjcl

[precision] Precision analysis for `fibonacci.cjcl` (seed=42)

┌──────┬─────────────────┬─────────────────┬────────────┐
│ Line │ f64             │ f32             │ Rel. error │
├──────┼─────────────────┼─────────────────┼────────────┤
│ 1    │ 55.000000000000 │ 55.000000000000 │ 0.00e+00   │
└──────┴─────────────────┴─────────────────┴────────────┘

Max relative error: 0.00e+00
Verdict: STABLE (within f32 epsilon bounds)

cjc lock <file.cjcl> — Deterministic lockfile generator & verifier

Generates a lockfile recording source SHA-256, seed, executor version, platform, and expected output SHA-256. Use --verify to check that the current run matches the lockfile. Enables cross-platform and cross-version reproducibility verification.

Flags: --seed <N> | --verify | --plain / --json / --color

$ cjcl lock fibonacci.cjcl

[lock] Generated lockfile: fibonacci.cjcl.lock
┌───────────────┬──────────────────────────────────────────────────────────────────┐
│ Field         │ Value                                                            │
├───────────────┼──────────────────────────────────────────────────────────────────┤
│ source_sha256 │ 3402c8cc3d398ba214ee1111095e3568f0617857785ed8e1f9ec74e5eea1adda │
│ seed          │ 42                                                               │
│ executor      │ eval v0.1.0                                                      │
│ platform      │ windows-x86_64                                                   │
│ output_sha256 │ 02d20bbd7e394ad5999a4cebabac9619732c343a4cac99470c03e23ba2bdc2bc │
└───────────────┴──────────────────────────────────────────────────────────────────┘
$ cjcl lock fibonacci.cjcl --verify

[lock] Verifying against fibonacci.cjcl.lock

┌───────────────┬─────────────────────┬─────────────────────┬────────┐
│ Check         │ Expected            │ Actual              │ Status │
├───────────────┼─────────────────────┼─────────────────────┼────────┤
│ source_sha256 │ 3402c8cc3d398ba2... │ 3402c8cc3d398ba2... │ PASS   │
│ seed          │ 42                  │ 42                  │ PASS   │
│ output_sha256 │ 02d20bbd7e394ad5... │ 02d20bbd7e394ad5... │ PASS   │
└───────────────┴─────────────────────┴─────────────────────┴────────┘

Verdict: MATCH

cjc parity <file.cjcl> — Dual-executor parity checker

Runs both the eval tree-walk interpreter (v1) and the MIR register-machine executor (v2) and compares their output. Verifies that both backends produce identical stdout, return values, and GC behavior.

Flags: --seed <N> | -v, --verbose | --plain / --json / --color

$ cjcl parity fibonacci.cjcl

[parity] eval vs mir-exec (seed=42)

┌────────────────┬───────────────┐
│ Check          │ Status        │
├────────────────┼───────────────┤
│ stdout match   │ PASS          │
│ value match    │ PASS          │
│ GC collections │ eval=0, mir=0 │
└────────────────┴───────────────┘

Verdict: IDENTICAL

cjc test <file.cjcl> — Native test runner

Discovers functions starting with test_ or decorated with @test. Each test runs in isolation with a fresh interpreter instance. Tests execute in alphabetical order for deterministic results.

Flags: --seed <N> | --filter <pattern> | -v, --verbose | --plain / --json / --color

$ cjcl test math_tests.cjcl

[test] Running 2 tests (seed=42)

  test_add .............................. PASS (0.1ms)
  test_multiply ......................... PASS (0.0ms)

2 passed, 0 failed

cjc ci [path] — Full CI diagnostic suite

Orchestrates the complete verification pipeline in a single command: doctor (project health), proof (determinism across 3 seeds), parity (eval vs mir-exec), test (native test runner), and nogc (static verification). Exit code 0 means everything passes.

Flags: --seed <N> | --strict | --plain / --json / --color

$ cjcl ci examples/

[ci] Running full diagnostic suite on `examples/`...

  doctor .... PASS (OK (9 type warnings))
  proof ..... PASS (PASS (33 checks, 3 seeds))
  parity .... PASS (PASS (eval ≡ mir-exec, 11 files))
  tests ..... PASS (0/0 passed)
  nogc ...... PASS (11/11 verified)

EXIT 0

Part 9.1 — CLI Benchmark Results

Every CLI command was tested against production-scale datasets (up to 1,000,000 rows / 108 MB) to verify correctness, numerical accuracy, and determinism. This section presents the full results.

Test Data

Dataset Rows Columns Size Description
million.csv 1,000,000 5 52 MB price, volume, returns, volatility, score
million_wide.csv 1,000,000 10 108 MB 10 float columns, uniform random
million_messy.csv 1,000,000 5 36 MB Mixed types, ~4% NaN, ~3% empty cells
million.tsv 1,000,000 4 38 MB Tab-separated, timestamp + sensor readings
drift_a.csv / drift_b.csv 1,000,000 3 43 MB each ~1,001 injected cell differences
stress_compute.cjcl – – 1.5 KB fib(20) + sum(100K) + Collatz + prime sieve + GCD

Smaller datasets (3 to 100,000 rows) were also tested for every command; only the production-scale results are shown here.

Production-Scale Performance

Command 1M-Row Time 108 MB Time Correct Deterministic
cjcl flow 0.9–1.8 s 1.8 s (10 cols) PASS Bit-identical across runs
cjcl schema 0.5–1.5 s 1.5 s (10 cols) PASS Bit-identical across runs
cjcl inspect 0.3–1.1 s 1.1 s (10 cols) PASS PASS
cjcl patch 5.5–13.6 s 13.6 s (10 cols) PASS PASS
cjcl drift 1.0–1.4 s – PASS PASS
cjcl seek 1.8–10.7 s – PASS PASS
cjcl proof 0.5–1.6 s – PASS All seeds pass
cjcl bench 1.3–1.4 s – PASS PASS
cjcl mem 0.7 s – PASS PASS
cjcl trace 0.3 s – PASS PASS
cjcl forge 0.2 s – PASS Hash identical
cjcl pack 0.03 s – PASS PASS
cjcl doctor 0.2 s – PASS PASS

Detailed Results by Command

flow – Streaming Aggregation (1M rows)

Test Dataset Time Result
Kahan sum, 5 columns million.csv (52 MB) 1.02 s PASS
All 7 ops (sum, mean, min, max, std, var, count) million.csv 0.91 s PASS
Column filter (-c price,returns) million.csv 0.75 s PASS
10-column wide million_wide.csv (108 MB) 1.77 s PASS
TSV input million.tsv (38 MB) 0.53 s PASS
12-digit precision million.csv 0.84 s PASS
JSON output million.csv 1.06 s PASS
Determinism: 3 consecutive runs million.csv – BIT-IDENTICAL JSON output

Numerical accuracy at 1M scale:

  • price mean = 499.12 (uniform [-500, 1500], expected ~500)
  • returns mean = -0.000048 (uniform [-0.1, 0.1], expected ~0)
  • volatility mean = 0.250038 (uniform [0, 0.5], expected 0.25)
  • score mean = 49.9653 (uniform [0, 100], expected 50)
  • Kahan summation label present in output

schema – Type Inference (1M rows)

Test Dataset Time Result
5 numeric columns million.csv (52 MB) 0.84 s PASS – types, min/max, nulls correct
10 columns million_wide.csv (108 MB) 1.46 s PASS – symmetric around 0
Messy data (NaN + empty) million_messy.csv (36 MB) 0.90 s PASS
TSV million.tsv (38 MB) 0.45 s PASS
Sampled (1,000 rows only) million.csv 0.12 s PASS – 8x faster
JSON output million.csv 0.62 s PASS
Determinism: 3 consecutive runs million.csv – BIT-IDENTICAL JSON output

Null detection accuracy at 1M scale:

  • measurement: 40,120 nulls (4.01%) – generated at 2% empty + 2% NaN = 4%
  • flag: 30,031 nulls (3.00%) – generated at 3% empty
  • reading: 10,004 nulls (1.00%) – generated at 1% NaN

inspect – File Analysis (1M rows)

Test Dataset Time Result
52 MB CSV million.csv 0.66 s 1M rows, 5 cols, min/max/mean correct
108 MB CSV million_wide.csv 1.13 s 1M rows, 10 cols
Messy CSV million_messy.csv 0.51 s Null counts match schema
TSV million.tsv 0.34 s Auto-detected delimiter
CJC source stress_compute.cjcl 0.04 s 8 functions, 0 parse errors

patch – Data Transformation (1M rows)

Test Dataset Time Result
Rename column million.csv (52 MB) 8.15 s “patched 1000000 rows”
Drop column million.csv 7.03 s Column removed
NaN fill million_messy.csv (36 MB) 5.53 s All NaN/empty replaced
Mean imputation million_messy.csv 6.53 s Correct mean computed
Replace values million_messy.csv 5.52 s Exact-match replacement
Rename + drop (10 cols) million_wide.csv (108 MB) 13.61 s Both transforms applied
TSV rename million.tsv (38 MB) 6.17 s Tab delimiter preserved

patch is I/O-bound at this scale – it writes the entire transformed dataset to stdout. All other commands read and aggregate without full re-serialization.

drift – Cell-by-Cell Comparison (1M rows)

Test Dataset Time Result
~1,001 injected diffs drift_a.csv vs drift_b.csv (86 MB) 1.34 s Found 1,001 cell differences
Identical files drift_a.csv vs itself 1.40 s “identical”, Frobenius = 0
With tolerance 1.0 drift pair 1.33 s Dropped to 936 diffs
Max diffs 5 drift pair 1.03 s Only 5 diffs shown
JSON output drift pair 1.44 s Valid JSON
12-digit precision drift pair 1.06 s max_deviation = 958.501978518200

seek – File Discovery (Full Project)

Test Scope Time Result
All .rs files 96K files in project 10.74 s 905 Rust files
All .csv files full project 9.77 s 3 CSV files
Content search (fn in .cjcl) full project 7.78 s 67 matching files
Files > 100 KB full project 5.78 s Lists git objects + binaries
Everything (no filter) full project 5.68 s 95,948 files total
Scoped search (pub fn in crates/) crates/ only 1.77 s 164 files

seek traverses the full file tree including target/ and .git/. Scoped searches run in under 2 s.

proof – Determinism Verification (Heavy Compute)

Test Program Time Result
3 runs, default seed stress_compute.cjcl 0.49 s PASS – stdout/exit/GC identical
10 runs stress_compute.cjcl 1.27 s PASS
5 seeds x 3 runs stress_compute.cjcl 1.62 s PASS across all seeds
10 runs, verbose stress_compute.cjcl 1.05 s All runs: 5 lines, gc=0

Computational correctness verified:

  • fib(20) = 6,765 (known correct)
  • sum(0..99999) = 4,999,950,000 (= 99999 x 100000 / 2)
  • collatz_steps(837799) = 524 (known Project Euler value)
  • count_primes(1000) = 168 (known: 168 primes below 1,000)
  • sum_gcd_pairs(100) = 13,015

bench – Performance Benchmarking (Heavy Compute)

Executor Mean Median CV Stability
Default (eval) 108 ms 107 ms 6.1% MODERATE
--mir 97 ms 98 ms 3.4% STABLE
--eval 107 ms 104 ms 10.0% MODERATE

MIR executor is ~10% faster with lower variance on this workload.

forge – Content-Addressable Caching

Test Result
forge run SHA-256 = 0f8544b7dd489d76...234ebb636, 29 output bytes
forge verify (correct hash) MATCH
Hash determinism (two clean runs) IDENTICAL SHA-256

trace, mem, doctor – Analysis Tools

Command Time Key Metrics
trace 0.30 s Parse: 0.3 ms, Exec: 232 ms, 8 functions, 0 GC
mem (5 runs) 0.69 s GC avg = 0, stable = true, avg exec = 130 ms
doctor (full project, 106 CJC files) 0.20 s 1 error (intentional), 83 type warnings

Audit Summary

Command Tests Run Passed Notes
cjcl proof 8 8/8 Multi-seed verdict cosmetic issue
cjcl flow 10 10/10 –
cjcl patch 11 9/11 --json/--plain flags not yet wired
cjcl seek 10 10/10 –
cjcl drift 8 8/8 Tolerance listing cosmetic issue
cjcl forge 8 8/8 –
cjcl inspect 11 11/11 –
cjcl schema 9 9/9 –
cjcl trace 9 9/9 –
cjcl mem 10 10/10 –
cjcl bench 9 9/9 –
cjcl pack 5 5/5 –
cjcl doctor 8 8/8 –
Total 116 114/116 2 cosmetic issues

Numerical Accuracy Guarantees

The following properties were verified at 1,000,000-row scale:

  • Kahan summation is active for all flow aggregations (label confirmed in output)
  • Sum, mean, variance, std all match expected values for known distributions
  • Frobenius norm accurate to 12 decimal places in drift comparisons
  • Null/NaN detection correct for empty cells, NaN strings, and missing values
  • Sample variance uses N-1 denominator consistently
  • SHA-256 hashes are deterministic across forge runs with cache cleared between invocations
  • 3 consecutive identical runs of flow and schema on 1M rows produce byte-for-byte identical JSON

Part 10 — Design Decisions and Trade-offs

Why No HashMap?

HashMap uses random iteration order in Rust (and most languages). This means any code that iterates over a hash map produces non-deterministic results. CJC-Lang uses BTreeMap and BTreeSet exclusively, trading some average-case performance for guaranteed deterministic iteration.

Why No FMA?

Fused multiply-add (FMA) computes a * b + c in a single instruction with one rounding step instead of two. This is faster and more accurate — but it produces different results depending on whether the hardware has FMA support. CJC-Lang uses mul_fixed (separate multiply and add) to guarantee identical results across all platforms.

Why Two Execution Engines?

The AST interpreter (cjc-eval) is simpler and easier to debug. The MIR executor (cjc-mir-exec) is faster and supports optimization. Having both means:

  • New features can be prototyped in the interpreter first
  • Parity tests catch subtle lowering bugs
  • Users can choose the right trade-off for their workload

Why Vec-Based Pauli Terms?

Quantum Hamiltonians are sums of Pauli terms. A natural representation is a hash map from Pauli string to coefficient. CJC-Lang uses Vec<PauliTerm> instead, because:

  • Iteration order is deterministic
  • No hashing overhead for small Hamiltonians
  • Summation order is fixed, so Kahan compensation works reliably

Why Sign-Stabilized SVD?

SVD is ambiguous in the signs of singular vectors. Two runs of the same SVD can produce vectors that differ by a sign flip. CJC-Lang’s MPS canonical form uses a sign convention (largest-magnitude element is positive) to eliminate this ambiguity. This is critical for deterministic tensor network simulations.


What’s Next

CJC-Lang v0.1.1 lays the groundwork for quantum-classical hybrid algorithms, noise-aware quantum simulation, and tensor network methods. Upcoming work includes:

  • Multi-file module system — programs that span multiple files with deterministic resolution
  • Default parameters and variadic functions — fn solve(x: f64, tol: f64 = 1e-6)
  • Decorator syntax — @log @timed fn train(x: Tensor)
  • Sparse eigensolvers — Lanczos and Arnoldi with deterministic iteration
  • MIR autodiff integration — gradients flowing through the MIR optimization pipeline

The language is growing, but the invariants remain fixed: no hidden allocations, no non-deterministic operations, no silent precision loss. Same seed, same bits, always.


CJC-Lang is open source and under active development. The codebase spans 21 Rust crates with zero external runtime dependencies. If deterministic numerical computing interests you, check out the introductory post or the v0.1.0 release notes.