calx
A compiler written in C++ that emits C for clang, with ownership checked at compile time, parallel loops the compiler proves race-free, and numbers that behave exactly like Java’s.
- 0.7×Rust’s time per tick on the tick-loop benchmark
- 32 msTo check 64 modules, 9,900 lines
- 260Test programs, run on Windows and Linux
Problem
Calcite has to reproduce vanilla Minecraft bit for bit, which means Java’s integer overflow and float rounding, while ticking across every core. Java brings a garbage collector into the tick. Rust and C++ don’t give Java’s math by default, and neither proves that parallel work can’t race.
What I built
Calx is a strict, compiled systems language. The compiler is C++ and emits C that clang builds on Windows and Linux. It has structs, enums, generics, interfaces, optionals, error values and modules, and a standard library with networking on IOCP and epoll, threads, files, hashing, crypto, zlib, lz4 and HTTP.
How
- 01
Ownership is checked at compile time and costs nothing at run time: no garbage collector, no reference counts. Unchecked code is opt-in and limited to the server core and trusted plugins.
- 02
parallel for runs a loop across every core, and the compiler checks that no iteration touches what another one changes. A program prints the same output on one thread or 24.
- 03
Integers and floats behave exactly as in Java, and std.java.math gives StrictMath’s results, so Calcite can match vanilla to the last bit.
- 04
Stricter than Rust: no implicit conversions, no dropped values, no unused names and no shadowing. Every error says what to write instead.
- 05
Libraries can be opened while a program runs, for plugins, and attributes written in Calx generate code at compile time.
- 06
calx run takes about 0.3 s from an empty cache and under 25 ms when nothing changed. CI times the builds and checks the benchmark’s checksum on every push.
struct Region {
blocks: List<i32>,
total: i64,
}
fn tick(r: mut Region, scale: i32) {
for i in 0usize..r.blocks.len() {
r.blocks[i] = r.blocks[i] * scale + 1
r.total += i64(r.blocks[i])
}
}
fn main() {
var regions = List<Region>()
for k in 0..16 {
regions.push(Region { blocks: [k, k + 1, k + 2], total: 0 })
}
parallel for k in 0usize..regions.len() {
tick(mut regions[k], 3)
}
println("{regions[0].total} {regions[15].total}") // out: 12 147
}Status
The compiler core and standard library are done and tested on Windows and Linux. The current phase is the protocol support Calcite needs to talk to a real client.