Public release v1.10.0 · Spec v0.2.0-draft · Star on GitHub

Use cases

High-performance prototyping in popular Rust domains. Compact .crp with implicit types; native emit that rustc checks. Same program surface is 37% fewer GPT-4 tokens than emitted Rust, which helps LLM agents iterate. No production case studies yet — each card links to live examples on GitHub.

CLI tools

Shapes, implicit generics, and interpolation — without spelling every type and borrow up front. Emit stays a normal Rust binary.

-- examples/hello/src/main.crp
shape Named = {
    name: str
}

type Guest = {
    name: str = "world"
}

id(x: T) = x

greet(who: Named) = "hello {who.name}"

pub main() = {
    world := Guest {}
    print(id(greet(world)))
}

-- run: crisp run examples/hello

Config & services

Structs with defaults, modules, and sealed APIs for small services that would otherwise drown in boilerplate.

-- examples/defaults/src/main.crp
type ServerConfig = {
    host: str  = "127.0.0.1"
    port: uint = 9000
    debug: bool = false
}

test "default port constant" = {
    assert_eq(9000, 9000)
}

pub main() = {
    cfg := ServerConfig { port: 3000 }
    log("port={cfg.port}")
}

Async workers

Tokio-backed async / await with Crisp’s lighter surface for spawn and sleep-style workflows.

-- examples/async_spawn/src/main.crp
worker() = async {
    sleep_ms(2)
    print("worker-done")
}

pub main() = async {
    spawn worker()
    sleep_ms(5)
    print("main-done")
}

FFI bridges

Call C with extern "C" and unsafe. Rust crates use rust = true + use serde_json { … } (see Interop).

-- examples/ffi/src/main.crp
extern "C" {
    abs(x: int) -> int
}

pub main() = {
    r := unsafe { abs(7) }
    print("ffi-result={r}")
}

Data pipelines

Vec operations, fallible IO, and chained transforms with ambient ! error sets instead of noisy Result at every step.

-- examples/fallible/src/main.crp
type IoError = { message: str }
type ParseError = { line: int }
type Config = { port: int }

read_file(path) -> str ! IoError =
    throw IoError { message: "not found" }

parse_config(text) -> Config ! ParseError =
    throw ParseError { line: 0 }

read_config(path) = {
    text := read_file(path)
    parse_config(text)
}

pub main() = {
    cfg := read_config("app.toml") catch _ -> Config { port: 3000 }
    print(cfg)
}

Multi-module design

Organize GoF-style patterns across files with Crisp modules — good practice for larger programs before sealed publish.

-- examples/vec2_methods/src/math/vector.crp
pub type Vec2 = {
    x: float
    y: float
}

impl Vec2 = {
    pub new(x: float, y: float) = Vec2 {
        x: x
        y: y
    }
    pub magnitude(self) =
        (self.x ** 2.0 + self.y ** 2.0) ** 0.5
}

-- see also examples/design_patterns

Rust crate interop

Depend on Cargo crates with rust = true, then import APIs TypeScript-style. Scalar and vec signatures (vec<float> / vec<int> / vec<str> / vec<bool>) go in extern rust / .crpi (#116 / #153 / #158). Known Result APIs become Crisp ambient errors (?).

-- examples/rust_import (crisp.toml: serde_json rust = true)
use serde_json { from_str, to_string }

pub main() = {
    v := from_str("[1, true, \"crisp\"]")
    s := to_string(v)
    print(s)
}

-- failures → CrispError::Thrown + ? (v1.5)
-- also: examples/net_http (ureq::get)

Traits, shapes & methods

Nominal trait / impl Trait for, data shapes, inherent impl Type, and prelude Show / Eq / Ord shims.

-- examples/show_trait/src/main.crp
trait Show = {
    show(self) -> str
}

type Point = {
    x: int
    y: int
}

impl Point = {
    pub new(x: int, y: int) = Point {
        x: x
        y: y
    }
}

impl Show for Point = {
    show(self) = "({self.x},{self.y})"
}

pub main() = {
    p := Point.new(3, 4)
    log("p={p.show()}")
}

Enums & match

Unit and tuple variants with match — a core systems-language pattern without Rust ceremony.

-- examples/enums/src/main.crp
type Color =
    | Red
    | Green
    | Blue
    | Custom(int, int, int)

describe(color) = match color {
    Color.Red -> "red"
    Color.Green -> "green"
    Color.Blue -> "blue"
    Color.Custom(r, g, b) -> "rgb({r},{g},{b})"
}

is_primary(color) = match color {
    Color.Red -> true
    Color.Green -> true
    Color.Blue -> true
    _ -> false
}

pub main() = {
    print(describe(Color.Red))
    print(describe(Color.Custom(1, 2, 3)))
    print(is_primary(Color.Blue))
}

Repo examples

Open any folder on GitHub, or run from a clone:

crisp run examples/hello
crisp run examples/enums
crisp run examples/show_trait
crisp run examples/shapes
crisp run examples/rust_import
crisp run examples/path_dep
crisp test examples/math
crisp check examples/design_patterns

All examples on GitHub → · Tutorial → · Install →

Feature snippets

Same patterns as the home gallery — copyable Crisp.

Enums + matchexamples/enums
type Color =
    | Red
    | Custom(int, int, int)

describe(color) = match color {
    Color.Red -> "red"
    Color.Custom(r, g, b) -> "rgb({r},{g},{b})"
}
Rust importexamples/rust_import
use serde_json { from_str, to_string }

pub main() = {
    v := from_str("[1, true, \"crisp\"]")
    print(to_string(v))
}
Traitsexamples/show_trait
trait Show = { show(self) -> str }

impl Show for Point = {
    show(self) = "({self.x},{self.y})"
}

label(x: T) = x.show()
Shapesexamples/shapes
shape HasPosition = {
    x: float
    y: float
}

distance(a: HasPosition, b: HasPosition) -> float = {
    dx := a.x - b.x
    dy := a.y - b.y
    dx * dx + dy * dy
}
Async spawnexamples/async_spawn
worker() = async {
    sleep_ms(2)
    print("worker-done")
}

pub main() = async {
    spawn worker()
    sleep_ms(5)
    print("main-done")
}