Chelis has two syntaxes for one language. Surf is what people read and
write: functions, named dimensions, pipes, algebraic data types, and
typed tensor programs. Deep is the canonical representation that tools
can inspect after Surf has done its job.
01 Functions are the everyday unit
Surf is the human-facing syntax. A function declares the tensor shape it returns, so callers and compiler passes agree on the shape contract.
module HelloTensordef main() -> tensor[n, f32] = { a = to_tensor([1.0, 2.0, 3.0]) b = to_tensor([4.0, 5.0, 6.0]) out = add(a, b) out}
02 Named dimensions travel through transforms
Dimensions are not comments. process works on a feature vector, and batch_process lifts it over the batch axis while preserving the feature axis in the type.
Surf supports algebraic data types and pattern matching. The compiler sees both variants of Activation, and match arms make the control flow visible in the source.
SurfSource slice: basics/pipeandmatch.ch
type Activation = | Relu | Sigmoiddef activate(act: Activation, x: &tensor[n, f32]) -> tensor[n, f32] = { match act with { | Relu => relu(x) | Sigmoid => sigmoid(x) }}
05 The type system rejects shape drift
Tensor widths, axes, and scalar element types are part of signatures and intermediate expressions. A wrong matmul width or bias shape is a type error instead of a backend crash.
After Surf is parsed, Chelis can lower to Deep: a stable s-expression tree for compiler tooling, shell integration, tests, and round-tripping back to Surf.
07 Automatic differentiation is a language primitive
grad takes a scalar-valued function and the parameter to differentiate with respect to. The result is the adjoint, computed by reverse-mode AD through the tensor graph.
The type system surfaces randomness, I/O, and device placement as effects. A function that uses dropout carries Random in its type; a handler like with seed(...) makes the randomness deterministic.
Tensors are consumed by default. Passing the same value to two call sites requires explicit copy(x) or read-only &borrow. The compiler rejects ambiguous ownership at check time.