Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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:

GroupKeywords
Functionsfn return
Conditionalsif elif else
Loopswhile for in break continue
Boolean logicand or not
Literalstrue false nil
Classesclass super
Empty blockpass

Rationale for the debatable members:

  • fn over def/func/function — shortest unambiguous choice.
  • elif over else if — one token, no nesting ambiguity, matches the single-keyword-per-concept style.
  • and/or/not as words, not &&/||/! — they read as English, they cannot be confused with future bitwise operators, and Korrin has no C heritage to honour.
  • self is 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 find self" 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.
  • super is a keyword, because super.method is special syntax: there is no value to bind a plain identifier to.
  • pass exists 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/raise land 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 not participates 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.
  • def for functions. Fine, but fn is shorter and equally clear.