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.

more...
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 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

cx in VS Code with completions and diagnostics

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.

VS Code Marketplace →

LSP editor setup →

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 screenshot

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 screenshot

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 output

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 screenshot

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.