77
Implemen’ng OCaml in OCaml An OCaml defini’on of OCaml evalua’on, or, COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse these slides for non-commercial educa’onal purposes 1

An OCaml definion of OCaml evaluaon, or,

  • Upload
    others

  • View
    4

  • Download
    0

Embed Size (px)

Citation preview

Page 1: An OCaml definion of OCaml evaluaon, or,

Implemen'ngOCamlinOCaml

AnOCamldefini'onofOCamlevalua'on,or,

COS326DavidWalker

PrincetonUniversityslidescopyright2013-2015DavidWalkerandAndrewW.Appel

permissiongrantedtoreusetheseslidesfornon-commercialeduca'onalpurposes

1

Page 2: An OCaml definion of OCaml evaluaon, or,

Implemen'nganInterpreter

letx=3inx+x

Let(“x”,Num3,Binop(Plus,Var“x”,Var“x”))

Num6

6

Parsing

Evalua'on

PreWyPrin'ng

textfilecontainingprogramasasequenceofcharacters

datastructurerepresen'ngprogram

datastructurerepresen'ngresultofevalua'on

textfile/stdoutcontainingwithformaWedoutput

thedatatypeandevaluatortellusalotaboutprogramseman'cs

2

Page 3: An OCaml definion of OCaml evaluaon, or,

WecandefineadatatypeforsimpleOCamlexpressions:

type variable = string

type op = Plus | Minus | Times | … type exp = | Int_e of int | Op_e of exp * op * exp | Var_e of variable | Let_e of variable * exp * exp type value = exp

MakingTheseIdeasPrecise 3

Page 4: An OCaml definion of OCaml evaluaon, or,

MakingTheseIdeasPrecise 4

WecandefineadatatypeforsimpleOCamlexpressions:

type variable = string type op = Plus | Minus | Times | … type exp = | Int_e of int | Op_e of exp * op * exp | Var_e of variable | Let_e of variable * exp * exp type value = exp let e1 = Int_e 3 let e2 = Int_e 17 let e3 = Op_e (e1, Plus, e2)

represents“3+17”

Page 5: An OCaml definion of OCaml evaluaon, or,

MakingTheseIdeasPrecise 5

WecanrepresenttheOCamlprogram:

let x = 30 in let y = (let z = 3 in z*4) in y+y;;

asanexpvalue:

Let_e(“x”, Int_e 30, Let_e(“y”, Let_e(“z”, Int_e 3, Op_e(Var_e “z”, Times, Int_e 4)), Op_e(Var_e “y”, Plus, Var_e “y”)

Page 6: An OCaml definion of OCaml evaluaon, or,

MakingTheseIdeasPrecise 6

No'cehowthisreflectsthe“tree”:Let_e(“x”,Int_e 30,

Let_e(“y”,Let_e(“z”,Int_e 3,

Op_e(Var_e “z”, Times, Int_e 4)),

Op_e(Var_e “y”, Plus, Var_e “y”)

let

x 30 let

y let +

z 3 *y y

z 4

Page 7: An OCaml definion of OCaml evaluaon, or,

Bindingoccurrencesversusappliedoccurrences 7

type exp = | Int_e of int | Op_e of exp * op * exp | Var_e of variable | Let_e of variable * exp * exp

Thisisabindingoccurrenceofavariable

Thisisauseofavariable

Page 8: An OCaml definion of OCaml evaluaon, or,

let is_value (e:exp) : bool = match e with | Int_e _ -> true | ( Op_e _ | Let_e _ | Var_e _ ) -> false

eval_op : value -> op -> value -> exp

(* substitute v x e:replace free occurrences of x with v in e *)

substitute : value -> variable -> exp -> exp

SomeUsefulAuxiliaryFunc'ons 8

nested“|”paWern(can’tusevariables)

Page 9: An OCaml definion of OCaml evaluaon, or,

ASimpleEvaluator 9

is_value : exp -> booleval_op : value -> op -> value -> valuesubstitute : value -> variable -> exp -> exp

let rec eval (e:exp) : exp = match e with | Int_e i -> | Op_e(e1,op,e2) ->

| Let_e(x,e1,e2) ->

Page 10: An OCaml definion of OCaml evaluaon, or,

ASimpleEvaluator 10

is_value : exp -> booleval_op : value -> op -> value -> valuesubstitute : value -> variable -> exp -> exp

let rec eval (e:exp) : exp = match e with | Int_e i -> Int_e i | Op_e(e1,op,e2) ->

| Let_e(x,e1,e2) ->

Page 11: An OCaml definion of OCaml evaluaon, or,

is_value : exp -> booleval_op : value -> op -> value -> valuesubstitute : value -> variable -> exp -> exp

let rec eval (e:exp) : exp = match e with | Int_e i -> Int_e i | Op_e(e1,op,e2) ->

let v1 = eval e1 in let v2 = eval e2 in

eval_op v1 op v2 | Let_e(x,e1,e2) ->

ASimpleEvaluator 11

Page 12: An OCaml definion of OCaml evaluaon, or,

ASimpleEvaluator 12

is_value : exp -> booleval_op : value -> op -> value -> valuesubstitute : value -> variable -> exp -> exp

let rec eval (e:exp) : exp = match e with | Int_e i -> Int_e i | Op_e(e1,op,e2) ->

let v1 = eval e1 in let v2 = eval e2 in

eval_op v1 op v2 | Let_e(x,e1,e2) -> let v1 = eval e1 in let e2’ = substitute v1 x e2 in

eval e2’

Page 13: An OCaml definion of OCaml evaluaon, or,

ShorterbutDangerous 13

Why?

is_value : exp -> booleval_op : value -> op -> value -> valuesubstitute : value -> variable -> exp -> exp

let rec eval (e:exp) : exp = match e with | Int_e i -> Int_e i | Op_e(e1,op,e2) ->

eval_op (eval e1) op (eval e2) | Let_e(x,e1,e2) ->

eval (substitute (eval e1) x e2)

Page 14: An OCaml definion of OCaml evaluaon, or,

is_value : exp -> booleval_op : value -> op -> value -> valuesubstitute : value -> variable -> exp -> exp

let rec eval (e:exp) : exp = match e with | Int_e i -> Int_e i | Op_e(e1,op,e2) ->

eval_op (eval e1) op (eval e2) | Let_e(x,e1,e2) ->

eval (substitute (eval e1) x e2)

SimplerbutDangerous

Whichgetsevaluatedfirst?DoesOCamluselei-to-rightevalorderorright-to-lei?AlwaysuseOCamlletifyouwanttospecifyevalua'onorder.

14

Page 15: An OCaml definion of OCaml evaluaon, or,

is_value : exp -> booleval_op : value -> op -> value -> valuesubstitute : value -> variable -> exp -> exp

let rec eval (e:exp) : exp = match e with | Int_e i -> Int_e i | Op_e(e1,op,e2) ->

eval_op (eval e1) op (eval e2) | Let_e(x,e1,e2) ->

eval (substitute (eval e1) x e2)

SimplerbutDangerous

Sincethelanguageweareinterpre'ngispure(noeffects),itwon’tmaWerwhichexpressiongetsevaluatedfirst.We’llproducethesameanswerineithercase.

15

Page 16: An OCaml definion of OCaml evaluaon, or,

Limita'onsofmetacircularinterpreters 16

is_value : exp -> booleval_op : value -> op -> value -> valuesubstitute : value -> variable -> exp -> exp

let rec eval (e:exp) : exp = match e with | Int_e i -> Int_e i | Op_e(e1,op,e2) ->

let v1 = eval e1 in let v2 = eval e2 in

eval_op v1 op v2 | Let_e(x,e1,e2) -> let v1 = eval e1 in let e2’ = substitute v1 x e2 in

eval e2’

Whichgetsevaluatedfirst,(evale1)or(evale2)?Seemsobvious,right?

Butthat’sbecauseweassumeOCamlhascall-by-valueevalua'on!Ifitwerecall-by-name,thenthisorderingofletswouldnotguaranteeorder

ofevalua'on.

Moral:usingalanguagetodefineitsownseman+cscanhavelimita6ons.

Page 17: An OCaml definion of OCaml evaluaon, or,

Backtotheevalfunc'on… 17

let eval_op v1 op v2 = …let substitute v x e = …

let rec eval (e:exp) : exp = match e with | Int_e i -> Int_e i | Op_e(e1,op,e2) -> eval_op (eval e1) op (eval e2) | Let_e(x,e1,e2) -> eval (substitute (eval e1) x e2)

(sameastheoneacoupleofslidesago)

Page 18: An OCaml definion of OCaml evaluaon, or,

Oops!WeMissedaCase: 18

let eval_op v1 op v2 = …let substitute v x e = …

let rec eval (e:exp) : exp = match e with | Int_e i -> Int_e i | Op_e(e1,op,e2) -> eval_op (eval e1) op (eval e2) | Let_e(x,e1,e2) -> eval (substitute (eval e1) x e2) | Var_e x -> ???

Weshouldneverencounteravariable–theyshouldhavebeensubs'tutedwithavalue!(Thisisatype-error.)Wecouldleaveoutthecaseforvariablesifwetypecheckbeforeevalua+ng.(whichweshoulddefinitelydo!)ButthatwillcreateamessofOcamlwarnings–badstyle.(Badfordebugging.)

Page 19: An OCaml definion of OCaml evaluaon, or,

WeCouldUseOp'ons: 19

let eval_op v1 op v2 = …let substitute v x e = …

let rec eval (e:exp) : exp option = match e with | Int_e i -> Some(Int_e i) | Op_e(e1,op,e2) -> eval_op (eval e1) op (eval e2) | Let_e(x,e1,e2) -> eval (substitute (eval e1) x e2) | Var_e x -> None

Butthisisn’tquiteright–weneedtomatchontherecursivecallstoevaltomakesurewegetSomevalue!

Page 20: An OCaml definion of OCaml evaluaon, or,

Excep'ons 20

exception UnboundVariable of variable

let rec eval (e:exp) : exp = match e with | Int_e i -> Int_e i | Op_e(e1,op,e2) -> eval_op (eval e1) op (eval e2) | Let_e(x,e1,e2) -> eval (substitute (eval e1) x e2) | Var_e x -> raise (UnboundVariable x)

Instead,wecanthrowanexcep'on.

Page 21: An OCaml definion of OCaml evaluaon, or,

Excep'ons 21

Notethatanexcep'ondeclara'onisalotlikeadatatypedeclara'on.Really,weareextendingonebigdatatype(exn)withanewconstructor(UnboundVariable).

exception UnboundVariable of variable

let rec eval (e:exp) : exp = match e with | Int_e i -> Int_e i | Op_e(e1,op,e2) -> eval_op (eval e1) op (eval e2) | Let_e(x,e1,e2) -> eval (substitute (eval e1) x e2) | Var_e x -> raise (UnboundVariable x)

Lateron,we’llseehowtocatchanexcep'on.

Page 22: An OCaml definion of OCaml evaluaon, or,

Excep'onorop'on?Inapreviouslecture,Iexplainedwhytouseanop'ontype(oraSuccess/Failuredatatype)insteadofraisinganexcep'on.

No!Idonotcontradictmyself!•  Theotherexamplewasforerrorsthatwilloccur

(becausetheinputmightbeillformaWed).•  Thisexampleisforerrorsthatcannotoccur

(unlesstheprogramitselfhasabug).

22

Page 23: An OCaml definion of OCaml evaluaon, or,

AUXILIARYFUNCTIONS

23

Page 24: An OCaml definion of OCaml evaluaon, or,

Evalua'ngthePrimi'veOpera'ons 24

let eval_op (v1:exp) (op:operand) (v2:exp) : exp = match v1, op, v2 with | Int_e i, Plus, Int_e j -> Int_e (i+j) | Int_e i, Minus, Int_e j -> Int_e (i-j) | Int_e i, Times, Int_e j -> Int_e (i*j) | _ ,(Plus | Minus | Times), _ ->

if is_value v1 && is_value v2 then raise TypeError else raise NotValue

let rec eval (e:exp) : exp = match e with | Int_e i -> Int_e i | Op_e(e1,op,e2) -> eval_op (eval e1) op (eval e2) | Let_e(x,e1,e2) -> eval (substitute (eval e1) x e2) | Var_e x -> raise (UnboundVariable x) ;;

Page 25: An OCaml definion of OCaml evaluaon, or,

Subs'tu'on

25

let substitute (v:exp) (x:variable) (e:exp) : exp =

...

;;

Wanttoreplacex(andonlyx)withv.

Page 26: An OCaml definion of OCaml evaluaon, or,

Subs'tu'on

26

let substitute (v:exp) (x:variable) (e:exp) : exp = let rec subst (e:exp) : exp = match e with | Int_e _ -> | Op_e(e1,op,e2) -> | Var_e y -> ... use x ... | Let_e (y,e1,e2) -> ... use x ...

in subst e ;;

Page 27: An OCaml definion of OCaml evaluaon, or,

Subs'tu'on

27

let substitute (v:exp) (x:variable) (e:exp) : exp = let rec subst (e:exp) : exp = match e with | Int_e _ -> e | Op_e(e1,op,e2) -> | Var_e y -> | Let_e (y,e1,e2) ->

in subst e ;;

Page 28: An OCaml definion of OCaml evaluaon, or,

Subs'tu'on

28

let substitute (v:exp) (x:variable) (e:exp) : exp = let rec subst (e:exp) : exp = match e with | Int_e _ -> e | Op_e(e1,op,e2) -> Op_e(subst e1,op,subst e2) | Var_e y -> | Let_e (y,e1,e2) ->

in subst e ;;

Page 29: An OCaml definion of OCaml evaluaon, or,

Subs'tu'on

29

let substitute (v:exp) (x:variable) (e:exp) : exp = let rec subst (e:exp) : exp = match e with | Int_e _ -> e | Op_e(e1,op,e2) -> Op_e(subst e1,op,subst e2) | Var_e y -> if x = y then v else e | Let_e (y,e1,e2) ->

in subst e ;;

Page 30: An OCaml definion of OCaml evaluaon, or,

Subs'tu'on

30

let substitute (v:exp) (x:variable) (e:exp) : exp = let rec subst (e:exp) : exp = match e with | Int_e _ -> e | Op_e(e1,op,e2) -> Op_e(subst e1,op,subst e2) | Var_e y -> if x = y then v else e | Let_e (y,e1,e2) -> Let_e (y, subst e1, subst e2) in subst e ;;

WRONG!

Page 31: An OCaml definion of OCaml evaluaon, or,

Subs'tu'on

31

let substitute (v:exp) (x:variable) (e:exp) : exp = let rec subst (e:exp) : exp = match e with | Int_e _ -> e | Op_e(e1,op,e2) -> Op_e(subst e1,op,subst e2) | Var_e y -> if x = y then v else e | Let_e (y,e1,e2) -> Let_e (y, if x = y then e1 else subst e1, if x = y then e2 else subst e2) in subst e ;;

wrong

Page 32: An OCaml definion of OCaml evaluaon, or,

Subs'tu'on

32

let substitute (v:exp) (x:variable) (e:exp) : exp = let rec subst (e:exp) : exp = match e with | Int_e _ -> e | Op_e(e1,op,e2) -> Op_e(subst e1,op,subst e2) | Var_e y -> if x = y then v else e | Let_e (y,e1,e2) -> Let_e (y, subst e1, if x = y then e2 else subst e2) in subst e ;;

evalua'on/subsitu'onmustimplementourvariablescopingrulescorrectly

Page 33: An OCaml definion of OCaml evaluaon, or,

Subs'tu'on

33

let substitute (v:exp) (x:variable) (e:exp) : exp = let rec subst (e:exp) : exp = match e with | Int_e _ -> e | Op_e(e1,op,e2) -> Op_e(subst e1,op,subst e2) | Var_e y -> if x = y then v else e | Let_e (y,e1,e2) -> Let_e (y, subst e1, if x = y then e2 else subst e2) in subst e ;; Ifxandyare

thesamevariable,thenyshadowsx.

Page 34: An OCaml definion of OCaml evaluaon, or,

SCALINGUPTHELANGUAGE(MOREFEATURES,MOREFUN)

34

Page 35: An OCaml definion of OCaml evaluaon, or,

ScalinguptheLanguage 35

type exp = Int_e of int | Op_e of exp * op * exp | Var_e of variable | Let_e of variable * exp * exp | Fun_e of variable * exp | FunCall_e of exp * exp ;;

Page 36: An OCaml definion of OCaml evaluaon, or,

ScalinguptheLanguage 36

type exp = Int_e of int | Op_e of exp * op * exp | Var_e of variable | Let_e of variable * exp * exp | Fun_e of variable * exp | FunCall_e of exp * exp ;;

OCaml’sfunx->e

isrepresentedasFun_e(x,e)

Page 37: An OCaml definion of OCaml evaluaon, or,

ScalinguptheLanguage 37

type exp = Int_e of int | Op_e of exp * op * exp | Var_e of variable | Let_e of variable * exp * exp | Fun_e of variable * exp | FunCall_e of exp * exp ;;

Afunc'oncallfact3

isimplementedasFunCall_e(Var_e“fact”,Int_e3)

Page 38: An OCaml definion of OCaml evaluaon, or,

ScalinguptheLanguage 38

type exp = Int_e of int | Op_e of exp * op * exp | Var_e of variable | Let_e of variable * exp * exp | Fun_e of variable * exp | FunCall_e of exp * exp;;

let is_value (e:exp) : bool = match e with | Int_e _ -> true | Fun_e (_,_) -> true | ( Op_e (_,_,_) | Let_e (_,_,_) | Var_e _ | FunCall_e (_,_) ) -> false ;;

Func'onsarevalues!

Easyexamques'on:WhatvaluedoestheOCamlinterpreterproducewhenyouenter(funx->3)intotheprompt?Answer:thevalueproducedis(funx->3)

Page 39: An OCaml definion of OCaml evaluaon, or,

ScalinguptheLanguage: 39

type exp = Int_e of int | Op_e of exp * op * exp | Var_e of variable | Let_e of variable * exp * exp | Fun_e of variable * exp | FunCall_e of exp * exp;;

let is_value (e:exp) : bool = match e with | Int_e _ -> true | Fun_e (_,_) -> true | ( Op_e (_,_,_) | Let_e (_,_,_) | Var_e _ | FunCall_e (_,_) ) -> false ;;

Func'oncallsarenotvalues.

Page 40: An OCaml definion of OCaml evaluaon, or,

ScalinguptheLanguage: 40

let rec eval (e:exp) : exp = match e with | Int_e i -> Int_e i | Op_e(e1,op,e2) -> eval_op (eval e1) op (eval e2) | Let_e(x,e1,e2) -> eval (substitute (eval e1) x e2) | Var_e x -> raise (UnboundVariable x) | Fun_e (x,e) -> Fun_e (x,e) | FunCall_e (e1,e2) -> (match eval e1, eval e2 with | Fun_e (x,e), v2 -> eval (substitute v2 x e) | _ -> raise TypeError)

Page 41: An OCaml definion of OCaml evaluaon, or,

ScalinguptheLanguage: 41

let rec eval (e:exp) : exp = match e with | Int_e i -> Int_e i | Op_e(e1,op,e2) -> eval_op (eval e1) op (eval e2) | Let_e(x,e1,e2) -> eval (substitute (eval e1) x e2) | Var_e x -> raise (UnboundVariable x) | Fun_e (x,e) -> Fun_e (x,e) | FunCall_e (e1,e2) -> (match eval e1, eval e2 with | Fun_e (x,e), v2 -> eval (substitute v2 x e) | _ -> raise TypeError)

values(includingfunc'ons)always

evaluatetothemselves.

Page 42: An OCaml definion of OCaml evaluaon, or,

ScalinguptheLanguage: 42

let rec eval (e:exp) : exp = match e with | Int_e i -> Int_e i | Op_e(e1,op,e2) -> eval_op (eval e1) op (eval e2) | Let_e(x,e1,e2) -> eval (substitute (eval e1) x e2) | Var_e x -> raise (UnboundVariable x) | Fun_e (x,e) -> Fun_e (x,e) | FunCall_e (e1,e2) -> (match eval e1, eval e2 with | Fun_e (x,e), v2 -> eval (substitute v2 x e) | _ -> raise TypeError)

Toevaluateafunc'oncall,wefirstevaluate

bothe1ande2tovalues.

Page 43: An OCaml definion of OCaml evaluaon, or,

ScalinguptheLanguage 43

let rec eval (e:exp) : exp = match e with | Int_e i -> Int_e i | Op_e(e1,op,e2) -> eval_op (eval e1) op (eval e2) | Let_e(x,e1,e2) -> eval (substitute (eval e1) x e2) | Var_e x -> raise (UnboundVariable x) | Fun_e (x,e) -> Fun_e (x,e) | FunCall_e (e1,e2) -> (match eval e1, eval e2 with | Fun_e (x,e), v2 -> eval (substitute v2 x e) | _ -> raise TypeError)

e1hadbeWerevaluatetoafunc'onvalue,elsewehaveatypeerror.

Page 44: An OCaml definion of OCaml evaluaon, or,

ScalinguptheLanguage 44

let rec eval (e:exp) : exp = match e with | Int_e i -> Int_e i | Op_e(e1,op,e2) -> eval_op (eval e1) op (eval e2) | Let_e(x,e1,e2) -> eval (substitute (eval e1) x e2) | Var_e x -> raise (UnboundVariable x) | Fun_e (x,e) -> Fun_e (x,e) | FunCall_e (e1,e2) -> (match eval e1, eval e2 with | Fun_e (x,e), v2 -> eval (substitute v2 x e) | _ -> raise TypeError)

Thenwesubs'tutee2’svalue(v2)forxineandevaluatetheresul'ng

expression.

Page 45: An OCaml definion of OCaml evaluaon, or,

SimplifyingaliWle 45

let rec eval (e:exp) : exp = match e with | Int_e i -> Int_e i | Op_e(e1,op,e2) -> eval_op (eval e1) op (eval e2) | Let_e(x,e1,e2) -> eval (substitute (eval e1) x e2) | Var_e x -> raise (UnboundVariable x) | Fun_e (x,e) -> Fun_e (x,e) | FunCall_e (e1,e2) -> (match eval e1 | Fun_e (x,e) -> eval (substitute (eval e2) x e) | _ -> raise TypeError)

Wedon’treallyneedtopaWern-matchone2.

Justevaluatehere

Page 46: An OCaml definion of OCaml evaluaon, or,

SimplifyingaliWle 46

let rec eval (e:exp) : exp = match e with | Int_e i -> Int_e i | Op_e(e1,op,e2) -> eval_op (eval e1) op (eval e2) | Let_e(x,e1,e2) -> eval (substitute (eval e1) x e2) | Var_e x -> raise (UnboundVariable x) | Fun_e (x,e) -> Fun_e (x,e) | FunCall_e (ef,e1) -> (match eval ef with | Fun_e (x,e2) -> eval (substitute (eval e1) x e2) | _ -> raise TypeError)

Thislookslikethecaseforlet!

Page 47: An OCaml definion of OCaml evaluaon, or,

LetandLambda 47

let x = 1 in x+41 -->1+41-->42

Ingeneral:

(fun x -> x+41) 1-->1+41-->42

(fun x -> e2) e1 == let x = e1 in e2

Page 48: An OCaml definion of OCaml evaluaon, or,

Sowecouldwrite: 48

let rec eval (e:exp) : exp = match e with | Int_e i -> Int_e i | Op_e(e1,op,e2) -> eval_op (eval e1) op (eval e2) | Let_e(x,e1,e2) -> eval (FunCall (Fun_e (x,e2), e1)) | Var_e x -> raise (UnboundVariable x) | Fun_e (x,e) -> Fun_e (x,e) | FunCall_e (ef,e2) -> (match eval ef with | Fun_e (x,e1) -> eval (substitute (eval e1) x e2) | _ -> raise TypeError)

Inprogramming-languagesspeak:“Letissyntac6csugarforafunc'oncall”Syntac'csugar:Anewfeaturedefinedbyasimple,localtransforma'on.

Page 49: An OCaml definion of OCaml evaluaon, or,

Recursivedefini'ons 49

type exp = Int_e of int | Op_e of exp * op * exp | Var_e of variable | Let_e of variable * exp * exp | | Fun_e of variable * exp | FunCall_e of exp * exp | Rec_e of variable * variable * exp ;;

let rec f x = f (x+1) in f 3

Let_e (“g, Rec_e (“f”, “x”, FunCall_e (Var_e “f”, Op_e (Var_e “x”, Plus, Int_e 1)) ), FunCall (Var_e “g”, Int_e 3))

(rewrite)

(alpha-convert)let f = (rec f x -> f (x+1)) inf 3

let g = (rec f x -> f (x+1)) ing 3

(implement)

Page 50: An OCaml definion of OCaml evaluaon, or,

Recursivedefini'ons 50

type exp = Int_e of int | Op_e of exp * op * exp | Var_e of variable | Let_e of variable * exp * exp | | Fun_e of variable * exp | FunCall_e of exp * exp | Rec_e of variable * variable * exp ;;

let is_value (e:exp) : bool = match e with | Int_e _ -> true | Fun_e (_,_) -> true | Rec_e of (_,_,_) -> true | (Op_e (_,_,_) | Let_e (_,_,_) | Var_e _ | FunCall_e (_,_) ) -> false ;;

Page 51: An OCaml definion of OCaml evaluaon, or,

Recursivedefini'ons 51

type exp = Int_e of int | Op_e of exp * op * exp | Var_e of variable | Let_e of variable * exp * exp | | Fun_e of variable * exp | FunCall_e of exp * exp | Rec_e of variable * variable * exp ;;

let is_value (e:exp) : bool = match e with | Int_e _ -> true | Fun_e (_,_) -> true | Rec_e of (_,_,_) -> true | (Op_e (_,_,_) | Let_e (_,_,_) | Var_e _ | FunCall_e (_,_) ) -> false ;; Fun_e(x,body)==Rec_e("unused",x,body)

AbeWerIRwouldjustdeleteFun_e–avoid

unnecessaryredundancy

Page 52: An OCaml definion of OCaml evaluaon, or,

Interlude:Nota'onforSubs'tu'on

“Subs'tutevaluevforvariablexinexpressione:” e[v/x]

(x+y)[7/y] is (x+7)(letx=30inlety=40inx+y)[7/y]is(letx=30inlety=40inx+y)(lety=yinlety=yiny+y)[7/y] is (lety=7inlety=yiny+y)

examplesofsubs'tu'on:

52

Page 53: An OCaml definion of OCaml evaluaon, or,

Evalua'ngRecursiveFunc'ons 53

Basicevalua'onruleforrecursivefunc'ons:

(recfx=body)arg-->body[arg/x][recfx=body/f]

en'refunc'onsubs'tutedforfunc'onname

argumentvaluesubs'tutedforparameter

Page 54: An OCaml definion of OCaml evaluaon, or,

Evalua'ngRecursiveFunc'ons 54

let g = rec f x -> if x <= 0 then x else x + f (x-1) in g 3

Startoutwithaletboundtoarecursivefunc'on:

TheSubs'tu'on:g 3 [rec f x -> if x <= 0 then x else x + f (x-1) / g]

TheResult: (rec f x -> if x <= 0 then x else x + f (x-1)) 3

Page 55: An OCaml definion of OCaml evaluaon, or,

Evalua'ngRecursiveFunc'ons

55

RecursiveFunc'onCall:

TheSubs'tu'on:

TheResult:

(if x <= 0 then x else x + f (x-1)) [ rec f x -> if x <= 0 then x else x + f (x-1) / f ] [ 3 / x ]

(rec f x -> if x <= 0 then x else x + f (x-1)) 3

(if 3 <= 0 then 3 else 3 + (rec f x -> if x <= 0 then x else x + f (x-1)) (3-1))

Subs'tuteen'refunc'onforfunc'onname

Subs'tuteargumentforparameter

Page 56: An OCaml definion of OCaml evaluaon, or,

Evalua'ngRecursiveFunc'ons 56

let rec eval (e:exp) : exp = match e with | Int_e i -> Int_e i | Op_e(e1,op,e2) -> eval_op (eval e1) op (eval e2) | Let_e(x,e1,e2) -> eval (substitute (eval e1) x e2) | Var_e x -> raise (UnboundVariable x) | Fun_e (x,e) -> Fun_e (x,e) | FunCall_e (e1,e2) -> (match eval e1 with | Fun_e (x,e) ->

let v = eval e2 in substitute e x v

| (Rec_e (f,x,e)) as f_val -> let v = eval e2 in substitute f_val f (substitute v x e)

| _ -> raise TypeError)

pa=ernasxmatchthepaWernandbindsxtovalue

Page 57: An OCaml definion of OCaml evaluaon, or,

MoreEvalua'on 57

(rec fact n = if n <= 1 then 1 else n * fact(n-1)) 3-->if 3 < 1 then 1 else 3 * (rec fact n = if ... then ... else ...) (3-1)-->3 * (rec fact n = if … ) (3-1)-->3 * (rec fact n = if … ) 2-->3 * (if 2 <= 1 then 1 else 2 * (rec fact n = ...)(2-1))-->3 * (2 * (rec fact n = ...)(2-1))-->3 * (2 * (rec fact n = ...)(1))-->3 * 2 * (if 1 <= 1 then 1 else 1 * (rec fact ...)(1-1))-->3 * 2 * 1

Page 58: An OCaml definion of OCaml evaluaon, or,

AMATHEMATICALDEFINITION*OFOCAMLEVALUATION

*it’sapar'aldefini'onandthisisabigtopic;formore,seeCOS510

58

Page 59: An OCaml definion of OCaml evaluaon, or,

FromCodetoAbstractSpecifica'on

OCamlcodecangivealanguageseman'cs–  advantage:itcanbeexecuted,sowecantryitout–  advantage:itisamazinglyconcise

•  especiallycomparedtowhatyouwouldhavewriWeninJava–  disadvantage:itisaliWleuglytooperateoverconcreteMLdatatypeslike“Op_e(e1,Plus,e2)”asopposedto“e1+e2”

–  disadvantage:definingalanguageinitselfisalogicalfallacy

59

Page 60: An OCaml definion of OCaml evaluaon, or,

FromCodetoAbstractSpecifica'on

PLresearchershavedevelopedtheirownstandardnota'onforwri'ngdownhowprogramsexecute

–  ithasamathema'cal“feel”thatmakesPLresearchersfeelspecialandgivesusgoosebumpsinside

–  itoperatesoverabstractexpressionsyntaxlike“e1+e2”–  itisusefultoknowthisnota'onifyouwanttoreadspecifica'onsofprogramminglanguageseman'cs•  e.g.:StandardML(ofwhichOCamlisadescendent)hasaformaldefini'ongiveninthisnota'on(andC,andJava;butnotOCaml…)

•  e.g.:mostpapersintheconferencePOPL(ACMPrinciplesofProg.Lang.)

60

Page 61: An OCaml definion of OCaml evaluaon, or,

Goal

Ourgoalistoexplainhowanexpressioneevaluatestoavaluev.Inotherwords,wewanttodefineamathema'calrela6onbetweenpairsofexpressionsandvalues.

61

Page 62: An OCaml definion of OCaml evaluaon, or,

FormalInferenceRulesWedefinethe“evaluatesto”rela'onusingasetof(induc've)rulesthatallowustoprovethatapar'cular(expression,value)pairispartoftherela'on.Arulelookslikethis:

Youreadarulelikethis:

–  “ifpremise1canbeprovenandpremise2canbeprovenand...andpremisencanbeproventhenconclusioncanbeproven”

Someruleshavenopremises–  thismeanstheirconclusionsarealwaystrue–  wecallsuchrules“axioms”or“basecases”

premise1premise2...premise3conclusion

62

Page 63: An OCaml definion of OCaml evaluaon, or,

Anexamplerule

e1-->v1e2-->v2eval_op(v1,op,v2)==v’e1ope2-->v’

let rec eval (e:exp) : exp = match e with | Op_e(e1,op,e2) -> let v1 = eval e1 in let v2 = eval e2 in

let v’ = eval_op v1 op v2 in v’

“Ife1evaluatestov1ande2evaluatestov2andeval_op(v1,op,v2)isequaltov’thene1ope2evaluatestov’

Asarule:

InEnglish:

Incode:

63

Page 64: An OCaml definion of OCaml evaluaon, or,

Anexamplerule

iϵΖi-->i

let rec eval (e:exp) : exp = match e with | Int_e i -> Int_e i ...

“Iftheexpressionisanintegervalue,itevaluatestoitself.”

Asarule:

InEnglish:

Incode:

assertsiisaninteger

64

Page 65: An OCaml definion of OCaml evaluaon, or,

Anexampleruleconcerningevalua'on

e1-->v1e2[v1/x]-->v2letx=e1ine2-->v2

let rec eval (e:exp) : exp = match e with | Let_e(x,e1,e2) -> let v1 = eval e1 in

eval (substitute v1 x e2) ...

“Ife1evaluatestov1(whichisavalue)ande2withv1subs'tutedforxevaluatestov2thenletx=e1ine2evaluatestov2.”

Asarule:

InEnglish:

Incode:

65

Page 66: An OCaml definion of OCaml evaluaon, or,

Anexampleruleconcerningevalua'on

λx.e-->λx.e

let rec eval (e:exp) : exp = match e with ... | Fun_e (x,e) -> Fun_e (x,e) ...

“Afunc'onvalueevaluatestoitself.”

Asarule:

InEnglish:

Incode:

typical“lambda”nota'onforafunc'onwithargumentx,bodye

66

Page 67: An OCaml definion of OCaml evaluaon, or,

Anexampleruleconcerningevalua'on

e1-->λx.ee2-->v2e[v2/x]-->ve1e2-->v

let rec eval (e:exp) : exp = match e with ..| FunCall_e (e1,e2) ->

(match eval e1 with | Fun_e (x,e) -> eval (substitute (eval e2) x e) | ...)

...

“ife1evaluatestoafunc'onwithargumentxandbodyeande2evaluatestoavaluev2andewithv2subs'tutedforxevaluatestovthene1appliedtoe2evaluatestov”

Asarule:

InEnglish:

Incode:

67

Page 68: An OCaml definion of OCaml evaluaon, or,

Anexampleruleconcerningevalua'on

e1-->recfx=ee2-->ve[recfx=e/f][v/x]-->v2e1e2-->v2

let rec eval (e:exp) : exp = match e with ... | (Rec_e (f,x,e)) as f_val ->

let v = eval e2 in substitute f_val (substitute v x e) g

“uggh”

Asarule:

InEnglish:

Incode:

68

Page 69: An OCaml definion of OCaml evaluaon, or,

Comparison:Codevs.Rules

Almostisomorphic:–  oneruleperpaWern-matchingclause–  recursivecalltoevalwheneverthereisa-->premiseinarule–  what’sthemaindifference?

let rec eval (e:exp) : exp = match e with | Int_e i -> Int_e i

| Op_e(e1,op,e2) -> eval_op (eval e1) op (eval e2) | Let_e(x,e1,e2) -> eval (substitute (eval e1) x e2) | Var_e x -> raise (UnboundVariable x)

| Fun_e (x,e) -> Fun_e (x,e) | FunCall_e (e1,e2) -> (match eval e1 | Fun_e (x,e) -> eval (Let_e (x,e2,e))

| _ -> raise TypeError) | LetRec_e (x,e1,e2) ->

•  (Rec_e (f,x,e)) as f_val ->

let v = eval e2 in substitute f_val f (substitute v x e) e1-->recfx=ee2-->v2e[recfx=e/f][v2/x]-->v3

e1e2-->v3

e1-->v1e2-->v2eval_op(v1,op,v2)==ve1ope2-->v

iϵΖi-->i

e1-->v1e2[v1/x]-->v2letx=e1ine2-->v2

λx.e-->λx.e

e1-->λx.ee2-->v2e[v2/x]-->ve1e2-->v

completeevalcode: completesetofrules:

69

Page 70: An OCaml definion of OCaml evaluaon, or,

Comparison:Codevs.Rules

•  There’snoformalruleforhandlingfreevariables•  Noruleforevalua'ngfunc'oncallswhenanon-func'oninthecallerposi'on•  Ingeneral,norulewhenfurtherevalua6onisimpossible

–  therulesexpressthelegalevalua6onsandsaynothingaboutwhattodoinerrorsitua'ons–  thecodehandlestheerrorsitua'onsbyraisingexcep'ons–  typetheoristsprovethatwell-typedprogramsdon’trunintoundefinedcases

e1-->v1e2-->v2eval_op(v1,op,v2)==ve1ope2-->v

iϵΖi-->i

e1-->v1e2[v1/x]-->v2letx=e1ine2-->v2

λx.e-->λx.e

e1-->λx.ee2-->v2e[v2/x]-->ve1e2-->v

completeevalcode: completesetofrules:

e1-->recfx=ee2-->v2e[recfx=e/f][v2/x]-->v3e1e2-->v3

let rec eval (e:exp) : exp = match e with | Int_e i -> Int_e i

| Op_e(e1,op,e2) -> eval_op (eval e1) op (eval e2) | Let_e(x,e1,e2) -> eval (substitute (eval e1) x e2) | Var_e x -> raise (UnboundVariable x)

| Fun_e (x,e) -> Fun_e (x,e) | FunCall_e (e1,e2) -> (match eval e1 | Fun_e (x,e) -> eval (Let_e (x,e2,e))

| _ -> raise TypeError) | LetRec_e (x,e1,e2) ->

•  (Rec_e (f,x,e)) as f_val ->

let v = eval e2 in substitute f_val f (substitute v x e)

70

Page 71: An OCaml definion of OCaml evaluaon, or,

Summary 71

•  WecanreasonaboutOCamlprogramsusingasubs6tu6onmodel.–  integers,bools,strings,chars,andfunc6onsarevalues–  valuerule:valuesevaluatetothemselves–  letrule:“letx=e1ine2”:subs'tutee1’svalueforxintoe2–  funcallrule:“(funx->e2)e1”:subs'tutee1’svalueforxintoe2–  reccallrule:“(recx=e1)e2”:likefuncallrule,butalsosubs'tute

recursivefunc'onfornameoffunc'on•  Tounwind:subs'tute(recx=e1)forxine1

•  Wecanmaketheevalua'onmodelprecisebybuildinganinterpreterandusingthatinterpreterasaspecifica'onofthelanguageseman'cs.

•  Wecanalsospecifytheevalua'onmodelusingasetofinferencerules–  moreonthisinCOS510

Page 72: An OCaml definion of OCaml evaluaon, or,

SomeFinalWords 72

•  Thesubs'tu'onmodelisonlyamodel.–  itdoesnotaccuratelymodelallofOCaml’sfeatures

•  I/O,excep'ons,muta'on,concurrency,…•  wecanbuildmodelsofthesethings,buttheyaren’tassimple.•  evensubs'tu'onistrickytoformalize!

•  It’susefulforreasoningabouthigher-orderfunc'ons,correctnessofalgorithms,andop'miza'ons.–  wecanuseittoformallyprovethat,forinstance:

•  mapf(mapgxs)==map(compfg)xs•  proof:byinduc'ononthelengthofthelistxs,usingthedefini'onsofthesubs'tu'onmodel.

–  weoienmodelcomplicatedsystems(e.g.,protocols)usingasmallfunc'onallanguageandsubs'tu'on-basedevalua'on.

•  Itisnotusefulforreasoningaboutexecu'on'meorspace–  morecomplexmodelsneededthere

Page 73: An OCaml definion of OCaml evaluaon, or,

SomeFinalWords 73

•  Thesubs'tu'onmodelisonlyamodel.–  itdoesnotaccuratelymodelallofOCaml’sfeatures

•  I/O,excep'ons,muta'on,concurrency,…•  wecanbuildmodelsofthesethings,buttheyaren’tassimple.•  evensubs'tu'onwastrickytoformalize!

•  It’susefulforreasoningabouthigher-orderfunc'ons,correctnessofalgorithms,andop'miza'ons.–  wecanuseittoformallyprovethat,forinstance:

•  mapf(mapgxs)==map(compfg)xs•  proof:byinduc'ononthelengthofthelistxs,usingthedefini'onsofthesubs'tu'onmodel.

–  weoienmodelcomplicatedsystems(e.g.,protocols)usingasmallfunc'onallanguageandsubs'tu'on-basedevalua'on.

•  Itisnotusefulforreasoningaboutexecu'on'meorspace–  morecomplexmodelsneededthere

AlonzoChurch,1903-1995

PrincetonProfessor,1929-1967

Youcansaythatagain!Igotitwrongthefirst'meItried,in1932.Fixedthebugby1934,

though.

Page 74: An OCaml definion of OCaml evaluaon, or,

Church'smistake 74

funxs->map(+)xs

funys->letmapxs=0::xsinf(mapys)

subs'tute:

forfin:

andifyoudon'twatchout,youwillget:

funys->letmapxs=0::xsin(funxs->map(+)xs)(mapys)

Page 75: An OCaml definion of OCaml evaluaon, or,

Church'smistake 75

funxs->map(+)xs

funys->letmapxs=0::xsinf(mapys)

subs'tute:

forfin:

andifyoudon'twatchout,youwillget:

funys->letmapxs=0::xsin(funxs->map(+)xs)(mapys)

theproblemwasthatthevalueyousubs'tutedin

hadafreevariable(map)initthatwascaptured.

Page 76: An OCaml definion of OCaml evaluaon, or,

Church'smistake 76

funxs->map(+)xs

funys->letmapxs=0::xsinf(mapys)

subs'tute:

forfin:

todoitright,youneedtorenamesomevariables:

funys->letzxs=0::xsin(funxs->map(+)xs)(zys)

Page 77: An OCaml definion of OCaml evaluaon, or,

NOWWEAREREALLYDONE!

77