vela

A small, fast, statically typed language that compiles straight to native x86-64 and ARM64 executables — no VM, no libc, no linker.

use std/io

struct Point {
    x: Float,
    y: Float,
}

fn Point.length(self) -> Float {
    return (self.x * self.x + self.y * self.y).sqrt()
}

fn main() {
    let p = Point{ x: 3.0, y: 4.0 }
    io.println("|{p}| = {p.length()}")
}

Get startedTake the tour

Why

Simple

The whole language is one document. Four primitive types, one reference model, no traits, no macros, no lifetimes, no implicit conversions.

Fast

About 33,000 lines per second, source to executable. A hello-world binary is 18 KB, starts in under a millisecond, and makes three syscalls before main.

Expressive

Closures, generics, sum types, pattern matching, string interpolation, and errors as values.

Cohesive

The collector, the collections, the formatter and the vela command are all written in Vela. There is no privileged layer you cannot read.

Install

curl -fsSL https://github.com/NT9712/vela/releases/latest/download/vela-1.1.0-linux-x86_64.tar.gz | tar xz
cd vela-1.1.0-linux-x86_64 && ./install.sh ~/.local
export PATH="$HOME/.local/bin:$PATH"

vela new hello && cd hello && vela run
hello from hello

A taste

use std/io
use std/fs

struct User {
    name: Str,
    age: Int,
}

enum Shape {
    Circle(Float),
    Rect(Float, Float),
    Empty,
}

fn area(s: Shape) -> Float {
    return match s {
        Shape.Circle(r) => 3.14159 * r * r,
        Shape.Rect(w, h) => w * h,
        Shape.Empty => 0.0,
    }
}

fn load(path: Str) -> !Str {
    let text = fs.read_file(path)?          // `?` propagates the error
    if len(text) == 0 {
        return err("{path} is empty")
    }
    return ok(text)
}

fn largest[T](xs: [T]) -> ?T {              // generics, monomorphised
    if len(xs) == 0 {
        return nil
    }
    let mut best = xs[0]
    for x in xs {
        if x > best {
            best = x
        }
    }
    return best
}

fn report(users: [User]) {
    let names = users.map(|u| u.name)       // closures, inference
    let oldest = largest(users.map(|u| u.age)) ?? 0
    io.println("{names.join(", ")} — oldest {oldest}")
    io.println("a circle of radius 2 covers {area(Shape.Circle(2.0))}")
}

Diagnostics are the product

A compiler that only says no wastes your time.

error: cannot add `Str` and `Int`
  --> demo.vela:8:18
   |
 8 |     let result = name + age
   |                  ^^^^^^^^^^
   = note: expected `Str + Str`
   = note: found    `Str + Int`
   = note: help: convert the right side with `str(x)`

What is actually here

partlanguagelines
bootstrap compiler, x86-64 and ARM64 backendsC12,000
runtime: allocator, collector, strings, collectionsVela2,900
standard library: io, fs, os, net, json, math, …Vela2,050
toolchain: formatter, docs, CLI, language serverVela2,600
testsVela + shell950
documentation and specificationMarkdown3,100

63 test groups: golden output, diagnostics, unit tests, formatter idempotency, the whole toolchain end to end, the language server, release packaging, a regression corpus and randomised fuzzing.

Two targets, no cross toolchain

The compiler encodes the instructions and writes the ELF itself, so cross-compiling needs nothing installed beyond velac.

vela build --target arm64
file build/hello-arm64
build/hello-arm64: ELF 64-bit LSB executable, ARM aarch64, statically linked

Honest limits