Sikau

Build an interpreter · Day 10 · about 50 min

Capstone: Loops and assignment

Add a feature through every stage: lexer, parser and evaluator.

Your language, your feature

This is how language designers work in practice: decide the syntax, teach the lexer the new words, give the parser the new grammar, and define what the new nodes mean. Each change is small because each stage has one clear job, which is exactly why interpreters are built as a pipeline.

Real language work means adding features that touch every stage. Chiya has no loops and no way to change a variable. You'll add both: while (cond) { … } and name = value. The lexer needs one new keyword, the parser two new statements, the environment an assign method, and the evaluator two new cases. When you're done, closures can even keep counters.

let i = 0;
let total = 0;
while (i < 5) {
  total = total + i;
  i = i + 1;
}
total  // 10

Assignment versus let

let x = 1 creates a name in the current env. x = 2 must change the existing variable, wherever it lives in the chain — otherwise a closure couldn't update a counter in its outer scope. So assign walks outwards like get, and if the name isn't defined anywhere it's an error, which catches typos like totl = 5.

assign(name, value) {
  if (this.vars.has(name)) this.vars.set(name, value);
  else if (this.outer) this.outer.assign(name, value);
  else throw new Error(`Unknown name: ${name}`);
}

In the parser, an assignment is an ident token followed by =. Peek two tokens ahead (tokens[pos + 1]) before deciding it isn't an expression.

The rest of this lesson

  • While loopsexplain
  • A closure with statepredict
  • Which stage changes?match
  • Running the looporder
  • Add while and assignmentchallenge
  • Badge quizquiz
  • What you learnedrecap

Continue this lesson free — run real code in your browser

Continue with Google

See all 10 lessons of Build an interpreter