|
|
---
|
|
|
# edu-ylb8
|
|
|
title: '§1 Introduction: What We''re Building'
|
|
|
status: completed
|
|
|
type: task
|
|
|
priority: normal
|
|
|
created_at: 2026-03-10T23:30:02Z
|
|
|
updated_at: 2026-03-10T23:30:02Z
|
|
|
---
|
|
|
|
|
|
## §1 Introduction: What We're Building — Stub to fill
|
|
|
|
|
|
File: `edu/src/lisp-compiler.md`, section `### 1. Introduction: What We're Building`
|
|
|
|
|
|
Replace the stub line with full content. Target 600–900 words. Match the style of Section 1 in `markov.md`: motivating prose paragraphs that build genuine enthusiasm before introducing any technical detail.
|
|
|
|
|
|
## Learning objectives
|
|
|
|
|
|
- Understand what a compiler is and how it differs from an interpreter
|
|
|
- Know what MiniLisp looks like and what the compiler will produce
|
|
|
- Understand why Rust + nom is a good toolchain for this task
|
|
|
- Know what prerequisite Rust knowledge is assumed
|
|
|
- Have a concrete mental picture of the end goal before writing any code
|
|
|
|
|
|
## Content to write
|
|
|
|
|
|
**What is a compiler?** A compiler is a program that reads source code in one language and produces equivalent code in another. Unlike an interpreter (which executes source code directly), a compiler's output is a new program that can be run independently. Our compiler reads MiniLisp and writes C. That C can then be compiled by any standard C compiler (`cc`, `gcc`, `clang`) into a native binary.
|
|
|
|
|
|
**Why Lisp?** Lisp is the ideal first compiler target. Its syntax is maximally regular — every expression is either an atom or a parenthesised list. There is no operator precedence to track, no statement/expression ambiguity, and no complex grammar rules. The AST almost directly mirrors the syntax. This regularity lets the course focus on the *concepts* of compilation rather than the incidental complexity of a messier language.
|
|
|
|
|
|
**Why compile to C?** C is essentially portable assembly. It is available everywhere, compiles quickly, and produces fast native code. By targeting C rather than actual assembly, we get a working native compiler without managing registers, calling conventions, or instruction sets. C handles all of that.
|
|
|
|
|
|
**A teaser: what the compiler produces.** Show a realistic MiniLisp program (recursive factorial + display call) alongside the C output the compiler will emit. This makes the goal concrete from the first page.
|
|
|
|
|
|
MiniLisp source:
|
|
|
```lisp
|
|
|
; Compute n!
|
|
|
(define (factorial n)
|
|
|
(if (= n 0)
|
|
|
1
|
|
|
(* n (factorial (- n 1)))))
|
|
|
|
|
|
(display (factorial 10))
|
|
|
(newline)
|
|
|
```
|
|
|
|
|
|
Compiler output:
|
|
|
```c
|
|
|
#include <stdio.h>
|
|
|
#include <stdint.h>
|
|
|
#define TRUE 1
|
|
|
#define FALSE 0
|
|
|
typedef int64_t ml_int;
|
|
|
|
|
|
/* forward declarations */
|
|
|
ml_int ml_factorial(ml_int ml_n);
|
|
|
|
|
|
ml_int ml_factorial(ml_int ml_n) {
|
|
|
return (ml_n == 0) ? 1 : (ml_n * ml_factorial((ml_n - 1)));
|
|
|
}
|
|
|
|
|
|
int main(void) {
|
|
|
printf("%ld\n", ml_factorial(10));
|
|
|
return 0;
|
|
|
}
|
|
|
```
|
|
|
|
|
|
**Why Rust and nom?** Rust's type system makes compiler writing unusually safe: exhaustive pattern matching means you cannot forget a case, `Result<T, E>` enforces error handling at every stage, and the borrow checker prevents accidental aliasing of AST nodes. nom is a parser-combinator library — parsers are ordinary Rust functions that compose, test, and debug naturally. No grammar files, no code generation, no build scripts.
|
|
|
|
|
|
**What this course assumes.** The reader should be comfortable with: ownership and borrowing, enums and pattern matching, `Result` and `Option`, basic trait usage (`impl Trait for Type`), and `#[test]`. No prior compiler or parsing experience is required.
|
|
|
|
|
|
**How to follow along.** Reading sections (Parts 1, 3) can be read anywhere. Implementation sections build on each other in order — each section adds code to the same project. A reference solution appears in a collapsible block at the end of each exercise so you can verify your work without being spoiled.
|
|
|
|
|
|
## Style notes
|
|
|
|
|
|
- Open with a hook: writing a compiler is a rite of passage; it demystifies the tools programmers use every day
|
|
|
- Put the teaser code block early — visual motivation before prose motivation
|
|
|
- Keep the tone encouraging: this is achievable for any Rust programmer, no specialist knowledge required
|
|
|
- End by telling the reader exactly what they will have at the end: a binary that compiles MiniLisp programs to runnable C
|