
Erlang/OTP 29, compiled to native code
Clause is an ahead-of-time compiler for Erlang. It preprocesses, parses and analyzes Erlang source, compiles it through LLVM and links native executables with its own runtime: lightweight processes on several scheduler threads, message passing, ports and per-process garbage collection.
Work in progress: Erlang/OTP 29 programs compile to native executables that run on Windows and Linux today, with Clause's own stdlib, kernel, crypto and ssl. Still to come: macOS Apple Silicon and native ARM hardware, OTP's own test suites, source file and line locations in stack traces, and more optimization; distribution and hot code loading are not supported. The benchmarks page shows where Clause stands against OTP; the documentation lists what works and where Clause differs.
Features
OTP 29
Modern Erlang syntax
Preprocesses and parses Erlang/OTP 29 source, native records included.
1.49× faster
Speed against OTP
Geometric mean of 31 benchmark kernels, Clause -O2 against the BEAM JIT.
clau -o app
Native executables
One command from Erlang source to a standalone program, compiled through LLVM with link-time optimization. Escripts too.
spawn · send · receive
Erlang processes
Lightweight processes with per-process garbage collection on several scheduler threads.
gen_server · ssl
OTP library
Clause's own stdlib, kernel, crypto and ssl with OTP 29's exports, results and errors.
gen_tcp · file · os
Ports and I/O
Files, subprocesses and TCP/UDP sockets on one event-driven I/O thread.
--print-types
Type inference
At O2, inferred types remove runtime checks and select specialized code.
clau --shell
Interactive shell
Links the Erlang shell into an executable: erl_eval, history and records, no BEAM.
7 targets
Cross-platform
Runs on Windows x64 and Linux x86-64; objects for seven targets.
Feature details
Frontend
- Erlang/OTP 29 syntax: records, maps, bitstrings, comprehensions, types and specifications
- Macros, includes and conditional compilation
- Parse transforms without an Erlang/OTP install: ms_transform, qlc, merl and your own
- ASN.1 specifications compiled into modules as asn1ct does: BER, DER, PER and UPER
Erlang semantics
- Pattern matching and guards in clauses, case, if and receive
- Records, funs, maybe and list, binary and map comprehensions
- Exceptions with try, catch and stack traces
Compiler
- Type inference with per-clause function types
- LLVM O0, O2 and Os, with link-time optimization across modules
- O2 removes type checks proven by inference
- O2 inlines small local functions, known funs and lists loops
- Proper tail calls and deep recursion
- Parallel code generation on every hardware thread
Runtime
- C++23 runtime with all Erlang term types, arbitrary-precision integers included
- Processes, selective receive, links, monitors and timers on several scheduler workers
- Per-process heaps with a copying garbage collector
- Concurrent ETS tables in C++
OTP library
- Clause's own OTP 29 modules with OTP's exports, results and error reasons
- gen_server, gen_statem, gen_event, supervisor, application and logger
- stdlib: lists, maps, string, binary, json, re, rand and the collection modules
- ets, dets, disk_log, zip and erl_tar with files as OTP writes them
- erl_scan, erl_parse, erl_lint, erl_eval, qlc and compile at run time, with compiled modules interpreted
- syntax_tools: erl_syntax, erl_prettypr, epp_dodger and merl
- kernel: file, gen_tcp, gen_udp, inet, inet_res and os
- crypto over OpenSSL with FIPS mode; public_key with certificate path, CRL and OCSP validation
- ssl: TLS 1.2 and 1.3 connections over OpenSSL's libssl
Projects and tooling
- One clau command from Erlang source to a native executable
- TOML projects with SQLite build caches
- Interactive Erlang shell with clau --shell
- Debug info with -g (CodeView or DWARF 5) and profiling with --profile
- Tested against the reference Erlang/OTP and benchmarked against OTP
Clause