Skip to content

XIOM Language Reference

Complete reference for every XIOM language construct. For tutorials and concepts, see Getting Started and Concepts.


Program Structure

A XIOM source file consists of top-level declarations: fn, type, enum, interface, module, const, use, extern.

use xiom.io;

fn main() -> Int {
  io.println("Hello, world!");
  return 0;
}

Scripts (via xiom run) may omit fn main() -- the compiler wraps top-level code automatically.


Variables and Constants

var -- Mutable variable

var x: Int = 0;        // type-annotated
var y = 42;            // type-inferred
var z: Float64 = 3.14;

let -- Immutable binding

let name: Str = "xiom";     // cannot be reassigned
let pi: Float64 = 3.14159;

const -- Compile-time constant

pub const MAX: Int = 1024;
pub const PI: Float64 = 3.1415926535;

Types

Primitives

Type Description Example
Int Signed 64-bit integer 42, -1
Int128 Signed 128-bit integer 170141183460469231731687303715884105727
UInt128 Unsigned 128-bit integer 340282366920938463463374607431768211455
Float64 64-bit IEEE 754 float 3.14, -0.5
Float128 128-bit IEEE 754 float 3.14 as Float128
Bool Boolean true, false
Str Immutable string "hello"
Char Single Unicode character 'a', '\n'
Unit Void / no value ()
UInt8 Unsigned 8-bit integer 255
Int32 Signed 32-bit integer -2147483648

Compound Types

Type Syntax
Struct type Point = { x: Float64; y: Float64; }
Enum enum Color { Red, Green, Blue }
Enum with data enum Option[T] { Some(T), None }
Interface interface Comparable { fn compare(self, other: &Self) -> Int; }
Tuple (Int, Str, Bool)
Array (fixed) [3]Int
Vec (dynamic) Vec[Int]
Slice &Slice[Int]
Map Map[Str, Int]
Set Set[Int]
Reference &T, &mut T
Raw pointer *T

Type Aliases

type UserId = Int;
type Point3D = { x: Float64; y: Float64; z: Float64; };

Functions

Basic function

fn add(a: Int, b: Int) -> Int {
  return a + b;
}

Method on a type (receiver)

pub fn Point.distance(self, other: &Point) -> Float64 {
  let dx = self.x - other.x;
  let dy = self.y - other.y;
  return math.sqrt(dx * dx + dy * dy);
}

Generic function

fn max[T: Comparable](a: T, b: T) -> T {
  if a > b { return a; }
  return b;
}

impl Trait return type (M9.6)

fn get_display() -> impl Display {
  return 42;
}

Control Flow

if / elif / else

if x > 0 {
  io.println("positive");
} elif x < 0 {
  io.println("negative");
} else {
  io.println("zero");
}

match -- Pattern matching

match value {
  Some(v) => io.println(v),
  None => io.println("nothing"),
}

Multi-line arms use braces:

match result {
  Ok(data) => {
    process(data);
    return data;
  }
  Err(e) => {
    io.println(e.message);
    return defaultValue;
  }
}

while let

while let Some(item) = iter.next() { process(item); }

if let is not implemented by the current compiler. Use match, or test a variant with if value is Variant when no binding is needed.

while loop

var i = 0;
while i < 10 {
  io.println(i);
  i = i + 1;
}

for loop (range-based)

for i in [0, 1, 2, 3] {
  io.println(i);
}

loop -- infinite loop

loop {
  // ...
  if done { break; };
}

break / continue

while i < 100 {
  i = i + 1;
  if i % 2 == 0 { continue; };
  if i > 50 { break; };
  io.println(i);
}

Loops can carry a label; break @label; and continue @label; target the labeled loop instead of the innermost one:

@outer: while i < 10 {
  var j = 0;
  while j < 10 {
    j = j + 1;
    if j > 5 { break @outer; }
  }
  i = i + 1;
}

Expressions

Arithmetic

a + b    a - b    a * b    a / b    a % b

Comparison

a == b   a != b   a < b    a <= b   a > b    a >= b

Logical

a && b   a || b   !a

Bitwise

a & b    a | b    a ^ b    a << b   a >> b   ~a

Assignment

x = value;           // simple
x += 1;              // compound: +=, -=, *=, /=, %=, &=, |=, ^=

Type cast

x as Float64;         // safe numeric cast
x as Int;             // truncating float->int

is -- Type check

result is Ok;         // true if result matches Ok pattern
value is Some;        // true if value is Some variant

? -- Error propagation

let file = io.read_file(path)?;
// Equivalent to:
//   match io.read_file(path) {
//     Ok(f) => f,
//     Err(e) => return Err(e.into()),
//   }

=> -- Implication (contracts only)

requires: x > 0 => result > 0

String interpolation via +

var msg = "Hello, " + name + "!";

Array/Vec indexing

arr[0]            // 0-indexed access
vec[i]            // bounds-checked at runtime

Field access

point.x             // struct field
enum_type.Variant   // enum variant
type.method()       // method call

Contracts

Contracts are compile-time verified safety annotations.

fn divide(a: Float64, b: Float64) -> Float64
  requires: b != 0.0
  ensures:  result * b == a
{
  return a / b;
}
type NonEmptyStack[T] = {
  items: Vec[T];
  invariant: items.len() > 0;
}
Clause Where Meaning
requires: fn Must be true when function is called
ensures: fn Must be true when function returns
invariant: type, enum Must hold for all instances of type

Error Handling

Result[T, E]

fn parse_int(s: Str) -> Result[Int, Str] {
  // ...
  return Ok(value);
  // or
  return Err("invalid integer");
}

Option[T]

fn find_user(id: Int) -> Option[User] {
  // ...
  return Some(user);
  // or
  return None;
}

Unwrapping

let val = result.unwrap();           // panics on Err
let val = result.unwrap_or(default); // safe fallback
let val = option.unwrap_or(42);     // safe fallback for Option

Modules and Visibility

module mylib.data;           // namespace declaration

pub fn public_api() { ... }; // visible outside module
fn private_impl() { ... };   // module-private

use xiom.io;                 // import module
use xiom.collections.Map;    // import specific type

Ownership and Borrowing

XIOM uses lexical-scope ownership. When a value leaves scope, it is freed.

fn take_ownership(v: Vec[Int]) { ... } // v is moved -- caller loses access
fn borrow_read(v: &Vec[Int]) { ... }   // v is borrowed -- caller keeps access
fn borrow_write(v: &mut Vec[Int]) { ... } // exclusive mutable borrow

See Memory Model for the complete ownership and borrowing rules.


Generics

fn identity[T](x: T) -> T { return x; }

type Pair[A, B] = { first: A; second: B; }

enum Option[T] { Some(T), None }

interface Add {
  fn add(self, other: &Self) -> Self;
}

// Bounded generic
fn sum[T: Add](a: T, b: T) -> T {
  return a.add(&b);
}

Unsafe and FFI

unsafe {
  let ptr = malloc(1024);
  free(ptr);
}

extern "C" {
  fn printf(format: *UInt8, ...) -> Int32;
  fn malloc(size: UInt) -> *UInt8;
}

Scripting Mode

XIOM supports a scripting workflow via xiom run:

xiom run script.xi          # JIT compile and execute
xiom run --watch script.xi  # auto-recompile on changes
xiom repl                   # interactive REPL
xiom --standalone script.xi # produce standalone binary

Shebangs are supported:

#!/usr/bin/env xiom
io.println("Hello from script!");

CLI Reference

Command Description
xiom build file.xi Compile to native binary
xiom run file.xi JIT compile and execute
xiom --check file.xi Type-check only (no codegen)
xiom doctor Verify toolchain (clang, opt)
xiom pkg search <q> Search registry
xiom pkg install <pkg> Install package
xiom pkg publish Publish package to registry
xiom doc file.xi Generate markdown docs
xiom doc file.xi --html Generate HTML docs
xiom fmt file.xi Format source code
xiom repl Start interactive REPL
xiom clean --cache Clean build cache

See Also

Document Covers
Syntax Detailed grammar and expression syntax
Type System Full type hierarchy, inference rules
Contracts Deep dive on requires/ensures/invariant
Memory Model Ownership, borrowing, move semantics
Generics Comptime monomorphisation, bounds
Standard Library Complete API reference