Work

n0ne

A compiled language that reads like Python. No braces, no semicolons, no runtime. Straight to a native binary.

C Sarath Babu's n0ne, a compiled programming language. Metal type sorts in a composing stick beside the impression they print

I wrote a programming language.

Statically typed, compiled, no braces, no semicolons, no runtime. It goes straight to a native binary.

task main
    show("hello world")
n0ne run hello.n0

The gap it sits in

Python reads well and runs slowly, and it needs a runtime wherever it goes.

Go is fast and ships as one binary, and it makes you write things you already knew were true.

Rust does everything and asks you to understand a lot before it lets you do anything.

None of those is wrong. But there is a middle: something that reads like Python and compiles like Go, without the tax any of them charge.

That is what I was after.

What it looks like

Indentation for blocks, no punctuation holding it together.

fn add(a: int, b: int) -> int
    return a + b
 
type User
    name : string
    age  : int
 
fn (self User) greet()
    show(f"hi i am {self.name}")

Types annotate where it matters. Methods hang off types the way Go does it. F-strings, because every language eventually adds them and it may as well be there from the start.

Errors as values

No exceptions.

fn divide(a: int, b: int) -> result[int]
    if b == 0
        return err("cannot divide by zero")
    return ok(a / b)

A function that can fail says so in its return type. The caller has to look at it. try unwraps and propagates when you do not want to write the check.

fn load(path: string) -> result[string]
    data = try fs.read(path)
    return ok(data)

Same for absence. option[T] rather than a null that every value silently might be.

Neither is my idea. Both are the thing I most wanted from Rust without the rest of Rust attached.

How it gets to a binary

Source.n0Lexerindent and dedent stackParserrecursive descent, ASTSematypes, scopes, errorsLLVM IRemitted as textBinaryclang links it
No VM, no interpreter, no garbage collector

The compiler is Rust. Emitting LLVM IR rather than machine code is what makes this possible at all: LLVM does the optimisation and the target-specific work, which is decades of effort I am not going to reproduce.

The indent and dedent stack in the lexer is the part that took longest to get right. Significant whitespace is easy to describe and full of edge cases the moment someone mixes tabs and spaces or dedents two levels at once.

What comes with it

n0ne build file.n0    compile to a native binary
n0ne run file.n0      compile and run
n0ne fmt file.n0      format
n0ne test             run tests

A formatter from the start, because a language without one grows five styles and an argument. An LSP server and a VS Code extension, because a language you cannot get completions in is a language nobody tries twice.

io and fs are done. json and http are what v0.2 is for.

Where it is

87 tests passing. v0.1 shipped with the core language, v0.1.1 added while, match, const, break, continue and multiline strings.

v0.2 is in progress: the standard library. Then a package manager, then cross-compilation and a stable release.

It is a real compiler, and it is early. Both of those are true.

tl;dr

A language that reads like Python and compiles to a native binary with no runtime attached.

Source on GitHub