Download

Vader

The discipline of static typing, the ergonomics of a script.

A general-purpose language with type inference, compiled to native code by a compiler written in Vader.

An experiment: the compiler compiles itself and runs the examples on both back ends, the VM and native code. The language still changes from one version to the next.

A Shape is a circle or a rectangle, and the match must handle both: forget one and the program does not compile.

module "main"

import "std/io"
import "std/math"

// A sum type: `match` must cover every variant.
Shape :: Circle | Rect

Circle :: struct { radius: f64 }
Rect   :: struct { w: f64, h: f64 }

area :: fn(s: Shape) -> f64 = match s {
    is Circle -> pi * s.radius * s.radius
    is Rect   -> s.w * s.h
}

main :: fn() -> i32 {
    shapes: Shape[]: [
        Circle { .radius = 2.0 },
        Rect { .w = 3.0, .h = 4.0 },
    ]
    total := 0.0
    for s in shapes {
        total += s.area()          // UFCS: s.area() is area(s)
    }
    println("${shapes.len()} shapes, total area ${total}")
    return 0
}
2 shapes, total area 24.566370614359172

Why Vader

Types you rarely write

Inference fills in the types of locals, lambdas and generic calls. :: binds a constant, := a variable, and that is the whole ceremony.

No null by accident

A value can be null only when its type says so, T | null. After if user == null { return }, the compiler knows user is a User.

Errors are values

There are no exceptions. A function that can fail returns a union, string | IOError, and the caller handles it like any other value.

Functions, not classes

There are no classes and no inheritance. a.f(b) calls f(a, b), so any function reads like a method of its first argument.

Compile time, not macros

@comptime runs ordinary Vader during the build and keeps what it computes: tables, constants, checks.

Written in Vader

The compiler compiles itself, to the same C byte for byte, and a C compiler is enough to rebuild it from the seed in the repository.

One command for everything

  • vader run: runs a program on the bytecode VM, with no build step.
  • vader build: compiles a program to a native binary, through C.
  • vader test: runs the @test functions of a project.
  • vader fmt: formats the sources; it has no configuration.
  • vader doc: writes the API reference of a project, as a site like the Library reference.
  • vader new: starts a project.
  • vader lsp and vader dap: the language server and the debugger that the VS Code and IntelliJ extensions run.

Read on

Specification

The language, chapter by chapter: its types, functions, control flow, modules, decorators and compile-time execution.

Library

The standard library and the packages beside it: I/O, strings, collections, iterators, JSON, the build contract.

37 modules · 802 exports

Compiler

The self-hosted compiler: its lexer and parser, the type checker, lowering, the back ends, and the tools around it.

48 modules · 1748 exports