# Lecture 6 — 2018-02-01

## WhileNZ

This lecture is written in literate Haskell; you can download the raw source.

We started defining a simple imperative language, which we called WhileNZ. Here’s its syntax and semantics:

```
n in Nat
v in Var (some set of variables)
e in Expr ::= n | e1 plus e2 | e1 times e2 | neg e | x
c in Command ::= SKIP | c1 ; c2 | x := e | WHILENZ e DO c END
sigma in Store, the set of total functions assigning ints to variables
i.e. Var -> Z
(sigma[x |-> z])(y) = / z if x = y
\ sigma(y) otherwise
eval : Store -> Expr -> Z
eval(sigma, n) = n
eval(sigma, e1 plus e2) = eval(sigma, e1) + eval(sigma, e2)
eval(sigma, e1 times e2) = eval(sigma, e1) * eval(sigma, e2)
eval(sigma, neg e) = -eval(sigma, e)
eval(sigma, x) = sigma(x)
interp : Store -> Command -> Store
interp(sigma, SKIP) = sigma
interp(sigma, c1 ; c2) = interp(interp(sigma, c1), c2)
interp(sigma, x := e) = sigma[x|->eval(sigma, e)]
interp(sigma, WHILENZ e DO c END) =
if eval(sigma, e) = 0
then sigma
else interp(interp(sigma, c), WHILENZ e DO c)
```

We went over an example or two in class, running some loops and observing that sometimes `interp`

wasn’t well defined, i.e., sometimes it ran forever, which isn’t the sort of thing that math is supposed to do.

Try running `interp`

on the following programs… what do they do? Do they always terminate? If so, what values will you get out?

```
Y := 5;
X := 1;
WHILENZ Y DO
X := Y * X;
Y := Y - 1
END
```

What will `X`

be? What about `Y`

?

```
A := X;
WHILENZ A DO
B := B + 1
END
```

What values will `A`

, `B`

and `X`

have?

```
X := 1;
WHILENZ X DO
X := X + 1
END
```

## A simple interpreter

Here’s how to write an interpreter for our simple language consisting of arithmetic expressions, assignments, and loops.

The first order of business is thinking about variables: how should we represent them? Haskell’s map type seems like a good bet.

```
import qualified Data.Map as Map
import Data.Map (Map, (!))
type VarName = String
type Store = Map VarName Int
update :: VarName -> Int -> Store -> Store
update v n st = Map.insert v n st
```

### Arithmetic expressions

We return to our old friend, `ArithExp`

, adding a notion of variable.

```
data ArithExp =
Num Int
| Var VarName
| Plus ArithExp ArithExp
| Times ArithExp ArithExp
| Neg ArithExp
deriving (Show, Eq)
evalA :: Store -> ArithExp -> Int
evalA st (Var x) = st ! x -- Map.findWithDefault ?
evalA _ (Num n) = n
evalA st (Plus e1 e2) = evalA st e1 + evalA st e2
evalA st (Times e1 e2) = evalA st e1 * evalA st e2
evalA st (Neg e) = - (evalA st e)
```

The interpreter is pretty similar to our old one, but note that we take an extra argument, `st :: Store`

. The store is where we look for variables. If a variable isn’t in the store, then `Map.!`

will complain with an error.

###
Commands in `WhileNZ`

Having converted the mathematical grammar:

`s ::= skip | x := a | s1;s2 | while a s`

To a Haskell datatype:

```
data WhileNZ =
Skip
| Assign VarName ArithExp
| Seq WhileNZ WhileNZ
| WhileNZ ArithExp WhileNZ
deriving Show
```

Let’s set about writing our interpreter. While `evalA :: Store -> ArithExp -> Int`

, here `eval`

takes a `Store`

and a statement and returns a new store.

```
eval :: Store -> WhileNZ -> Store
eval st Skip = st
eval st (Assign x e) = update x (evalA st e) st
eval st (Seq c1 c2) = eval (eval st c1) c2
eval st eLoop@(WhileNZ e c) =
if evalA st e == 0
then st
else eval (eval st c) eLoop
```

We can try writing a program or two…

```
p1, p2 :: WhileNZ
p1 = Seq (Assign "x" (Plus (Var "x") (Num 1)))
(Assign "y" (Plus (Var "y") (Num (-1))))
p2 = Seq (Assign "y" (Num 5))
(Seq (Assign "x" (Num 0))
(WhileNZ (Var "y") p1))
```

…and then we can run them in a sample store:

```
stXY :: Store
stXY = Map.fromList [("x",0),("y",0)]
```