Tutorial
Building a Programming Language
A tutorial on building an interpreted programming language from scratch using Rust. You will build Lux, a dynamically-typed, interpreted language with functions, closures, control flow, a REPL, and a file runner.
Chapters
About this tutorial
A tutorial on building an interpreted programming language from scratch using Rust.
What You'll Build
Lux: a dynamically-typed, interpreted programming language with clean, modern syntax. By the end of this tutorial, you'll have a fully functional language with:
- Variables and data types (numbers, strings, booleans, lists, nil)
- Functions and closures
- Control flow (if/else, while, for loops)
- First-class functions and higher-order functions
- Dynamic typing with runtime type checking
- A REPL (Read-Eval-Print Loop) for interactive exploration
- A file runner for executing .lux programs
- Error reporting with source locations
What Lux Looks Like
// Variables and expressions
let name = "World";
let age = 30;
print "Hello, " + name + "!";
print "Age: " + str(age);
// Functions
fn fibonacci(n) {
if n <= 1 {
return n;
}
return fibonacci(n - 1) + fibonacci(n - 2);
}
print fibonacci(10);
// Closures
fn make_counter() {
let count = 0;
fn increment() {
count = count + 1;
return count;
}
return increment;
}
let counter = make_counter();
print counter(); // 1
print counter(); // 2
// Lists and iteration
let numbers = [1, 2, 3, 4, 5];
for n in numbers {
print n * n;
}
// Higher-order functions
fn map(list, f) {
let result = [];
for item in list {
push(result, f(item));
}
return result;
}
let doubled = map([1, 2, 3], fn(x) { return x * 2; });
print doubled;
Contents
| Chapter | Topic | Description |
|---|---|---|
| 01 | Language Design | Architecture, grammar, and project setup |
| 02 | Lexer | Tokenization and lexical analysis |
| 03 | Parser | Parsing tokens into an AST |
| 04 | Interpreter | Tree-walking interpreter and evaluation |
| 05 | Functions & Closures | First-class functions and closure capture |
| 06 | Advanced Features | Lists, for loops, string operations |
| 07 | Error Handling | Thorough error reporting |
| 08 | REPL & File Runner | Interactive shell and file execution |
| 09 | Testing & Debugging | Testing strategies and debugging tools |
| 10 | What's Next | Future features and resources |
Prerequisites
Required:
- Basic understanding of Rust (see rust/ for a complete tutorial)
- Familiarity with programming language concepts (variables, functions, loops)
- Command line basics
Recommended:
- Understanding of Rust ownership and borrowing (see rust/03-ownership.md)
- Knowledge of Rust enums and pattern matching (see rust/06-structs-enums.md)
- Experience with at least one programming language
No prior compiler/interpreter knowledge required! This tutorial teaches everything from scratch.
Quick Start
# Create the project
cargo new lux
cd lux
# Follow along with the tutorial, building each component
# Run the REPL
cargo run
# Run a .lux file
cargo run -- program.lux
# Run tests
cargo test
Learning Path
Fast Track (1 week, 2-3 hours/day)
- Read Chapter 1 to understand the architecture
- Implement chapters 2-4 (lexer, parser, interpreter core)
- Add functions (chapter 5)
- Build the REPL (chapter 8)
- Skip to chapter 10 for what's next
Comprehensive (2-3 weeks, 1-2 hours/day)
- Read all chapters in order
- Type out all code examples
- Complete the test suites in chapter 9
- Experiment with language extensions
- Build additional features from chapter 10
Project-Based (Flexible)
- Read chapter 1 for overview
- Implement one feature at a time
- Test as you go
- Refer to specific chapters as needed
Why Build a Language?
- Deep Understanding: Building a language teaches you how languages work from the inside
- Transferable Skills: Concepts apply to compilers, interpreters, DSLs, and code analysis tools
- Career Growth: Compiler/interpreter knowledge is rare and valuable
- It's Fun: Creating your own language is deeply satisfying
- Practical Applications: Build DSLs for your domain, custom scripting languages, configuration systems
What Makes This Tutorial Different
- Rust-based: Learn modern systems programming while building your language
- Full Implementation: Working code for every feature
- Practical Focus: Working language, not toy examples
- Error Handling: Emphasis on great error messages
- Testing: Full test strategy included
- Real-World Ready: REPL and file runner, like production languages
The Interpreter Pipeline
Source Code (text)
↓
LEXER (tokenization)
↓
Tokens (list)
↓
PARSER (syntax analysis)
↓
AST (abstract syntax tree)
↓
INTERPRETER (evaluation)
↓
Output / Side Effects
After This Tutorial
You'll be equipped to:
- Build custom scripting languages for your applications
- Create domain-specific languages (DSLs)
- Understand how production languages work
- Read compiler/interpreter source code
- Optimize and extend existing languages
- Interview confidently for compiler engineering roles
Additional Resources
- Crafting Interpreters by Robert Nystrom
- Writing An Interpreter In Go by Thorsten Ball
- The Rust Book
- Engineering a Compiler
Ready to build a programming language? Start with Chapter 1: Language Design!