Syntax Guide for CJC Version 0.1.1
A comprehensive reference for CJC-Lang’s language features, compiler infrastructure, and quantum computing extensions.
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);
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 (
visitmodule) — read-only traversal covering all node variants withwalk_*functions - Metrics (
metricsmodule) — single-pass structural statistics: node counts, depth, operator frequencies, feature flags - Validation (
validatemodule) — structural checks: break/continue outside loops, duplicate params, empty match, unreachable code after return, nesting depth limits - Inspect (
inspectmodule) — deterministic text dumps:dump_ast_summary,dump_ast_metrics,dump_validation_report,dump_expr_tree - Node utilities (
node_utilsmodule) — helper methods likeExpr::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
LoopInfowithis_countable,trip_count_hint,num_exits, schedule metadata - Reduction analysis — enriched
ReductionInfowithaccumulator_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:
- Rust backend — optimized, compiled, fast
- 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:
pricemean = 499.12 (uniform [-500, 1500], expected ~500)returnsmean = -0.000048 (uniform [-0.1, 0.1], expected ~0)volatilitymean = 0.250038 (uniform [0, 0.5], expected 0.25)scoremean = 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% emptyreading: 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
flowaggregations (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,
NaNstrings, 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
flowandschemaon 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.