cheatah
Guide

Transpiler

What purrc emits — every gen/ example, .purr beside its generated C++.

purrc is a transpiler: it compiles a .purr program to modern C++ — the .gen.cpp shown on the right — which is then built at -O3 -march=native into a loadable module the cheatah runtime runs. The whole program is emitted inside a namespace cheatah_program, where each module gets its own short alias (io::, ndarray::, …) and the exported entry point is a one-line extern "C" trampoline.

These are the programs in the repository's gen/ folder; regenerate them with bash gen/generate.sh to see how a language change moves the output.

fizzbuzz.purr

Ranges, if, floor division //, and string building.

# Copyright (c) 2026 BigBrain LLC. MIT-licensed (see LICENSE).
# Original work; see ACKNOWLEDGMENTS.md for the open-source ideas we build upon.
# FizzBuzz — ranges, `if`, floor division `//`, and string building. cheatah has no
# `%`, so divisibility is `i // n * n == i`.
import io

for i in range(1, 21) {
    let out = ""
    if i // 3 * 3 == i { out = out + "Fizz" }
    if i // 5 * 5 == i { out = out + "Buzz" }
    if out == "" { out = io.str(i) }
    io.print(out)
}
fizzbuzz.purrcheatah
// Generated by purrc — do not edit.
#include "cheatah.hpp"
#include "io.hpp"

namespace cheatah_program {

namespace builtins = ::cheatah::builtins;
namespace io = ::cheatah::io;

void purr_main() {
    for (long long i = 1LL; i < 21LL; ++i) {
        auto out = std::string("");
        if (((builtins::floordiv(i, 3LL) * 3LL) == i)) {
            out += "Fizz";
        }
        if (((builtins::floordiv(i, 5LL) * 5LL) == i)) {
            out += "Buzz";
        }
        if ((out == std::string(""))) {
            out = io::str(i);
        }
        io::print(out);
    }
}

}  // namespace cheatah_program

PURR_EXPORT void purr_main() { cheatah_program::purr_main(); }
fizzbuzz.gen.cppC++

http_response.purr

A +-chain self-append lowers to one chained ((head += a) += b) += c; — no temporary per piece.

# Copyright (c) 2026 BigBrain LLC. MIT-licensed (see LICENSE).
# Original work; see ACKNOWLEDGMENTS.md for the open-source ideas we build upon.
# Build a small HTTP response. Shows the in-place string self-append codegen:
# `head = head + ... + ...` lowers to a single chained `((head += a) += b) += c;`
# with no intermediate std::string — look for it in http_response.gen.cpp.
import io

fn response(status, ctype, body) {
    let nl = "\n"
    let head = "HTTP/1.1 " + status + nl
    head = head + "Content-Type: " + ctype + nl
    head = head + "Content-Length: " + io.str(len(body)) + nl
    head = head + "Connection: close" + nl + nl
    return head + body
}

io.print(response("200 OK", "text/plain", "hello, cheatah"))
http_response.purrcheatah
// Generated by purrc — do not edit.
#include "cheatah.hpp"
#include "io.hpp"

namespace cheatah_program {

namespace builtins = ::cheatah::builtins;
namespace io = ::cheatah::io;

static auto response(builtins::Value auto&& status, builtins::Value auto&& ctype, builtins::Value auto&& body) {
    auto nl = std::string("\n");
    auto head = ((std::string("HTTP/1.1 ") + builtins::str(status)) + builtins::str(nl));
    ((head += "Content-Type: ") += ctype) += nl;
    ((head += "Content-Length: ") += io::str(builtins::len(body))) += nl;
    ((head += "Connection: close") += nl) += nl;
    return (head + body);
}


void purr_main() {
    io::print(response(std::string("200 OK"), std::string("text/plain"), std::string("hello, cheatah")));
}

}  // namespace cheatah_program

PURR_EXPORT void purr_main() { cheatah_program::purr_main(); }
http_response.gen.cppC++

grades.purr

A struct with a method, a list, and method-call (UFCS) syntax.

# Copyright (c) 2026 BigBrain LLC. MIT-licensed (see LICENSE).
# Original work; see ACKNOWLEDGMENTS.md for the open-source ideas we build upon.
# A `struct` with a method, a `list` of them, and method-call (UFCS) syntax.
import io

struct Student {
    name: str
    score: float
    fn grade(self) {
        if self.score >= 90.0 { return "A" }
        if self.score >= 80.0 { return "B" }
        return "C"
    }
}

let roster = [
    Student("Ada", 95.0), 
    Student("Linus", 82.0), 
    Student("Grace", 78.0)
]

for s in roster {
    io.print(s.name + ": " + s.grade())
}
grades.purrcheatah
// Generated by purrc — do not edit.
#include "cheatah.hpp"
#include "io.hpp"

namespace cheatah_program {

namespace builtins = ::cheatah::builtins;
namespace io = ::cheatah::io;

struct Student {
    std::string name;
    double score;
    auto grade() const {
        if (((*this).score >= 90.0)) {
            return std::string("A");
        }
        if (((*this).score >= 80.0)) {
            return std::string("B");
        }
        return std::string("C");
    }
    void cheatah_pretty_print(std::ostream& os_, long long indent_) const {
        os_ << "Student(\n";
        os_ << std::string(indent_ + 4, ' ') << "name = ";
        os_ << this->name;
        os_ << ",\n";
        os_ << std::string(indent_ + 4, ' ') << "score = ";
        os_ << this->score;
        os_ << "\n";
        os_ << std::string(indent_, ' ') << ")";
    }
};
inline std::ostream& operator<<(std::ostream& os_, const Student& v_) {
    return os_ << "Student(" << "name=" << v_.name << ", score=" << v_.score << ")";
}

void purr_main() {
    auto roster = std::vector{
        Student{std::string("Ada"), 95.0},
        Student{std::string("Linus"), 82.0},
        Student{std::string("Grace"), 78.0}
    };
    for (auto& s : roster) {
        io::print(((builtins::str(s.name) + std::string(": ")) + builtins::str(s.grade())));
    }
}

}  // namespace cheatah_program

PURR_EXPORT void purr_main() { cheatah_program::purr_main(); }
grades.gen.cppC++

palette.purr

A scoped enum with match/case — the enum class lowering, with a generated operator<<.

# Copyright (c) 2026 BigBrain LLC. MIT-licensed (see LICENSE).
# Original work; see ACKNOWLEDGMENTS.md for the open-source ideas we build upon.
# A scoped `enum` + `match`/`case`. Shows the enum-class codegen.
import io

enum Color { RED, GREEN, BLUE }

fn to_hex(c) {
    match c {
        case Color.RED { return "#ff0000" }
        case Color.GREEN { return "#00ff00" }
        case Color.BLUE { return "#0000ff" }
    }
    return "#000000"
}

for c in [Color.RED, Color.GREEN, Color.BLUE] {
    io.print(c, "->", to_hex(c))
}
palette.purrcheatah
// Generated by purrc — do not edit.
#include "cheatah.hpp"
#include <ostream>
#include "io.hpp"

namespace cheatah_program {

namespace builtins = ::cheatah::builtins;
namespace io = ::cheatah::io;

enum class Color {
    RED,
    GREEN,
    BLUE,
};
inline std::ostream& operator<<(std::ostream& os_, Color v_) {
    if (v_ == Color::RED) return os_ << "Color.RED";
    if (v_ == Color::GREEN) return os_ << "Color.GREEN";
    if (v_ == Color::BLUE) return os_ << "Color.BLUE";
    return os_ << "Color(" << static_cast<long long>(v_) << ")";
}

static auto to_hex(builtins::Value auto&& c) {
    {
        auto __match_0 = c;
        if (__match_0 == Color::RED) {
            return std::string("#ff0000");
        }
        else if (__match_0 == Color::GREEN) {
            return std::string("#00ff00");
        }
        else if (__match_0 == Color::BLUE) {
            return std::string("#0000ff");
        }
    }
    return std::string("#000000");
}


void purr_main() {
    for (auto& c : std::vector{Color::RED, Color::GREEN, Color::BLUE}) {
        io::print(c, "->", to_hex(c));
    }
}

}  // namespace cheatah_program

PURR_EXPORT void purr_main() { cheatah_program::purr_main(); }
palette.gen.cppC++

vectors.purr

ndarray arrays through linalg routines — the numeric core, with per-module namespace aliases (ndarray::, linalg::).

# Copyright (c) 2026 BigBrain LLC. MIT-licensed (see LICENSE).
# Original work; see ACKNOWLEDGMENTS.md for the open-source ideas we build upon.
# A tiny numeric program — `ndarray` arrays into `linalg` routines.
import io
import ndarray
import linalg

let a = ndarray.array([[2.0, 1.0], [1.0, 3.0]])
let b = ndarray.array([1.0, 2.0])
io.print("solve A x = b ->", ndarray.to_string(linalg.solve(a, b)))
io.print("det(A) ->", linalg.det(a))
io.print("eigenvalues ->", ndarray.to_string(linalg.eigvalsh(a)))
vectors.purrcheatah
// Generated by purrc — do not edit.
#include "cheatah.hpp"
#include "io.hpp"
#include "linalg.hpp"
#include "ndarray.hpp"

namespace cheatah_program {

namespace builtins = ::cheatah::builtins;
namespace io = ::cheatah::io;
namespace linalg = ::cheatah::linalg;
namespace ndarray = ::cheatah::ndarray;

void purr_main() {
    auto a = ndarray::array(std::vector{std::vector{2.0, 1.0}, std::vector{1.0, 3.0}});
    auto b = ndarray::array(std::vector{1.0, 2.0});
    io::print("solve A x = b ->", ndarray::to_string(linalg::solve(a, b)));
    io::print("det(A) ->", linalg::det(a));
    io::print("eigenvalues ->", ndarray::to_string(linalg::eigvalsh(a)));
}

}  // namespace cheatah_program

PURR_EXPORT void purr_main() { cheatah_program::purr_main(); }
vectors.gen.cppC++

numerics.purr

Four modules linked into one program: math, ndarray and linalg each lower to an #include and a short namespace alias, solving a 3×3 system on the SIMD core.

# Copyright (c) 2026 BigBrain LLC. MIT-licensed (see LICENSE).
# Original work; see ACKNOWLEDGMENTS.md for the open-source ideas we build upon.
# The numeric core, several modules linked into one program: each `import` lowers to its own
# #include and a short namespace alias (math::, ndarray::, linalg::) in the generated C++.
import io
import math
import ndarray
import linalg

# A 3x3 system A x = b, built from nested lists (ndarray reads the shape off the nesting).
let A = ndarray.array([[3.0, 2.0, -1.0],
                       [2.0, -2.0, 4.0],
                       [-1.0, 0.5, -1.0]])
let b = ndarray.array([1.0, -2.0, 0.0])

# Solve with the SIMD linalg core, then check the residual norm ‖A x - b‖.
let x = linalg.solve(A, b)
let residual = linalg.norm(ndarray.sub(linalg.matmul(A, x), b))

io.print("x        =", x)
io.print("residual =", residual)
io.print("det(A)   =", linalg.det(A))
io.print("hypot    =", math.sqrt(3.0 * 3.0 + 4.0 * 4.0))
numerics.purrcheatah
// Generated by purrc — do not edit.
#include "cheatah.hpp"
#include "io.hpp"
#include "linalg.hpp"
#include "math.hpp"
#include "ndarray.hpp"

namespace cheatah_program {

namespace builtins = ::cheatah::builtins;
namespace io = ::cheatah::io;
namespace linalg = ::cheatah::linalg;
namespace math = ::cheatah::math;
namespace ndarray = ::cheatah::ndarray;

void purr_main() {
    auto A = ndarray::array(std::vector{
        std::vector{3.0, 2.0, (-1.0)},
        std::vector{2.0, (-2.0), 4.0},
        std::vector{(-1.0), 0.5, (-1.0)}
    });
    auto b = ndarray::array(std::vector{1.0, (-2.0), 0.0});
    auto x = linalg::solve(A, b);
    auto residual = linalg::norm(ndarray::sub(linalg::matmul(A, x), b));
    io::print("x        =", x);
    io::print("residual =", residual);
    io::print("det(A)   =", linalg::det(A));
    io::print("hypot    =", math::sqrt(((3.0 * 3.0) + (4.0 * 4.0))));
}

}  // namespace cheatah_program

PURR_EXPORT void purr_main() { cheatah_program::purr_main(); }
numerics.gen.cppC++

shapes.purr

An interface lowers to a C++20 concept (a static_assert checks every struct that fulfills it), and an interface-typed parameter constrains the generated template — no inheritance.

# Copyright (c) 2026 BigBrain LLC. MIT-licensed (see LICENSE).
# Original work; see ACKNOWLEDGMENTS.md for the open-source ideas we build upon.
# Records with behavior. A `struct` lowers to a C++ struct; an `interface` lowers to a C++20
# concept, and an interface-typed parameter (`s: Shape`) constrains the generated template —
# checked at compile time, with no inheritance and no runtime dispatch.
import io

interface Shape {
    fn area(self)
}

struct Circle: Shape {
    r: float
    fn area(self) { return 3.14159 * self.r * self.r }
}

struct Rect: Shape {
    w: float
    h: float
    fn area(self) { return self.w * self.h }
}

# Constrained by the Shape concept: any record with an `area(self) -> float` fits.
fn report(s: Shape) {
    io.print("area =", s.area())
}

let c = Circle({.r = 2.0})
let r = Rect({.w = 3.0, .h = 4.0})
report(c)
report(r)
shapes.purrcheatah
// Generated by purrc — do not edit.
#include "cheatah.hpp"
#include "io.hpp"

namespace cheatah_program {

namespace builtins = ::cheatah::builtins;
namespace io = ::cheatah::io;

template <typename Self>
concept Shape =
    requires(Self& self) { self.area(); };

struct Circle {
    double r;
    auto area() const {
        return ((3.14159 * (*this).r) * (*this).r);
    }
    void cheatah_pretty_print(std::ostream& os_, long long indent_) const {
        os_ << "Circle(\n";
        os_ << std::string(indent_ + 4, ' ') << "r = ";
        os_ << this->r;
        os_ << "\n";
        os_ << std::string(indent_, ' ') << ")";
    }
};
static_assert(Shape<Circle>, "Circle must fulfill Shape");
inline std::ostream& operator<<(std::ostream& os_, const Circle& v_) {
    return os_ << "Circle(" << "r=" << v_.r << ")";
}

struct Rect {
    double w;
    double h;
    auto area() const {
        return ((*this).w * (*this).h);
    }
    void cheatah_pretty_print(std::ostream& os_, long long indent_) const {
        os_ << "Rect(\n";
        os_ << std::string(indent_ + 4, ' ') << "w = ";
        os_ << this->w;
        os_ << ",\n";
        os_ << std::string(indent_ + 4, ' ') << "h = ";
        os_ << this->h;
        os_ << "\n";
        os_ << std::string(indent_, ' ') << ")";
    }
};
static_assert(Shape<Rect>, "Rect must fulfill Shape");
inline std::ostream& operator<<(std::ostream& os_, const Rect& v_) {
    return os_ << "Rect(" << "w=" << v_.w << ", h=" << v_.h << ")";
}

static auto report(Shape auto&& s) {
    io::print("area =", s.area());
}


void purr_main() {
    auto c = Circle{.r = static_cast<double>(2.0)};
    auto r = Rect{.w = static_cast<double>(3.0), .h = static_cast<double>(4.0)};
    report(c);
    report(r);
}

}  // namespace cheatah_program

PURR_EXPORT void purr_main() { cheatah_program::purr_main(); }
shapes.gen.cppC++