# Build (debug)
cargo build --manifest-path turbo/Cargo.toml
# Build (release)
cargo build --release --manifest-path turbo/Cargo.toml
# Run all unit tests
cargo test --workspace --manifest-path turbo/Cargo.toml
# Run a .tb source file via JIT
cargo run --manifest-path turbo/Cargo.toml -- run turbo/tests/phase1/hello.tb
# Or via the installed binary:
# turbolang run turbo/tests/phase1/hello.tb
# Run integration tests (requires release build)
cd turbo && ./tests/run_tests.shThe compiler is a five-stage pipeline:
Source (.tb)
│
▼
Lexer (turbo-lexer, logos) → Token stream
│
▼
Parser (turbo-parser, recursive descent) → AST (Module)
│
▼
Semantic Analysis (turbo-sema) → Validated AST + type errors
│
▼
Codegen (turbo-codegen-cranelift) → JIT execution or AOT .o file
│ │
▼ ▼
done link with turbo_rt.c → native binary
- Lexer tokenizes source using the
logoscrate. Whitespace-insensitive; newlines and semicolons are filtered out by the parser. - Parser is hand-written recursive descent. Collects multiple errors for better diagnostics (no bail-on-first-error).
- Sema walks the AST to resolve types, check scopes, validate match exhaustiveness, and enforce trait bounds. Produces a
SemaResultwith both errors and warnings. - Codegen translates the AST into Cranelift IR.
jit_run()for development,aot_compile()for production binaries. - C Runtime (
turbo_rt.c) providesrt_print_*, allocation helpers, string operations, array/hashmap support, async primitives, and math functions. Linked into AOT binaries viacc.
| Crate | Path | Purpose |
|---|---|---|
turbo-lexer |
crates/turbo-lexer/ |
Logos-based tokenizer. Defines Token enum and Spanned<Token>. |
turbo-ast |
crates/turbo-ast/ |
AST node definitions (Module, Item, Expr, Stmt, TypeExpr, Pattern) and ErrorCode enum. |
turbo-parser |
crates/turbo-parser/ |
Recursive descent parser. Entry: parse(tokens) -> (Module, Vec<ParseError>), which also runs a post-parse COW rewrite pass (cow_rewrite.rs) before returning. |
turbo-sema |
crates/turbo-sema/ |
Semantic analysis and type checking. Entry: check(module) -> SemaResult (errors + warnings). |
turbo-codegen-cranelift |
crates/turbo-codegen-cranelift/ |
Cranelift JIT + AOT backend. Entries: jit_run(), aot_compile(). |
turbo-formatter |
crates/turbo-formatter/ |
Source formatter. Entry: format_source() / format_file(). Used by turbolang fmt. |
turbo-cli |
crates/turbo-cli/ |
CLI frontend (clap). Commands: run, build, test, fmt, init, lsp, repl, bench, doc, playground. |
turbo-lsp |
crates/turbo-lsp/ |
LSP server (lsp-server crate). Provides diagnostics, hover, and go-to-definition. |
turbo-ast (the shared vocabulary):
Span—Range<usize>, byte offsets into source.Spanned<T>— wraps any node with itsSpan.Module— root AST node; containsVec<Spanned<Item>>.Item— top-level:Function(FnDef),Struct(StructDef),Enum(EnumDef),Impl(ImplBlock),Trait(TraitDef),Import,Const.FnDef— function name, params, return type, body, plus flags:is_async,is_test,is_unsafe.StructDef— name, type params, derives, fields.EnumDef— name, type params, variants (each may carry data fields).Expr— expression nodes: literals,BinaryOp,Call,If,While,Match,Block,FieldAccess,MethodCall,Closure,ArrayLit,Index,Assign,Spawn,Await, etc.Stmt—Let { mutable, name, ty, value },Expr(...),Return(...),Defer(...).TypeExpr— type syntax:Named,Unit,Array,FnType,Result,Optional,Future,Inferred.
turbo-ast:
ErrorCode— unique error code enum (E0001-E0515). Defined inturbo-ast/src/errors.rs. Used by all error types. Seedocs/errors.mdfor the full table.
turbo-sema:
Ty— internal type representation:I8,I16,I32,I64,U8,U16,U32,U64,F32,F64,Bool,Str,Unit,Array(Box<Ty>),Struct(String),Enum(String),Fn(Vec<Ty>, Box<Ty>),Result,Optional,Future,TypeParam,Error.intis an alias forI64,floatforF64,usizeforU64.SemaError—{ code: ErrorCode, message: String, span: Span }.
turbo-codegen-cranelift:
TurboTy— codegen-level type tag (distinct fromTybecause Cranelift IR types alone can't distinguish e.g.strfromi64on ARM64).CodegenError—{ code: ErrorCode, message: String }.
- Every diagnostic carries an
ErrorCode(e.g.E0100) for searchable, unique identification. Codes are defined inturbo-ast/src/errors.rs. Full reference:docs/errors.md. turbolang explain E0100prints the description for any error code.- All error types carry a
Span(exceptCodegenError). The CLI usesariadneto render them as pretty diagnostics with the formaterror[E0100]: message. - Every rendered error ends with a
more info:footer pointing at the GitHub blob URLhttps://github.com/ZVN-DEV/Turbo-Language/blob/master/docs/errors/E0NNN.md. The URL is generated byerror_code_url()inturbo-cli/src/main.rs. Onceturbolang.dev/errors/has a real redirect, the URL will be flipped back to the short form (TODO(P3) inerror_code_url). - The parser collects errors into
Vec<ParseError>and continues parsing (error recovery). - Sema uses
Ty::Erroras a poison type to avoid cascading errors — if an expression has typeTy::Error, further checks on it are skipped.
- The long-form explanation for each error code lives in one place:
turbo/crates/turbo-cli/src/errors/E0NNN.md. The CLI embeds these viainclude_str!soturbolang explainworks in a release binary with no filesystem dependency. - A parallel public tree at
docs/errors/E0NNN.mdexists so the rendered footer URL has something to resolve to (currently a GitHub blob URL; theturbolang.dev/errors/E0NNNshort form is aspirational). These are symlinks pointing back at the source-of-truth files — never duplicate the content. turbo/crates/turbo-cli/build.rsparsesturbo-ast::ErrorCodeat build time and fails the build if any variant is missing adocs/errors/entry. This is the same exhaustiveness guarantee thedetailed_explanation()include_str!table provides for the source-of-truth side.- When adding a new error code, follow the checklist in
CONTRIBUTING.md("Adding a new error code") — both halves of the docs tree must be in place or the build breaks.
- Built-in functions (
print,assert,len,push,str_*,hashmap_*,math_*, etc.) are handled as special cases insidecompile_call()inturbo-codegen-cranelift/src/expr.rs. They are not in the AST; the compiler recognizes them by name. - To add a new built-in: add a branch in
compile_call(), implement the JIT function pointer in the codegen setup, and add the C implementation inturbo_rt.cfor AOT.
- A subset of builtins —
push,map,filter,replace,upper,lower,trim,repeat,split— are copy-on-write: they return a new value instead of mutating their first argument in place. - To make idiomatic code like
arr.push(4)ors.trim()still act as a mutation when used as a statement, the parser runs a post-parse pass (turbo-parser/src/cow_rewrite.rs) that rewrites every COW call in statement position into a self-assignment (arr = push(arr, 4)). Value-position calls are left alone. The pass threads avalue_ctxflag top-down from each function's return type. - The end-to-end regression tests are
turbo/tests/phase1/cow_tail_expression.tbandturbo/tests/phase1/cow_tail_rvalue_contexts.tb.
- Integration tests live in
turbo/tests/phase1/as pairs:foo.tb(source) +foo.expected(expected stdout). run_tests.shcompiles each.tbviaturbolang run, captures stdout, and diffs against.expected.- Expected-error tests: if the
.expectedfile starts withERROR:, the test runner checks that the compiler error output contains the pattern. - Unit tests use standard
#[cfg(test)]modules inside each crate.
# Unit tests (all crates)
cargo test --all --manifest-path turbo/Cargo.toml
# Integration tests (needs release build)
cargo build --release --manifest-path turbo/Cargo.toml
cd turbo && ./tests/run_tests.sh
# Single file
cargo run --manifest-path turbo/Cargo.toml -- run turbo/tests/phase1/fibonacci.tb- Create
turbo/tests/phase1/my_feature.tbwith afn main()that prints output. - Create
turbo/tests/phase1/my_feature.expectedwith the exact expected stdout. - For error tests, put
ERROR:<pattern>as the first line of.expected.
- Runtime (
turbo/crates/turbo-codegen-cranelift/runtime/turbo_rt.c): implement the C function (e.g.rt_my_func). - JIT setup (
turbo/crates/turbo-codegen-cranelift/src/jit.rs): register the function pointer in the JIT symbol table so the JIT can call it. - Codegen (
compile_call()inturbo/crates/turbo-codegen-cranelift/src/expr.rs, with built-in dispatch wired throughsrc/builtins.rs): add a branch that matches the function name, builds the Cranelift IR call, and returns the correctTurboTy. - Sema (
turbo/crates/turbo-sema/src/lib.rs): add the function signature to the built-in type environment so the type checker accepts calls to it. - Test: add a
.tb/.expectedpair inturbo/tests/phase1/. - COW registration (only if the builtin returns a new value instead of mutating in place): add its name to the
COW_BUILTINSlist inturbo/crates/turbo-parser/src/cow_rewrite.rsso statement-position calls get rewritten into self-assigns.
- AST (
turbo/crates/turbo-ast/src/lib.rs): add the variant toExpr,Stmt, orItem. - Lexer (
turbo/crates/turbo-lexer/src/lib.rs): add any new tokens/keywords. - Parser (
turbo/crates/turbo-parser/src/lib.rs): parse the new syntax into the new AST node. - Sema (
turbo/crates/turbo-sema/src/lib.rs): add type-checking logic for the new node. - Codegen (
turbo/crates/turbo-codegen-cranelift/src/lib.rs): add code generation for the new node. - Formatter (
turbo/crates/turbo-formatter/src/lib.rs): handle pretty-printing if applicable.
- AST: add to
TypeExprif it needs new syntax. - Lexer: add keyword token if needed.
- Parser: parse the type expression.
- Sema: add to
Tyenum, implement type-checking rules, updateresolve_type_expr(). - Codegen: add to
TurboTyenum, implementturbo_ty_from_type_expr(), handle incompile_expr(). - Runtime: add C support functions in
turbo_rt.cif the type needs runtime representation.
turbo/
Cargo.toml # Workspace root
crates/
turbo-lexer/ # Token definitions + logos lexer
turbo-ast/ # AST types (shared by all crates)
turbo-parser/ # Recursive descent parser
turbo-sema/ # Type checking + semantic analysis
turbo-codegen-cranelift/
src/lib.rs # Codegen entry, function/struct setup
src/expr.rs # Expression compilation incl. compile_call()
src/builtins.rs # Built-in function dispatch + JIT symbol table
src/runtime.rs # Runtime helpers and Cranelift glue
src/wasm_codegen.rs # WASM target backend
src/aot.rs # AOT object emission + linker invocation
src/jit.rs # JIT module setup + execution
src/stmt.rs # Statement-level helpers
src/turbo_types.rs # TurboTy enum
runtime/turbo_rt.c # C runtime linked into AOT binaries
turbo-formatter/ # Source formatter (turbolang fmt)
turbo-cli/ # CLI entry point + REPL + playground
turbo-lsp/ # Language Server Protocol server
tests/
phase1/ # Integration tests (.tb + .expected pairs)
adversarial/ # Edge-case / adversarial tests
regression/ # Regression tests
run_tests.sh # Integration test runner script
design/ # Language specification documents
examples/ # Example applications (web-api, desktop-app, etc.)