The functional systems language.
High-level thinking, native-level control.
Axiom lets you model your ideas with algebraic data types and exhaustive pattern matching, check side effects at compile time, and ship a native executable with no VM, no garbage collector and no calls into the C library.
- Ship the binary. That's it. Programs compile through LLVM to a native executable that carries its own allocator and talks to the kernel directly.
- Make side effects explicit. The compiler infers effects, requires
functions that perform I/O to say so, and checks promises like
restrict(no-io). - Find the problem. Keep moving. Every error has a precise
location, a stable code, often a fix your editor can apply, and a
full explanation behind
axiom explain. - Built for you and your agents. The syntax is uniform S-expressions, and the compiler can describe errors and symbols in a compact machine-readable form, so tools see the same facts you do.
- Read the compiler, in Axiom. The compiler is written in Axiom: over 136,000 lines of it. A clean checkout rebuilds it from committed LLVM IR, and the build stops unless two generations come out byte-identical.
- Bring Rust along. Declare Rust functions in an
externblock, andaxiom build --cratebuilds and links the crate for you.
Axiom is young. The core language is complete, the standard library, FFI and editor support are functional, and macros are partial. There is no package index and no green threads yet. What's ready today lists every feature with the test behind it.
Axiom needs llc from LLVM, and a C compiler for the final link.
# macOS
xcode-select --install
brew install llvm
export PATH="$(brew --prefix llvm)/bin:$PATH"
# Debian and Ubuntu
sudo apt-get install -y llvm clangThen install the compiler:
curl -fsSL https://raw.githubusercontent.com/chrispaig3/axiom/stable/scripts/install.sh | bash
export PATH="$HOME/.axiom/bin:$PATH"The installer downloads a prebuilt archive for macOS or Linux on arm64 and checks its SHA-256. Before it replaces anything, it builds and runs a small program with the new compiler. It only ever replaces an installation it made itself. On any other host it stops and points you here.
On any other host, including linux-x86_64, build from source. The
repository carries the compiler's own LLVM IR in bootstrap/, so all
you need is the prerequisites above:
git clone https://github.com/chrispaig3/Axiom.git && cd Axiom
./scripts/bootstrap-from-seed.sh --install .axiom-bin
export PATH="$PWD/.axiom-bin:$PATH"CONTRIBUTING explains what the bootstrap does.
--target picks the platform to generate code for. That sets the
syscall ABI and the standard library's platform modules:
axiom --target=linux-aarch64 emit-llvm main.ax -o main.llSupported: darwin-aarch64, linux-aarch64. The default is your
host.
A target is supported when a CI job executes what the compiler emits there. Both supported targets run the whole test battery on every change, and each ships a prebuilt archive.
Source-only: darwin-x86_64, freebsd-aarch64, freebsd-x86_64,
linux-x86_64, windows-aarch64, windows-x86_64,
baremetal-aarch64. The compiler emits
code for each, and
CI assembles that code on every change. CI runs the test battery on
none of them, so they aren't supported, and no prebuilt archive is
published for them. CI builds the compiler from the seed in
bootstrap/ on linux-x86_64, and on freebsd-x86_64 and
freebsd-aarch64 in FreeBSD 14.4 VMs. No runner builds it on
darwin-x86_64.
The compiler doesn't run on Windows, so windows-aarch64 and
windows-x86_64 are targets you cross-compile to from Linux or macOS.
No runner builds the compiler on baremetal-aarch64; its embedded
image checks and optional QEMU execution are described in the
embedded guide.
Start a project and run it:
axiom new hello && cd hello && axiom runHello from Axiom! 🚀
axiom new writes Main.ax and an axiom.pkg manifest. Inside a
project, run and build need no file name.
Here is a slightly bigger program. Put it in shapes.ax:
(import IO)
(data Shape
(Circle { r : Float })
(Rect { w : Float, h : Float })
(Triangle { b : Float, h : Float }))
(:: area (-> Shape Float))
;@axiom:restrict(no-io)
(fn (area s)
(match s
((Circle {r = r}) (* 3.14159 (* r r)))
((Rect {w = w, h = h}) (* w h))
((Triangle {b = b, h = h}) (/ (* b h) 2.0))))
(:: report (-> String Shape Int))
;@axiom:effect(io)
(fn (report name s)
{
(let a (area s))
(println "{name:<10}{a:>8.2}")
})
(:: main ())
;@axiom:effect(io)
(fn (main)
{
(report "circle" (Circle 2.0))
(report "rect" (Rect 3.0 4.5))
(report "triangle" (Triangle 4.0 3.0))
})axiom run shapes.axcircle 12.57
rect 13.50
triangle 6.00
Shape is a sum type with named fields, and area handles every case.
area promises it performs no I/O, and the compiler holds it to that.
report prints, so it says so with effect(io). Delete that line and
the compiler tells you the claim is missing.
When a match misses a case, the compiler names the case and offers
the fix:
(data Light
(Red)
(Amber)
(Green))
(:: next (-> Light Light))
(fn (next l)
(match l
((Red) (Green))
((Green) (Amber))))error[AX3005]: non-exhaustive pattern match: missing Amber
--> light.ax:8:10
|
8 | (match l
| ^ this `match` does not cover: Amber
|
= help: add the missing arms, each a `todo` until it is written ~>
((Amber) (todo "Amber"))
= help: import `todo` from IO ~>
(import IO (todo))
= help: run `axiom explain AX3005` for a full explanation
compilation failed due to 1 previous error
The commands you'll use most:
axiom run shapes.ax # compile and run
axiom build shapes.ax -o shapes # keep the native executable
axiom check shapes.ax # type-check and verify effects, no code generation
axiom test # run every function whose name starts with test
axiom fmt shapes.ax # the one canonical layout
axiom explain AX3005 # the full explanation for any error code
axiom repl # Axiom 0.7.9 - REPLIO is part of Axiom's own standard library, so the shapes binary
calls no C library function, for printing or for allocation.
For programs the size of real work, examples/
has a batch job over a million records, and the generator that writes
this repository's standard library reference.
Start at Read Axiom's docs. The main references are:
| Read | Use |
|---|---|
| Language | Syntax, types, effects and tools |
| Standard library | Recipes, including TCP with Net |
| Public API | Generated signatures and effects |
| Examples | Complete programs |
| Feature status | Supported behaviour and limits |
Editor setup, Rust, databases, cryptography and embedded guides are linked from the docs index. Compiler contracts and assurance records have their own development reading path there.
Issues and pull requests are welcome. CONTRIBUTING.md walks through the project layout, how the compiler works, and how to add a diagnostic or a standard library function. The rule every change follows is if you claim it, gate it: every claim is backed by a test that runs in CI.
If Axiom is useful to you, star the repository so other people can find it, and fork it to start your first contribution.
MIT. See LICENSE.
