▄▀█ █░░
   █▀█ █▄▄

   Usage:
     al run <file.al>      Run a program
     al --help             Show all commands

   Examples:
     al run hello.al
     al run examples/fibonacci.al
Install
curl -fsSL al.alistair.sh/install.sh | bash

How it works

AL compiles to bytecode and runs on a stack-based virtual machine. The compiler is written in V, producing a single native binary with no dependencies.

The VM supports closures, tagged enums with pattern matching, first-class functions, and a unified error handling model where both optional values and errors are handled with the same or syntax.

Language features

Everything is an expression

No statements. If/else, match, and blocks all return values. The last expression in a block is its value.

result = if x > 0 {
    'positive'
} else {
    'non-positive'
}

grade = match score {
    90..100 -> 'A',
    80..90 -> 'B',
    else -> 'C',
}

Optional values with ?

Functions that might not return a value use ? in their return type. Use 'or' to provide defaults.

fn find_user(id Int) ?User {
    if id == 0 {
        none
    } else {
        User{ id: id, name: 'found' }
    }
}

user = find_user(0) or User{ id: 0, name: 'guest' }

Error handling with !

Functions that can fail use ! with an error type. Handle errors with 'or', or propagate with !.

fn divide(a Int, b Int) Int!DivisionError {
    if b == 0 {
        error DivisionError{ message: 'divide by zero' }
    } else {
        a / b
    }
}

safe = divide(10, 0) or 0
safe_with_err = divide(10, 0) or err -> -1
result = divide(10, 2)!  // propagate error

Pattern matching

Match on values, enums, and even literal payloads. Exhaustive checking ensures you handle all cases.

enum Result {
    Ok(String),
    Err(String),
}

fn handle(r Result) String {
    match r {
        Ok('special') -> 'matched literal!',
        Ok(value) -> 'got: $value',
        Err(e) -> 'error: $e',
    }
}

Structs and enums

Define data with structs. Model variants with enums that can carry payloads.

struct Person {
    name String,
    age Int,
}

enum Status {
    Active,
    Inactive,
    Banned(String),
}

person = Person{ name: 'alice', age: 30 }
status = Status.Banned('spam')

String interpolation

Embed expressions directly in strings with $ for simple variables or ${} for expressions.

name = 'world'
greeting = 'Hello, $name!'
math = 'Result: 7'

First-class functions

Functions are values. Pass them around, store them, return them.

fn apply(x Int, f fn(Int) Int) Int {
    f(x)
}

double = fn(n Int) Int { n * 2 }
result = apply(5, double)  // 10

Assertions

Assert conditions that must be true. If they fail, the function returns an error.

fn process(x Int) Int!Error {
    assert x > 0, Error{ message: 'must be positive' }
    x * 2
}

a = process(5)!   // 10
b = process(-1) or err -> 0  // 0