cx is a fast language that gets out of your way
Built for shipping high-performance software and enjoying the process, it features safety checks by default, simple C-like syntax, and type-safe constructs as efficient as hand-written C.
enum Event {
Click(int x, int y),
Keypress(char key),
Quit,
}
void handle(Event event) {
switch event {
case Click: println("fire at ", event.x, ", ", event.y);
case Keypress: println("pressed ", event.key);
case Quit: println("quit");
}
}
void main() {
handle(Click(6, 7));
handle(Keypress('W'));
handle(Quit);
// Fieldless enums iterate all cases; cases print by name.
for button in MouseButton {
println(button);
}
}
enum MouseButton { Left, Middle, Right }- Null-safety
- Data-oriented
- Import C headers
- Vendored C libs
- LLVM + C backends
- Fast iteration via JIT
- Tagged unions
- Vector swizzles
- LSP
- Lazy iterators
- Zero-alloc closures
- Detects memory leaks
- Checked debug builds
- Joy of programming
Null safety at compile time
Every type is non-nullable unless marked with ?. The
compiler analyzes the data-flow to refine the type based on your null
checks, so a forgotten null check is a compile-time warning, not a
crash.
string? name = getName();
println(name.toLower()); // warning, name may be null
if name {
println(name.toLower()); // ok, name is non-null here
}
Catches leaks and double-frees in debug builds
Debug builds track every allocation and fail the run at exit if any leaked, reporting how many allocations and bytes went missing. No Valgrind round-trip for the common case.
$ cx run
memory leak: 1 allocation(s), 32 byte(s) leaked
Type-safe tagged unions
Tagged unions via enum, with switch
matching and automatic type-narrowing. Polymorphism without vtables,
allocation, or boilerplate.
switch event {
case Click: println("fire at ", event.x, ", ", event.y);
case Input: println("pressed ", event.key);
case Quit: println(event.x); // error, no 'x' in Quit
}
Zero-allocation iterator chains and closures
Functions like filter, map,
chain return pipeable lazy views. Lambdas can capture
locals, and each call site is monomorphized, so the whole pipeline runs
without a single heap allocation.
int limit = 5;
var total = numbers
.filter(n => n % 2 == 1 && n <= limit)
.map(n => n * n)
.sum();
println(total); // 35, zero heap allocations
Import C/C++ headers directly
C/C++ interop without bindings. Adopt cx file by file next to your existing C/C++ code. (For now C++ interop only supports C-like constructs.)
import "SDL3/SDL.h";
SDL_Init(SDL_INIT_VIDEO);
defer SDL_Quit();
Bundled C libraries
Vendored modules that provide cx-native APIs for C libraries such as
SDL3, raylib, and GLFW. extern declarations with
null-correct type annotations: calls go straight into the C library with
no wrapper layer.
import glfw;
var window = glfwCreateWindow(800, 600, "Demo", null, null);
glfwMakeContextCurrent(window); // ok, accepts null
glfwSwapBuffers(window); // warning, window may be null
Vectors and swizzles
Fixed-size arrays double as vectors: element-wise math, dot products, and GLSL-style swizzle reads and writes. Larger element-wise loops vectorize in release builds.
float[3] pos = [0.0, 10.0, 0.0];
float[3] vel = [3.0, 4.0, 0.0];
vel.y -= 9.8 * dt;
pos += vel * dt;
Errors are values
Fallible functions return Result by convention. Callers
handle both cases with switch: every error path is visible
in the code.
switch makeImage(width, height) {
case Ok img: println(img.width, "x", img.height);
case Err e: println("rejected: ", e);
}
Tooling included
VS Code extension and cx-lsp language server
Provides diagnostics, hover signatures, go to definition, completions, find references, and semantic highlighting. Works with VS Code and other LSP-compatible editors.
cx run for fast iteration via JIT
Compiles and instantly runs your project through an in-process JIT, implemented via LLVM ORC, providing faster iteration.
$ ls
main.cx util.cx
$ cx run
Hello world
cx test test runner
Mark a top-level function with @test to make it a unit
test, then run them all with the cx test command.
@test
void mathWorks() {
assert(add(2, 3) == 5);
}
Built with cx
Voxel game
Minecraft-style voxel game: procedural terrain, first-person movement, block breaking, and placing. OpenGL and GLFW, imported via the vendored modules.
Fractal explorer
GPU Mandelbrot explorer: the fragment shader evaluates the set per pixel with smooth coloring, so panning and zooming stay fluid. OpenGL and GLFW, imported via the vendored modules.
Raytracer
Whitted-style CPU ray tracer: three reflective spheres over a checkered ground plane, with shadows, Blinn-Phong highlights, and reflections. Zero dependencies; renders 1080p in about 0.1 seconds.
Boids
Flocking simulation: 1500 agents with separation, alignment, and cohesion over a uniform grid, colored by speed. SDL3 for graphics, imported as a plain C header.
Installing
Prebuilt binaries for Linux (x64), macOS (Apple Silicon), and Windows (x64). To build from source, see Building from source.
Install
$ curl https://cx-language.github.io/cx/install.sh | bash
Installs into ~/.cx, adds itself to your
PATH, and smoke-tests the result.
Write hello.cx
void main() {
println("Hello world");
}
Run it
$ export PATH="$HOME/.cx:$PATH"
$ cx run hello.cx
Hello world
New shells get the PATH automatically; this shell needs
one export first. Then cx run JIT-compiles and
executes in one step. Point your editor at the bundled
cx-lsp - see Editor setup.
Download
Download cx-windows-x64.zip from the latest release and unpack it.
> Expand-Archive cx-windows-x64.zip
> cd cx-windows-x64
Write hello.cx
void main() {
println("Hello world");
}
Run it
> .\cx.exe run hello.cx
Hello world
cx run builds and executes in one step. Point your
editor at the bundled cx-lsp.exe - see Editor setup.