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 signatures go in extern rust / .crpi (#116). 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 →