LEVIATHAN v962456e · 962456eee1

leviathan-lang.com / docs / learn

A taste of metaprogramming

Compile-time folding with comptime, typed attributes, and rules that generate code.

Running the compiler on your code

Leviathan can run itself at compile time and generate code, with zero runtime reflection. An attribute is an inert, typed annotation; a rule matches a shape and injects code; and comptime folds a computation to a literal before the program ever runs.

comptime folds a value at build time

bool isPrime(int n) {
    if (n < 2) { return false; }
    int d = 2;
    while (d * d <= n) {
        if (n % d == 0) { return false; }
        d = d + 1;
    }
    return true;
}

int nextPrime(int n) {
    int candidate = n;
    while (!isPrime(candidate)) { candidate = candidate + 1; }
    return candidate;
}

// Fold a value at build time: the loop never runs at runtime.
comptime int TABLE_SIZE = nextPrime(1000);

console.writeln(TABLE_SIZE);
1009

Attributes

An attribute declares typed fields, and its fields are its arguments:

Declaring and applying an attribute

class User {
    public string name;
}

// An attribute: its fields ARE its arguments.
attribute Route { string method; string path; }

@Route("GET", "/users")
Array<User> listUsers() => [User("Ada"), User("Alan")];

console.writeln(listUsers().length());
2

Rules

A rule in a namespace can then find every @Route and wire up a router at compile time. The generated code is checked and compiled exactly like code you wrote by hand, so it costs nothing extra at runtime. The full story (rules, body-replacing rewrites, and procedural macros) is in the reference entries on metaprogramming, rules, and procedural macros.

See also