Worksheet Lox

Table of Contents

1. Lox

From the schedule tab of the course homepage, download the lox interpreter for chapter 13. Because we deal with many versions of the language, I will sometimes identify them by chapter. Thus, the lox interpreter of chapter 13 will be called lox13.

Follow the instructions on the resources page to compile and run lox13. Play with the interpreter. Type in the programs from chapter 3 of the book and watch them execute.

Note that lox does not print anything unless you have an explicit print statement:

$ java -cp target/classes com.craftinginterpreters.lox.Lox  
lox13> 1+3
[line 1] Error at end: Expect ';' after expression.
lox13> 1+3;
lox13> print 1+3;
4

Multi-line programs must be included in a file, such as this:

fun returnFunction() {
  var outside = "outside";

  fun inner() {
    print outside;
  }

  return inner;
}

var fn = returnFunction();
fn();
$ java -cp target/classes com.craftinginterpreters.lox.Lox returnFunction1.lox
outside

Enter CTRL-D to exit the Lox REPL.

2. Scala

Here is a Scala version of the returnFunction from lox. This time, it returns a pair of functions rather than a single function. This is not easy to express in lox because it does not have built-in pairs.

def returnFunction() : (()=>Unit, ()=>Unit) = {
  var outside = "outside";

  def inner() = {
    println (outside);
  }
  def changeInner() = {
    outside = "something else";
  }
  return (inner, changeInner);
}

def main (args:Array[String]) = {
  var (fn1, fn2) = returnFunction();
  fn1();
  fn2();
  fn1();
}
$ scala returnFunction2.scala
outside
something else

You can also run it like this:

$ scala                      
Welcome to Scala 3.4.1 (21, Java OpenJDK 64-Bit Server VM).
Type in expressions for evaluation. Or try :help.

scala> :load returnFunction2.scala
def returnFunction(): (() => Unit, () => Unit)
def main(args: Array[String]): Unit
                                                                                
scala> main(Array())
outside
something else

Here we are invoking the main function with an empty Array.

Enter CTRL-D to exit the Scala REPL.

3. Lexical Structure

Take a look at the lexical structure of scala by examining the Language Reference

4. Visitor Pattern

Compare and contrast the following three versions of the same code.

4.1. Simple Java

abstract class Pastry {
  public void printMe (); 
}
class Beignet extends Pastry {
  @Override
  public void printMe() {
    System.out.println ("It's a beignet");
  }
}
class Cruller extends Pastry {
  @Override
  public void printMe() {
    System.out.println ("It's a cruller");
  }
}

class PastryTest {
  public static void main (String[] args) {
    var ps = new Pastry[] {new Beignet(), new Cruller()};
    for (var p : ps) {
      p.printMe();
    }
  }
}
$ javac PastryTest.java 
$ java PastryTest 
It's a beignet
It's a cruller

4.2. Scala match

enum Pastry:
  case Beignet
  case Cruller
import Pastry.*

def printPastry (p: Pastry) =
  p match
    case Beignet => println("It's a Beignet")
    case Cruller => println("It's a Cruller")

def main(args:Array[String]) = 
  var ps = List(Beignet,  Cruller)
  for (p <- ps) do printPastry(p)
$ scala Pastry.scala 
It's a Beignet
It's a Cruller

4.3. Java Visitor

interface PastryVisitor {
  public void visitBeignet(Beignet beignet); 
  public void visitCruller(Cruller cruller);
}
abstract class Pastry {
  public abstract void accept(PastryVisitor visitor);
}
class Beignet extends Pastry {
  @Override
  public void accept(PastryVisitor visitor) {
    visitor.visitBeignet(this);
  }
}
class Cruller extends Pastry {
  @Override
  public void accept(PastryVisitor visitor) {
    visitor.visitCruller(this);
  }
}

class PastryPrinter implements PastryVisitor {
  public void visitBeignet(Beignet beignet) {
    System.out.println ("It's a beignet");
  }
  public void visitCruller(Cruller cruller) {
    System.out.println ("It's a cruller");
  }
}
public class PastryTest {
  public static void main (String[] args) {
    var printer = new PastryPrinter ();
    var ps = new Pastry[] {new Beignet(), new Cruller()};
    for (var p : ps) {
      p.accept(printer);
    }
  }
}
$ javac PastryTest.java 
$ java PastryTest 
It's a beignet
It's a cruller

Author: James Riely

Created: 2025-04-01 Tue 17:12

Validate