A very simple progamming language from David Beazley's compiler course
func fib(n int) int {
if n < 2 {
return 1;
} else {
return fib(n-1) + fib(n-2);
}
return 0;
}
print fib(10);This repo implements:
- Lexer and Parser
- Compiler via LLVM
- Formatter
- Type checker
Source code moves through a sequence of independent AST passes before reaching native code:
Source
│
├─ Tokenizer — hand-written lexer; produces a flat token stream
├─ Brace checker — validates balanced braces before parsing
├─ Parser — recursive-descent; builds an untyped AST
│
├─ AST validator — checks structural invariants
├─ Type annotation — decorates every node with its Wabbit type
├─ Type checker — enforces type compatibility across the whole tree
├─ Constant folding — evaluates compile-time arithmetic (e.g. 2 * 3 → 6)
├─ Deinit — removes redundant initializations
├─ Scope resolution — rewrites Name nodes to typed LocalName / GlobalName variants
├─ Unscript — lifts top-level expressions into an implicit main function
│
├─ LLVM IR emitter — walks the simplified AST and emits .ll text
└─ clang — compiles .ll + runtime.c to a native binary
Errors point directly at the offending token with a source excerpt and caret underline.
Type mismatch in binary operation
var x int = 1.0 + true;
File "example.wb" line 1
var x int = 1.0 + true;
^^^^^^^^^^^
WabbitTypeError: Operator + not supported for types "float" and "bool"
Return type mismatch
func square(n int) int {
return 3.14;
}
File "example.wb" line 2
return 3.14;
^^^^
WabbitTypeError: Expression of type "float" cannot be assigned to return type "int".
Undeclared variable
print foo;
File "example.wb" line 1
print foo;
^^^
WabbitSyntaxError: Undeclared variable: `foo`.
break outside a loop
break;
File "example.wb" line 1
break;
^^^^^
WabbitTypeError: "break" can only be used within a loop
Install dependencies:
poetry install
Run the compiler CLI:
poetry run wabbit [COMMAND] [OPTIONS] FILE
| Command | Description |
|---|---|
tokenize <file> |
Print the token stream |
ast <file> |
Print the AST (supports --validate, --typed, --fold, --type-check, --deinit, --resolve, --unscript) |
source <file> |
Pretty-print formatted Wabbit source (--optimize to simplify first) |
llvm <file> |
Emit LLVM IR (--output <file> to write to a file) |
compile <file> <output> |
Compile to a native binary via clang |
poetry run wabbit compile examples/fib.wb fib
./wabbit/bin/fib
poetry run task test # run tests
poetry run task lint # lint with ruff
poetry run task fmt # format and auto-fix
poetry run task check_types # type-check with pyright
- Python 3.10+
clang(only required for thecompilecommand)