Skip to content
Saule
Docs

Introduction

Saule is a statically typed, class-oriented scripting language. It borrows Lua’s simplicity and runtime model — tables, closures, coroutines, multiple return values — and puts a real type system in front of them.

The goal is a language that stays small enough to hold in your head while refusing to let a nil reach production.

export class Player
local name: string
local health: integer
static maxHealth: integer = 100
fn init(name: string, health: integer)
self.name = name
self.health = health
end
fn damage(amount: integer)
self.health = self.health - amount
if self.health <= 0 then
self.health = 0
println(self.name .. " has fallen")
end
end
end

Lua’s ergonomics, without the runtime surprises. Lua’s single number type is split into integer and float, and mixing them is a compile error rather than a silent coercion. Tables are generically typed, so table<string> cannot quietly acquire an integer.

nil is opt-in. A variable cannot hold nil unless its type says so with ?. The compiler then makes you deal with it — through safe access, a coalescing default, or an explicit force unwrap you had to type out on purpose.

Classes, not table metaprogramming. Inheritance, interfaces, access modifiers and static members are language constructs with real declarations instead of metatable conventions you rediscover in every codebase.

Exhaustive pattern matching. match takes a value apart and binds what it finds — enum variants and their payloads, nil, literals, tuples — and it will not compile if you leave a case unhandled.