wolf

A compiled systems language. Pre-alpha; the surface still moves.

Memory lives in regions the compiler infers, so a program carries no lifetime annotations. Allocation goes through arenas by default. A region moves between tasks instead of being shared, which is what keeps concurrent access safe, and the aliasing that falls out of that is information the optimizer gets to use. Arithmetic is checked in every profile, including release.

fn fill(n: int) -> List[int] {
    var xs = List[int]()           // lands in the caller's current region
    for i in 0..n { (mut xs).push(i) }
    xs
}

fn main() -> !int {
    var total = 0
    region tmp {
        let xs = fill(100)         // allocated in tmp [mem.region.create.3]
        for x in xs { total += x }
    }                              // wholesale free [mem.region.intra.2]
    if total == 4950 { 0 } else { 1 }
}

That is corpus/memory/region_ambient_ok.lu, verbatim below its header. The callee allocates into the caller's region, so the list lives in tmp and dies with it, and the bracketed names in the comments are the specification clauses the program is pinned to. Run it in the browser, along with twenty-odd other programs from the same corpus.

What runs today

v0.1.0 is tagged, under the codename wolfgang. wolf build and wolf run compile .lu source to native machine code through the compiler's own backend, with no LLVM in the loop. wolf build --release goes through LLVM instead. Both tiers produce the same verdict and the same output on every corpus program they both execute, and CI holds a floor under how many that is, so the comparison cannot quietly shrink to nothing.

There is a second implementation. lupin is a reference interpreter written against the same specification, sharing no code with the compiler; the two are compared program by program through a published observation protocol. Neither is allowed to disagree with the other in silence. The playground on this site runs that interpreter, compiled to WebAssembly.

The performance goal the project set for itself, beating naive clang -O3 across a kernel suite, does not hold. The most recent measurement puts the suite geometric mean at 0.191 of that baseline, with three kernels ahead, one level, and nine behind by more than ten percent. The measurements ship with the code, including the ones that refute the goal, and the protocol for reproducing them ships beside them.

There are no macros; compile-time evaluation and reflection are the metaprogramming tier. There is no package registry.

Getting it

git clone https://github.com/wolffe-lang/wolf-lang
cd wolf-lang
cargo build --release -p wolf_driver
./target/release/wolf run corpus/hello.lu

That prints hello, wolf. To put the toolchain on your path instead, cargo xtask install copies both artifacts to ~/.local/bin: the wolf binary and the runtime archive it links programs against. The binary cannot link anything without the archive beside it, which is why the install step exists.

The toolchain pin is Rust 1.97.1, recorded in rust-toolchain.toml, and rustup honors it on the first cargo invocation. There are no build scripts anywhere in the wolf ecosystem. CI builds and tests linux x86-64 and aarch64, macOS aarch64, and windows x86-64. Tagged builds upload archives to the releases page; the packaging around them is a stub, so building from source is the path that is known to work.

Reading

The Wolf Book
The language text. Every sample in it is executed by CI against a pinned toolchain.
The playground
The reference interpreter in your browser, with corpus programs to load.
Diagnostics and warnings
Both catalogues, generated from the compiler's own registry.
The specification
Normative. Both implementations are readings of it.
The source
All of it, including the issue tracker where the open problems and the known divergences live.

Bruckner revised the same symphony for twenty years and left several versions behind. This is version 0.1.0.