1. Overview & Core Goals
A language specification describes what the language means. It does not imply that every property of every program is formally proven.
XIOM is a compiled, statically typed, memory-safe systems programming language. It is designed around three properties that no existing mainstream language provides simultaneously:
| SAFE | Ownership-based memory safety with no garbage collector and no mandatory managed runtime. Memory is freed deterministically when the owner leaves scope. |
|---|---|
| VERIFIED | Pre-conditions, post-conditions, and type invariants are first-class language constructs: enforced at runtime today, and available to verification tooling for supported properties. Runtime checking and formal verification are distinct mechanisms. |
| PRECISE | The grammar is unambiguous. Every construct has exactly one canonical form. No implicit coercions; allocation is explicit in the language model, and library operations document when they allocate. |
XIOM compiles to native machine code via LLVM and to WebAssembly as a co-equal target. Self-hosting gates are cleared, but no self-hosted release has shipped; the released toolchain is the bootstrap compiler.
Status of this revision: it defines the core language. The current implementation surface, compiler flags, platform behavior and toolchain features are documented separately in the language documentation and are not part of this revision.
2. Design Principles
2.1 Canonical Syntax and Explicit Semantics
Every construct has exactly one canonical syntax. Formatting is part of the language specification. The canonical formatter (xiom fmt) is part of the compiler toolchain.
2.2 Explicit Over Implicit
Nothing happens without being written. Memory allocation is visible. Type conversions are explicit. If a function can fail, its return type says so. If a value can be absent, its type says so.
2.3 Contracts Are Specification
Contracts (requires, ensures, invariant) are not assert statements. They are formal specifications that the compiler reasons about. At minimum they compile to checked runtime guards with precise error messages.
2.4 No Null
The language has no null, nil, or undefined value. Absence is expressed through Option[T]. The compiler enforces exhaustive handling of the absent case at every use site.
2.5 Errors Are Types
Functions that can fail return Result[T, E]. There are no exceptions. The ? operator propagates errors explicitly.
2.6 Structural Interfaces
A type satisfies an interface if it has the required fields and methods. No implements declaration is needed.
2.7 Comptime Is the Only Metaprogramming
There is no preprocessor, no macro system, and no template language. All compile-time code generation uses comptime.
2.8 Derive -- Compiler-Generated Correctness
For common interfaces (Eq, Clone, Display, Hash, Ord), the programmer declares intent and the compiler generates the implementation. The generated code is always correct by construction.
3. Syntax Preview
Variables
let x: Int = 42 // immutable binding
var y: Float64 = 3.14 // mutable binding
let name = "XIOM" // type inferred
Functions with Contracts
fn divide(a: Float64, b: Float64) -> Float64
requires: b != 0.0
ensures: result * b == a
{
return a / b
}
Types with Derive
type Point = {
x: Float64;
y: Float64;
} derive[Eq, Clone, Display]
// Compiler generates eq(), clone(), to_str() automatically
Generics with Inline Constraints
fn max[T: Comparable](a: T, b: T) -> T {
if a > b { return a }
return b
}
let m = max(10, 20) // T = Int, inferred
Algebraic Types
enum AgentState {
Idle,
Patrolling(route: Vec[Vector3]),
Attacking(target: EntityId),
Dead(cause: DamageCause),
}
Error Handling
fn loadFile(path: Str) -> Result[File, IOError] {
let f = open(path)? // ? propagates error up
return Ok(f)
}
match loadFile("data.bin") {
Ok(file) => process(file),
Err(e) => log.error(e.message),
}
Methods with Implicit Self
pub fn Vec3.dot(other: &Vec3) -> Float32 {
return x * other.x + y * other.y + z * other.z
// self is implicit -- fields accessed directly
}
Structural Interfaces
interface Comparable {
fn compare(other: &Self) -> Int
}
type Score = { value: Int }
fn Score.compare(other: &Score) -> Int {
if value < other.value { return -1 }
if value > other.value { return 1 }
return 0
}
// Score satisfies Comparable -- no implements keyword needed
4. Primitive Types
| Type | Width | Description |
|---|---|---|
Bool | 1 bit | Only true or false. No integer coercion. |
Int | Platform (64-bit) | Signed. Default integer type. |
Int8-Int128 | 8-128 bits | Explicit-width signed integers, including Int128; integer literals beyond 64 bits are supported. |
UInt | Platform (64-bit) | Unsigned. Use for sizes and indices. |
UInt8-UInt128 | 8-128 bits | Explicit-width unsigned integers, including UInt128. UInt8 is aliased as Byte. |
Float32, Float64 | IEEE 754 single / double | Float64 is the default float type. Float128 is produced by conversion and has no literal suffix. |
Char | 32 bits | Unicode scalar value. Not a byte. |
Str | Fat pointer | Immutable UTF-8 slice. Not null-terminated. |
Compound Types
| Type | Description |
|---|---|
Option[T] | Either Some(value) or None. Replaces null. |
Result[T, E] | Either Ok(value) or Err(error). Replaces exceptions. |
Vec[T] | Heap-allocated growable array. |
Map[K, V] | Hash map. K must satisfy Hash and Eq. |
Set[T] | Hash set. T must satisfy Hash and Eq. |
(T, U, ...) | Tuple. Fixed arity, mixed types. |
*T | Raw pointer. Only usable inside unsafe blocks. |
5. Memory Model
XIOM uses ownership semantics for memory management. There is no garbage collector. Memory is freed when the owning binding leaves its scope. The model uses lexical scope borrowing: borrows are validated from scope nesting alone, without Rust-style lifetime annotations. This is a design choice, not a claim that the two languages have identical semantics.
Ownership Rules
| Rule | Description |
|---|---|
| Single Owner | Every value has exactly one owner at any time. Assignment moves ownership. |
| Scope Lifetime | A value is freed when its owning binding leaves scope. |
Read Borrow (&T) | Multiple simultaneous read borrows allowed. No mutation. |
Write Borrow (&mut T) | Exactly one write borrow at a time. No other borrows. |
| Explicit Clone | Duplicating requires .clone(). No implicit deep copy. |
| Move On Call | Passing a value to a function moves ownership unless the parameter is a borrow. |
Borrows cannot be stored in struct fields. Borrows cannot be returned from functions. This is a constraint, not a bug -- it is the design.
fn consume(data: Vec[Int]) { } // takes ownership
fn read_only(data: &Vec[Int]) { } // read borrow
fn mutate(data: &mut Vec[Int]) { } // write borrow
let v = [1, 2, 3]
read_only(&v) // borrow, v still valid
mutate(&mut v) // write borrow, v still valid
consume(v) // move -- v no longer usable
6. Contract System
Contracts are part of the language: pre-conditions, post-conditions and type invariants. They compile to runtime guards by default, and supported properties can be exported to verification tooling. Runtime checking and formal verification are different mechanisms, and a contract in the source is not by itself a proof.
Keywords
| Keyword | Semantics |
|---|---|
requires | Pre-condition. Must hold when the function is called. Caller is responsible. |
ensures | Post-condition. Must hold when the function returns. Implementation is responsible. |
invariant | Type-level contract. Must hold after every mutation of a value of this type; enforcement coverage in the current compiler is partial. |
result | Refers to the return value inside an ensures clause. |
self@pre | Value of self at the moment the function was entered. |
Type Invariants
type Health = {
current: Int;
maximum: Int;
invariant: current >= 0;
invariant: current <= maximum;
invariant: maximum > 0;
}
// The compiler rejects any code that could violate these invariants.
Contract Collection Methods
| Method | Meaning |
|---|---|
.is_sorted() | Elements are in non-decreasing order |
.all(closure) | All elements satisfy the predicate |
.none(closure) | No element satisfies the predicate |
.contains(value) | Collection contains the given value |
7. Target Platforms
| Target | Path |
|---|---|
| x86_64 Windows / Linux / macOS | XIOM -> LLVM -> native |
| aarch64 macOS / iOS / Android | XIOM -> LLVM -> native |
| riscv64 Linux | XIOM -> LLVM -> native |
| WASM (browsers, Node.js, edge, WASI) | XIOM -> LLVM -> WASM32 |
GPU and console targets are library concerns accessed through C FFI -- they are not language features.
8. Non-Normative Material
Language comparisons, benchmark methodology and trade-off discussions are documentation, not specification. They live on the Prior art and trade-offs page and the Why XIOM page, and do not define the language.