NL The NL programming language

A language that takes correctness seriously.

NL is a statically typed, class-based language with native null safety, checked exceptions and exhaustive matching — compiled to compact bytecode and run by nlvm, a lightweight virtual machine written in Rust.

or install in one line
$ curl -fsSL https://nlvm.dev/install.sh | bash
~/app

01Why NL

Whole classes of bugs, caught before your program runs

Familiar C-family syntax, but the compiler is on your side: nullability, error handling and case analysis are part of the type system, not conventions.

Null safety, built in

Types are non-nullable unless you say otherwise. string|null is a real union type, and the compiler rejects unchecked use — with ?? and ?: to handle the null case in one expression.

string|null name = null;
system.Out.println(name ?? "anonymous");

int|null port = readPort();
int actual = port ?? 8080;

Errors you can't ignore

Checked exceptions: a method that can fail declares throws, and callers must catch or declare. Every exception carries a full stack trace, captured by the VM.

public static string load(string path)
        throws IOException {
    return system.io.File.readAllText(path);
}

try {
    system.Out.println(load("config.txt"));
} catch (IOException ex) {
    system.Err.println("Error: " + ex.message);
}

Exhaustive matching

match over an enum must cover every case — add a variant later and the compiler points at every match you forgot to update.

enum Color { Red, Green, Blue }

string name = match(c) {
    Color.Red:   "red",
    Color.Green: "green",
    Color.Blue:  "blue",
};

Functions are values

First-class function types with explicit signatures — including throws — plus closures and type inference with auto.

(int, int) => int add = (int a, int b) => a + b;
auto eight = add(3, 5);

(string|null) => int throws Exception len =
    (string|null s) => throws Exception {
        if (s == null) {
            throw new Exception("null");
        }
        return s.length();
    };

One binary, one file

nlc compiles your whole program into a single .nlp file. The VM is one dependency-free Rust executable. Ship both, done.

$ nlc Main.nl -o Main.nlp
$ nlvm Main.nlp
Hello, world!

Specified and tested

The language is defined by a versioned, public specification — nlvm-specs — and the implementation tracks it release by release, backed by a YAML conformance suite run in CI.

$ nlvm --version
nlvm 0.23.0 (nlvm-specs 0.8.48)
$ nltest tests/
232 passed, 0 failed, 232 total

02Dogfooding

03Under the hood

A compiler and a VM, built as one toolchain

One Rust workspace, eight crates. The bytecode format is a single shared definition between compiler and VM, so the two halves can never drift apart.

140+
conformance tests
8
Rust crates
1
file to ship (.nlp)
0
runtime dependencies

Ready to try it?

Clone, build with Cargo, and run your first program in under a minute.