6. The Milestone 1 keyword set
- Status: Accepted
- Date: 2026-09-02
Context
"A small, deliberate set of keywords — nothing bloated" is a core design goal. The keyword set needs to be fixed early because it affects the lexer, the grammar, and what identifiers user code may use.
Decision
Milestone 1 defines exactly these 19 reserved words:
| Group | Keywords |
|---|---|
| Functions | fn return |
| Conditionals | if elif else |
| Loops | while for in break continue |
| Boolean logic | and or not |
| Literals | true false nil |
| Classes | class super |
| Empty block | pass |
Rationale for the debatable members:
fnoverdef/func/function— shortest unambiguous choice.elifoverelse if— one token, no nesting ambiguity, matches the single-keyword-per-concept style.and/or/notas words, not&&/||/!— they read as English, they cannot be confused with future bitwise operators, and Korrin has no C heritage to honour.selfis not a keyword. It is a conventional identifier — the name of a method's first parameter (0005). Using it outside a method is an ordinary "cannot findself" error, which is clear enough; making it a keyword would buy a marginally better message at the cost of one more reserved word and a special case in the resolver.superis a keyword, becausesuper.methodis special syntax: there is no value to bind a plain identifier to.passexists because indentation-defined blocks cannot be empty (0001).
Deliberately not keywords in M1: self, import, try, raise, catch,
let, var, const, match, lambda, global, nonlocal, async, await,
yield, with, del. Each is either deferred to a later milestone with its own
ADR or ruled out by another decision (let/var by
0011; global/nonlocal likewise).
Consequences
- The lexer's keyword table is a fixed 19-entry match.
import/try/raiseland later and will each get an ADR when their design is settled; user code today may use those words as identifiers, and reserving them later is a documented breaking change. Accepted for a pre-1.0 language.- Booleans-as-words means
notparticipates in operator precedence as a unary operator, handled in the Pratt parser.
Alternatives considered
- Symbol operators for logic (
&&,||,!). No benefit here; costs readability and a lexer that has to distinguish&/&&. - Reserving the post-M1 words now. Would break fewer future programs, but reserves words for features whose design (and therefore whose exact keywords) is not yet decided. Prefer to reserve a word when its ADR lands.
deffor functions. Fine, butfnis shorter and equally clear.