Explicit on demand, implicit by default.
Crisp (.crp) is a systems language that transpiles to Rust. You write compact source; crisp infers types, ownership, and error propagation, emits Rust, and rustc is the soundness boundary.
This is a Rust-hosted bootstrap compiler (v1.9.0) — public release track. It is not self-hosted yet (ROADMAP Phase 2 / milestone v2.0.0). The language document remains spec v0.2.0-draft — treat “spec-complete” claims cautiously; see known limitations and spec ↔ impl deltas.
Known Rust Result APIs from rust = true deps lower to Crisp ambient errors (CrispError::Thrown + ?) — see examples/rust_import, examples/net_http (#55).
Spec: docs/spec/CrispLang-SPECS-0.2.0.md
Quickstart: QUICKSTART.md
Web docs: crisp-lang.org · branch docs
Roadmap: ROADMAP.md
Changelog: CHANGELOG.md
Contributing: CONTRIBUTING.md
Security: SECURITY.md
Milestone: v1.9.0
License: MIT OR Apache-2.0 (LICENSE, LICENSE-MIT, LICENSE-APACHE).
Crisp is optimized for writing and local reading. Semantics are defined by lowering to Rust, not by a separate runtime or VM.
In practice that means:
- Types, borrows, lifetimes, and error sets are inferred globally when the source stays silent.
- When you need precision — public APIs, performance-sensitive paths, or ambiguous usage — you annotate, and the compiler treats those annotations as hard constraints.
-
revealis the “show your work” companion tocrisp: it prints inferred types, ownership (&/&mut), lifetimes, error sets, traits, and the emitted Rust that compact.crpsource leaves implicit. See QUICKSTART §10.
Crisp is a front end that produces Rust. Rust remains the authority on memory safety and data races. Crisp’s own borrow/region passes exist to drive good diagnostics and to decide what to emit (&, &mut, owned, .clone() fallbacks); they are not claimed as an independent soundness boundary. If generated Rust fails to compile, that is a crisp bug, not a user error.
Design goals: native code via rustc; HM-style type inference; deterministic global ownership dataflow; ambient fallible functions lowered to a uniform Result<T, CrispError>; compact syntax; tooling-first ergonomics.
Non-goals: scripting semantics; a GC; a stable library ABI across separately compiled units; pretending Crisp’s checker replaces rustc; claiming full enum/trait/shape coverage while those remain incomplete.
Crisp v0.2.0 (spec) retargets from “direct-to-LLVM language” to source → CIR → Rust → native. The unit of compilation is the whole program or a sealed crate — inferred signatures depend on call sites, so ad-hoc separate compilation without a lockfile is not supported.
.crp sources
│
▼
Lexer → Parser → Resolve → Type inference → Ownership → Regions → Errors
│
▼
CIR (typed, ownership-resolved IR)
│
▼
Rust emission ──► rustc ──► native binary
│
└── probe emit + rustc (§7.6 fallbacks when ownership disagrees)
| Stage | Crate / tool | Role |
|---|---|---|
| Lex / parse |
crisp-lexer, crisp-parser
|
UTF-8 .crp, expression-based AST, spans |
| Resolve | crisp-resolve |
File modules, use, prelude, visibility |
| Typeck | crisp-typeck |
HM inference + constraint solving |
| Ownership | crisp-ownership |
Global usage → & / &mut / owned; §7.6 fallbacks |
| Regions / errors |
crisp-regions, crisp-errors
|
Lifetimes, ambient ! → CrispError
|
| IR | crisp-cir |
Typed CIR consumed by emit |
| Emit | crisp-rust-emit |
Rust project under target/rust/, tests, crisp.lock
|
| CLI | crisp |
check, emit, build, run, test
|
| Inspect | reveal |
Companion CLI: inferred types/ownership/errors, traits, emitted Rust (QUICKSTART §10) |
| IDE | crisp-lsp |
Stdio LSP host (hover, inlay hints, diagnostics) + CrispAnalysis API (#56) |
Sealed crates (crisp.lock): a crate’s pub API has fully resolved signatures frozen at publish time. Downstream code analyzes against the lockfile, not re-inferred internals — the explicit tradeoff for whole-program inference inside a boundary.
Type vs ownership inference: HM-style unification handles types; ownership is a separate deterministic dataflow pass over the typed program. They are not unified — affine ownership does not compose with HM unification.
| Area | Surface | Lowers to |
|---|---|---|
| Functions | named f(x) = … or ` |
x |
| Bindings | x := value |
let / let mut
|
| Types |
type T = { … }, float, int, str, … |
Rust structs / aliases / f64 / i64 / String
|
| Generics | Prefer id(x: T), type Pair = { left: A, right: B }; <> pins / applies |
Rust type params (T: Clone on emit) |
| Errors |
f() ! E, throw, catch
|
Result<T, CrispError> |
| Modules | one file = one module; use m { f }
|
generated mod tree |
| Tests |
test, test_compile_fail
|
injected #[test] in emitted crate |
| Async / FFI |
async, await, extern "C"
|
Tokio / extern blocks (see examples) |
Comments: -- and nested {- -}. String interpolation: "hello {name}". Exponentiation: ** → .powf().
v1.9.0 — extern rust vec<float> / vec<int> (#153); OS prelude env_* / path_* / fs_write (#151); src/lib.crp emits Cargo [lib] (#152). v1.8.x language features remain.
Still open: crates.io republish (#66), repo visibility (#58); trait bounds / dyn Trait remain partial (#59). See ROADMAP.md.
MSRV: Rust 1.85 (rust-version in root Cargo.toml). CI runs Ubuntu + macOS on stable, plus an MSRV job.
Install the compiler from crates.io (puts crisp and reveal on your PATH via ~/.cargo/bin):
cargo install crisp-lang --locked
crisp --versionYou still need a Rust toolchain (1.85+) with cargo / rustc — Crisp lowers to a Cargo project and builds with rustc.
mkdir -p hello/src && cd hello
cat > crisp.toml <<'EOF'
[package]
name = "hello"
version = "0.1.0"
edition = "2026"
[build]
target = "rust"
runtime = "tokio"
error_model = "enum"
EOF
cat > src/main.crp <<'EOF'
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)))
}
EOF
crisp run .Expected output:
"hello world"
git clone https://github.com/jose-compu/crisp.git
cd crisp
# already installed via cargo install crisp-lang, or:
# cargo install --path crates/crpc --locked
crisp run examples/helloOther commands on a project:
crisp check . # resolve + typecheck
crisp emit . # write Rust under target/rust/
crisp build . # emit + cargo buildOptional LSP:
cargo install crisp-lsp --lockedSee QUICKSTART.md for project layout, modules, tests, and fallible functions. crates.io notes: docs/CRATES_IO.md (#66).
| Example | Topics | Notes |
|---|---|---|
hello, math, float_demo, enums
|
Shapes, implicit generics, integers, floats, enum + match | crisp test |
show_trait, trait_defaults, shapes
|
Traits, defaults, data shapes | crisp test |
generics_implicit, generics, generics_pub, shapes_generic, shapes_user
|
Implicit binders (preferred), pins, pub schemes, HasPosition + native ops / user Measure
|
crisp test |
std_traits, rust_import, net_http
|
Show/Eq/Ord, Rust crates, thin HTTP | |
defaults, inventory, server
|
Struct defaults, domain modules, config | |
fallible, fallible_chain
|
!, throw, catch, error chains |
|
vec_ops, data_pipeline
|
vec stdlib, fallible IO |
|
patterns, match
|
Pattern matching (literal-oriented today) | see limitations |
async_hello, async_spawn
|
Async / Tokio | |
ffi, unsafe_math
|
C FFI, unsafe
|
|
sealed |
crisp.lock sealed public API |
|
kitchen_sink, ownership_demo
|
Combined features | |
workshop |
Small multi-file workshop | crisp test |
design_patterns |
GoF-style multi-module patterns |
crisp test / check
|
abnormal_suite |
Compile-fail edge cases | typecheck / fail tests |
crates/ Rust compiler workspace (lexer → emit, crisp, lsp, reveal)
docs/ Spec, limitations, error catalog, web site scaffold
examples/ Sample .crp projects
std/ Standard library (Crisp prelude and modules)
tests/ Integration placeholders (fixtures live under crates/)
cargo build --release -p crisp-lang
cargo test --workspace --verbose
cargo fmt --all --check
cargo clippy --workspace -- -D warningsSee CONTRIBUTING.md. Spec conformance and e2e coverage live under crates/crisp-rust-emit/tests/ and crates/crpc/tests/.

