CSCI 2041

ADVANCED PROGRAMMING PRINCIPLES

Programs as Data:

Representing Programs

Programs

Programmers think of programs as sequences of instructions, but compilers represent and manipulate them as “abstract syntax trees” or “expression trees”:

tree representation of let x=3+4 in (x*3)+1

The translation from sequences to trees is called parsing.

Let’s design a type to represent programs…

type expr =
  IntC of int
| Mul of expr*expr
| Add of expr*expr
| Sub of expr*expr
| Div of expr*expr

How would we represent the expression (8*2)*(0-1)?

Mul(Mul (IntC 8, IntC 2), Sub (IntC 0, IntC 1))

Or 3 / (1 - (2*3))?

Div(IntC 3, Sub (IntC 1, Mul (IntC 2, IntC 3)))

Let’s define a function to evaluate expressions (turn a program into a value)

let rec eval e = match e with
| IntC i -> i
| Mul (e1,e2) -> (eval e1)*(eval e2)
| Add (e1,e2) -> (eval e1)+(eval e2)
| Sub (e1,e2) -> (eval e1) – (eval e2)
| Div (e1,e2) -> (eval e1) / (eval e2)

A compiler would output:

  • code to evaluate e1,
  • code to evaluate e2,
  • code to perform the arithmetic:
let v1 = eval e1 in
let v2 = eval e2 in
v1+v2

What about let?

type expr =

| Let of string * expr * expr (* the name, value, and body *)
| Name of string

and evaluating:

let rec eval e = match e with
| Let (nm, e1, e2) ->
    let v = (eval e1) in (* uh... *)

| Name n -> (* wait a minute ... *)

We need an environment that gives values to names

let rec eval e env = match e with
| Let (n,e1,e2) ->
    let v = eval e1 env in
      eval e2 (n,v)::env
| Name n -> List.assoc n env

How do we represent let x = 3+4 in x*3+1?

let e = (Let ("x",Add (IntC 3, IntC 4),
  Add (Mul (Name "x", IntC 3), IntC 1)))

How about if?

type expr = …
| If of boolExpr*expr*expr (* condition, then-branch, else-branch *)

let rec eval e env = match e with
| If (cnd, thn, els) -> if (* cnd? *)

Looks like we need a way to represent booleans…

We can define boolExpr eval:

type expr = …
and type boolExpr = …
| Eq of exp * exp
| Gt of exp * exp

let rec eval exp env = …
and beval bexp env = match bexp with
| And (l,r) -> (beval l env) && (beval r env)
| Or (l,r) -> (beval l env) || (beval r env)
| Not x -> not (beval x env)
| BoolC b -> b
| Eq (e1, e2) -> (eval e1 env) = (eval e2 env)
| Gt (e1, e2) -> (eval e1 env) > (eval e2 env)

How do we represent…

Let v1 = 2*10 in
Let v2 = 3-4 in
if v1 > v2 then 3 else 17
let e2 = Let ("v1", Mul (IntC 2, IntC 10),
  Let ("v2", Sub (IntC 3, IntC 4),
  If (Gt (Name "v1", Name "v2"), IntC 3, IntC 17)))

What happens if we want to have other types in our programs, e.g. float, string,…?

cs2041.org

// reveal.js plugins