350 likes | 426 Views
Fundamentals of. Staged Computation. Tim Sheard Oregon Graduate Institute. Lecture 8: Operational Semantics of MetaML. CSE 510 Section FSC Winter 2005. Assignments. Reading Assignment A Methodology for Generating Verified Combinatorial Circuits . By Kiseyov, Swadi, and Taha.
E N D
Fundamentals of Staged Computation Tim Sheard Oregon Graduate Institute Lecture 8: Operational Semantics of MetaML CSE 510 Section FSC Winter 2005
Assignments • Reading Assignment • A Methodology for Generating Verified Combinatorial Circuits. • By Kiseyov, Swadi, and Taha. • Available on the readings page of the course web-site • Homework # 5 • assigned Tuesday Feb. 1, 2005 • due in class Tuesday Feb. 8, 2005 • Details on the assignment page of the course web-site. Cse583 Winter 2002
Map of today’s lecture • Thanks to Walid Taha. Todays lecture comes from chapter 4 of his thesis • Simple interpreter for lambda calculus • Addition of constants for • Operators • If-then-else over integer • Y combinator • Add staging annotations • Fix up environment mess Cse583 Winter 2002
Terms and Values datatype exp = EI of int (* integers *) | EA of exp * exp (* applications *) | EL of string * exp (* lambda-abs *) | EV of string; (* variables *) datatype value = VI of int | VF of (value -> value); Cse583 Winter 2002
Example terms fn x => x val ID = EL("x",EV "x"); val COMPOSE = EL("f", EL("g", EL("x",EA(EV "f", EA(EV "g",EV "x"))))); fn f => fn g => fn x => f(g x) Cse583 Winter 2002
Example Values val id = VF(fn x => x); val compose = VF(fn (VF f) => VF (fn (VF g) => VF(fn x => f(g x)))); val square = VF (fn (VI x) => VI(x * x)); val bang = let fun fact n = if n=0 then 1 else n*(fact (n-1)) in VF (fn (VI x) => VI(fact x)) end; Note how “primitive” functions can be implemented Cse583 Winter 2002
An interpreter • The interpreter • ev0 : (string -> value) -> exp -> value • Environments type env =string -> value; exception NotBound of string val env0 = fn x => (print x; raise (NotBound x)); fun ext env x v = (fn y => if x=y then v else env y); Cse583 Winter 2002
Semantics in 8 lines fun ev0 env e = case e of EI i => VI i | EA(e1,e2) => (case (ev0 env e1,ev0 env e2) of (VF f,v) => f v) | EL(x,e1) => VF(fn v => ev0 (ext env x v) e1) | EV x => env x; -| val ex1 = ev0 env0 (EA(ID,EI 5)); val ex1 = VI 5 : value Cse583 Winter 2002
Printing Terms fun showe e = case e of EI n => show n | EA(f,x as EA(_,_)) => (showe f)^" ("^(showe x)^")" | EA(f,x) => (showe f)^" "^(showe x) | EL(x,e) => "(fn "^x^" => "^(showe e)^")" | EV x => x Cse583 Winter 2002
Making it useful • The interpreter is good for the lambda calculus with integer constants, but we have no operations on integers • Need to add primitive operations • Arithmetic • Case analysis over integers • Recursion over integers • This is accomplished by adding an initial environment with values for some constants Cse583 Winter 2002
Arithmetic val plus = VF(fn (VI x) => VF(fn (VI y) => VI(x+y))); val minus = VF(fn (VI x) => VF(fn (VI y) => VI(x-y))); val times = VF(fn (VI x) => VF(fn (VI y) => VI(x*y))); val env1 = ext env0 "*" times; val SQUARE = EL("x",EA(EA(EV "*",EV "x"),EV "x")); -| val ex2 = ev0 env1 (EA (SQUARE,EI 5)); val ex2 = VI 25 : value Cse583 Winter 2002
If-zero function fun Z n tf ff = if n=0 then tf 0 else ff n; val Z : int -> (int -> 'a ) -> (int -> 'a ) -> 'a val ifzero = VF(fn (VI n) => VF(fn (VF tf) => VF(fn (VF ff) => if n=0 then tf(VI 0) else ff(VI n)))); Cse583 Winter 2002
Recursion fun Y f = f (fn v => (Y f) v); Y : (('b -> 'a ) -> 'b -> 'a ) -> 'b -> 'a val recur = let fun recur' (VF f) = f(VF (fn v=> (case (recur' (VF f)) of VF fp => fp v | w => error “not function“ ))) in VF recur' end; Cse583 Winter 2002
New initial environment val env1 = ext(ext(ext(ext(ext env0 "+" plus) "-" minus) "*" times) "Z" ifzero) "Y" recur; Cse583 Winter 2002
Using the constants • Start with a recursive function in ML • Transform it removing ML features • Example function fun h1 n z = if n=0 then z else (fn x => (h1 (n-1) (x+z))) n; Cse583 Winter 2002
Steps • Remove recursion by using Y val h1 = Y(fn h1' => fn n => fn z => if n=0 then z else (fn x => (h1' (n-1) (x+z))) n); • Remove if val h1 = Y(fn h1' => fn n => fn z => Z n (fn _ => z) (fn n => (fn x => (h1' (n-1) (x+z))) n)); Cse583 Winter 2002
Make a term fun minus x y = EA(EA(EV "-",x),y); fun plus x y = EA(EA(EV "+",x),y); val H1 = EA(EV "Y",EL("h1",EL("n",EL("z", EA(EA(EA(EV "Z",EV "n") ,EL("w",EV "z")) ,EL("n",EA(EL("x",EA(EA(EV "h1", minus (EV "n") (EI 1)) ,plus (EV "x") (EV "z"))) ,EV "n"))))))); Cse583 Winter 2002
What does it look like? -| print(showe H1); Y (fn h1 => (fn n => (fn z => Z n (fn w => z) (fn n => (fn x => h1 (- n 1)(+ x z)) n)))) Cse583 Winter 2002
Running it -| val IT = EA(EA(H1,EI 3),EI 4); -| val answer = ev0 env1 IT; val answer = VI 10 : value Cse583 Winter 2002
Adding Staging • What are the new kinds of values • Code • Represented as embedding exp in value • What are the new kinds of terms • Brackets • Escapes • Run • Cross stage persistent constants Cse583 Winter 2002
Terms and values datatype value = VI of int | VF of (value -> value) | VC of exp and exp = EI of int (* integers *) | EA of exp * exp (* applications *) | EL of string * exp (* lambda-abstractions *) | EV of string (* variables *) | EB of exp (* brackets *) | ES of exp (* escape *) | ER of exp (* run *) | EC of string * value; (* cross-stage constants *) Cse583 Winter 2002
Generalizing environments type env = string -> exp; fun env0 x = EV x; val env1 = ext(ext(ext(ext(ext env0 "+" (EC("+",plus))) "-" (EC("-",minus))) "*" (EC("*",times))) "Z" (EC("if",ifzero))) "Y" (EC("Y",recur)); Note the initial values in the environment are cross-stage persistent Expressions. Other values will also be injected usingEC Cse583 Winter 2002
Printing terms fun showe e = case e of EI n => show n | EA(f,x as EA(_,_)) => (showe f)^" ("^(showe x)^")" | EA(f,x) => (showe f)^" "^(showe x) | EL(x,e) => "(fn "^x^" => "^(showe e)^")" | EV x => x | EB e => "<"^(showe e)^">" | ES(EV x) => "~"^x | ES e => "~("^(showe e)^")" | ER e => "run("^(showe e)^")" | EC(s,v) => "%"^s; Cse583 Winter 2002
Fresh Variables val ctr = ref 0; fun NextVar s = let val _ = ctr := (!ctr) + 1 in s^(toString (! ctr)) end; -| NextVar "x"; val it = "x1" : string -| NextVar "x"; val it = "x2" : string Cse583 Winter 2002
The interpreter fun ev1 env e = case e of EI i => VI i | EA(e1,e2) => (case (ev1 env e1,ev1 env e2) of (VF f,v) => f v) | EL(x,e1) => VF(fn v => ev1 (ext env x (EC(x,v))) e1) | EV x => (case env x of EC(_,v) => v | w => VC w) | EB e1 => VC(eb1 1 env e1) | ER e1 => (case ev1 env e1 of VC e2 => ev1 env0 e2) | EC(_,v) => v | ES e1 => error "escape at level 0" Cse583 Winter 2002
Rebuilding terms and eb1 n env e = case e of EI i => EI i | EA(e1,e2) => EA(eb1 n env e1,eb1 n env e2) | EL(x,e1) => let val x' = NextVar x in EL(x',eb1 n (ext env x (EV x')) e1) end | EV y => env y | EB e1 => EB(eb1 (n+1) env e1) | ES e1 => if n=1 then (case ev1 env e1 of VC e => e) else ES(eb1 (n-1) env e1) | ER e1 => ER(eb1 n env e1) | EC(s,v) => EC(s,v) Cse583 Winter 2002
Staging H1 val H2 = let fun minus x y = EA(EA(EV "-",x),y) fun plus x y = EA(EA(EV "+",x),y) in EA(EV "Y",EL("h1",EL("n",EL("z", EA(EA(EA(EV "Z",EV "n") ,EL("w",EV "z")) ,EL("n",EB(EA(EL("x",ES(EA(EA(EV "h1", minus (EV "n") (EI 1)) ,EB(plus (EV "x") (ES (EV "z")))))) ,EV "n")))))))) end; -| print(showe H2); Y (fn h1 => (fn n => (fn z => Z n (fn w => z) (fn n => <(fn x => ~(h1 (- n 1) <+ x ~z>)) n>)))) Cse583 Winter 2002
Generating code val VC answer = ev1 env1 IT; -| val answer = EA (EL ("x7", EA (EL ("x8", EA (EL ("x9", EA (EA (EC ("+",VF fn ),EV "x9"), EA (EA (EC ("+",VF fn ),EV "x8"), EA (EA (EC ("+",VF fn ),EV "x7"),EI 4)))), EC ("n",VI 1))), EC ("n",VI 2))), EC ("n",VI 3)) -| showe answer; val it = "(fn x7 => (fn x8 => (fn x9 => %+ x9 (%+ x8 (%+ x7 4))) %n) %n) %n" Cse583 Winter 2002
A problem -| val puzzle = run ((run <fn a => ~( (fn x => <x>) (fn w => <a>) ) 5>) 3); -| val puzzle = 3 : int Cse583 Winter 2002
In our language (* (fn x => <x>) *) val t1 = EL("x",EB(EV "x")); (* (fn w => <a>) *) val t2 = EL("w",EB(EV "a")); (* <fn a => ~( (fn x => <x>) (fn w => <a>) ) 5> *) val t3 = EB(EL("a",EA(ES(EA(t1,t2)),EI 5))); val puzzle = ER(EA(ER t3,EI 3)); -| showe puzzle; val it = "run(run(<(fn a => ~((fn x => <x>) (fn w => <a>)) 5)>) 3)“ Cse583 Winter 2002
Running it run(run(<(fn a => ~((fn x => <x>) (fn w => <a>)) 5)>) 3)“ -| ev1 env1 puzzle; val it = VC EV "a14" : value What’s gone wrong? Cse583 Winter 2002
Covers fun coverE env e = case e of EI i => EI i | EA(e1,e2) => EA(coverE env e1,coverE env e2) | EL(x,e1) => EL(x,coverE env e1) | EV y => env y | EB e1 => EB(coverE env e1) | ES e1 => ES(coverE env e1) | ER e1 => ER(coverE env e1) | EC(s,v) => EC(s,coverV env v) and coverV env v = case v of VI i => VI i | VF f => VF((coverV env) o f) | VC e => VC(coverE env e); Cse583 Winter 2002
Final interpreter fun ev1 env e = case e of EI i => VI i | EA(e1,e2) => (case (ev1 env e1,ev1 env e2) of (VF f,v) => f v) | EL(x,e1) => VF(fn v => ev1 (ext env x (EC(x,v))) e1) | EV x => (case env x of EC(_,v) => v | w => VC w) | EB e1 => VC(eb1 1 env e1) | ER e1 => (case ev1 env e1 of VC e2 => ev1 env0 e2) | EC(s,v) => coverV env v Cse583 Winter 2002
Final rebuilder and eb1 n env e = case e of EI i => EI i | EA(e1,e2) => EA(eb1 n env e1,eb1 n env e2) | EL(x,e1) => let val x' = NextVar x in EL(x',eb1 n (ext env x (EV x')) e1) end | EV y => env y | EB e1 => EB(eb1 (n+1) env e1) | ES e1 => if n=1 then (case ev1 env e1 of VC e => e) else ES(eb1 (n-1) env e1) | ER e1 => ER(eb1 n env e1) | EC(s,v) => EC(s,coverV env v) Cse583 Winter 2002
Now it works -| ev1 env1 puzzle; val it = VI 3 : value Cse583 Winter 2002