CSCI 2041

ADVANCED PROGRAMMING PRINCIPLES

Programs as Data:

Functions

Programs

Representing programs:

type expr = <arith> | <bool> | <compare> | <let> | <if>
type expType = IntT | BoolT
type result = IntR of int | BoolR of bool

Last time: expressions, types for imperative programs.

What about functions and recursion?

Functions

What if we add functions?

type expType = ... | FunT of expType*expType

type expr = ...
| Fun of string * expType * expr
| Apply of expr * expr
type envType = (string*result) list
and result = IntR of int
| BoolR of bool
| Closure of expr * string * envType
let rec eval exp env= ...
| Fun (argname,argtype,body) -> Closure (body,argname,env)
| Apply(f,e) -> evalFunc (eval f env) e env
...
let add1 = Fun("n",IntT, Add(Name "n", IntC 1))
let four = Apply(add1, IntC 3)

let times3plus1 = Fun("n", IntT, Add(IntC 1, Mul (IntC 3, Name "n")));;
let t17 = Apply (times3plus1, IntC 17)
let rec eval exp env= ...
| Fun (argname,argtype,body) -> Closure (body,argname,env)
| Apply(f,e) -> evalFunc (eval f env) e env
...
and evalFunc func argexp env =
  let Closure (body, argn, def_env) = func in
  let argval = eval argexp env in
  eval body (argn,argval)::def_env
eval add1 [];;
eval four [];;
eval times3plus1 [];;
eval t17 [];;

How does name analysis change? Type checking?

Γ,(n : τ₁) ⊦   b : τ₂
Γ ⊦ Fun (n:τ₁, b) : τ₁ -> τ₂
f : τ₁ -> τ₂     e : τ₁
Apply(f,e) : τ₂

Previous examples won’t work for recursion…

let p1 = Let ("fact",
  Fun ("x",IntT,
    If (Eq (Name "x", IntC 0),
      IntC 1,
      Apply (Name "fact", Sub (Name "x",IntC 1)))
  ),
  Apply(Name "fact", IntC 3));;
eval p1 [];;
typeof p1 [];;

What would need to change?

Another way to implement evaluation:

and evalFunc func argexp env =
  let Closure (body, argn, def_env) = func in
  let bodyExp = subName body argn argexp in
  eval bodyExp def_env
and subName exp nm sub = match exp with
| Name n -> if n = nm then sub else (Name n)
| Let (n,v,b) -> if n = nm then Let(n,subName v nm sub, b) else
  Let (n, subName v nm, subName b nm)
| Fun (argn, argt, body) -> if argn = nm then exp else
  Fun (argn, argt, subName body nm sub)
| IntC _ | BoolC _ -> exp
| Not e -> Not (subName e nm sub)
| Add (e1,e2) -> Add (subName e1 nm sub, subName e2 nm sub)
...

Would this change anything?

cs2041.org

// reveal.js plugins