4.8 KiB
+++ title = "§2 MiniLisp Language Specification" priority = 5 status = "done" ticket_type = "task" dependencies = [] +++
§2 MiniLisp Language Specification — Stub to fill
File: edu/src/lisp-compiler.md, section ### 2. MiniLisp Language Specification
Replace the stub line with full content. Target 700–1000 words. This is a reference section — clear, precise, complete. Define the entire language before the reader writes a single parser.
Learning objectives
- Know every data type and its literal syntax
- Understand every special form and its evaluation rule
- Know which built-in operators and functions exist
- Know what is explicitly out of scope
- Have seen a complete, realistic MiniLisp program
Content to write
EBNF Grammar
Lead with the grammar as a compact reference:
program = expr* EOF
expr = atom | list | comment
atom = integer | boolean | string | symbol
integer = '-'? DIGIT+
boolean = '#t' | '#f'
string = '"' (char | escape)* '"'
escape = '\\' ('"' | '\\' | 'n' | 't')
symbol = sym_start sym_cont*
sym_start = ALPHA | '-' | '_' | '?' | '!' | '+' | '*' | '/' | '=' | '<' | '>'
sym_cont = sym_start | DIGIT
list = '(' expr* ')'
comment = ';' (not NEWLINE)* NEWLINE
Note: symbol must not match - followed by a digit (that is a negative integer).
Data Types
Integers. 64-bit signed. Optional - followed by one or more decimal digits. Examples: 42, -7, 0.
Booleans. #t (true) and #f (false).
Strings. Double-quoted. Supported escapes: \", \\, \n, \t. Example: "hello, world\n".
Symbols. Identifiers made of letters, digits, and -_?!+*/=<>. Must not begin with a digit. Must not begin with - followed by a digit. Examples: x, my-var, factorial, zero?, +.
Comments. ; to end of line. No block comments.
Special Forms
For each form: syntax pattern, evaluation rule, and one or two examples.
(define <name> <expr>) — Bind <name> to the value of <expr>. At top level, creates a global. Inside a function body, creates a local.
(define (<name> <param>...) <body>...) — Shorthand for (define <name> (lambda (<param>...) <body>...)). Requires at least one body expression.
(lambda (<param>...) <body>...) — Creates a function. Parameters and body are evaluated in a new scope. Returns the value of the last body expression. In MiniLisp, lambdas may only reference their own parameters and top-level names (no closures over enclosing function locals).
(if <cond> <then> <else>) — Evaluates <cond>; returns <then> or <else> depending on truthiness. Both branches are required.
(let ((<name> <expr>)...) <body>...) — Evaluates each <expr> in the current scope, then binds results to the corresponding <name> in a new inner scope, then evaluates <body>... in that scope. Returns the last body value.
(begin <expr>...) — Evaluates each expression in order; returns the last value. Used when multiple side effects are needed inside an if branch.
Built-in Operators
These compile directly to C infix operators. All take exactly two arguments except not (one argument).
| Form | C equivalent | Return type |
|---|---|---|
(+ a b) |
a + b |
integer |
(- a b) |
a - b |
integer |
(* a b) |
a * b |
integer |
(/ a b) |
a / b |
integer (truncating) |
(= a b) |
a == b |
boolean |
(< a b) |
a < b |
boolean |
(> a b) |
a > b |
boolean |
(<= a b) |
a <= b |
boolean |
(>= a b) |
a >= b |
boolean |
(not a) |
!a |
boolean |
Built-in Functions
These compile to C function calls defined in the preamble.
| Form | Behaviour |
|---|---|
(display expr) |
Print value to stdout; integers with %ld, booleans as true/false, strings with %s |
(newline) |
Print \n to stdout |
(error msg) |
Print msg to stderr and call exit(1) |
What Is NOT Supported
Be explicit. This sets expectations and prevents confusion:
- No floating-point numbers
- No pairs or lists (
cons,car,cdr) - No closures (lambdas cannot capture enclosing function locals)
- No tail-call optimisation
- No garbage collector
- No variadic functions
- No macros
- No
quoteorquasiquote
Section 18 discusses how these could be added.
Complete Example Program
End with a realistic multi-function program that exercises: define (function and variable), if, recursion, let, begin, display, newline, and arithmetic. A good choice: define even?, odd?, and collatz-length, then print results for a few inputs.
Style notes
- Grammar first (dense reference), then prose elaboration
- Tables for operators and built-ins
- Complete example is the last thing — a reward for reading the spec
- Be precise about symbol character set; ambiguity here causes parser bugs