CS 152 - Lecture 12

Cover page image

Cay S. Horstmann

The Simple Language SL1

Some SL1 Examples

Interpreter Outline

The Symbol Table

Evaluating Expressions

def eval(expr : Expr, symbols : List[(String, Any)]) : Any = 
  expr match {
    case Number(num) => num
    case Variable(name) => ... // find name in symbols   
    case Operator(left, right, f) => ...
      // was f(left, right), but now we don't know they are Int
    case IfExpr(cond, block1, block2) => ...
    ...
  }

Evaluating Blocks

Parsing Challenge: Function Calls

Calling a Function

Lab

???

Step 1: Becoming Comfortable with SL1

  1. Make a project lab11 and add this Scala code. Run the four SL1 programs from slide 3. What outputs do you get?
  2. Write a SL1 program that defines pow2 to compute 2n for a given n, then calls pow2(10). What is your program and what is its output?

Step 2: Understanding the Parse Tree

For each of the following SL1 expressions and blocks, draw a parse tree. That should be the tree returned by parser.parse(...).get. Write the tree sideways with indentations, like this for the expression x * (y + 1). Use - for indentations so they don't get lost in your report.

Feel free to modify the program to print the parse tree.

Operator
-Variable(x)
-Operator
--Variable(y)
--Number(1)
--<add function>
-<multiply function>
  1. { x, y => x + y }
  2. fac(x - 1)
  3. val sq = { x => x * x } ; sq(2)

Step 3: Understanding Symbol Tables

For each of the following scenarios, write the symbol table. Write it as a set of equations, like this

a = 3
sq = { x => x * x }
a = 2

where the newest symbols appear at the bottom. In our example, the last definition of a shadows the previous one. Note that each variable is bound either to an integer or a function.

  1. At the end of the program val a = 3 ; val b = a + 1; val a = 2 ; a + b
  2. At the execution of the function call in the program val a = 3; val sq = { x => x * x } ; sq(a + 2). Be sure to show the binding for x.
  3. At the execution of the function call in the program val a = 3; val x = 2; { x => a * x } (a)

Confirm your guesses for 2 and 3 with this trick. Define a function

def spy[T](t : T) = { println(t); t }

Then add a spy(...) call around

params.zip(args.map(eval(_, symbols))) ::: syms

in the evaluation of a Funcall.