1 / 31

Implementing Staged Computation

Implementing Staged Computation. Chiyan Chen and Hongwei Xi Boston University. Talk Overview. Staged Computation Guarded Recursive Datatype Constructors Code Representation Higher-order Abstract Syntax First-order Abstract Syntax (via de Bruijn indices). An Example in Scheme.

meli
Download Presentation

Implementing Staged Computation

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Implementing Staged Computation Chiyan ChenandHongwei Xi Boston University

  2. Talk Overview • Staged Computation • Guarded Recursive Datatype Constructors • Code Representation • Higher-order Abstract Syntax • First-order Abstract Syntax (via de Bruijn indices)

  3. An Example in Scheme (define (run code) (eval code nil)) (define (power n x)(if (= n 0) 1 `(* ,x ,(power (- n 1) x)))) ;;; (power 2 ‘x) yields (* x (* x 1)) (define square(run `(lambda (x) ,(power 2 ‘x)))) ;;; (power 3 ‘y) yields (* y (* y (* y 1))) (define cube(run `(lambda (y) ,(power 3 ‘y))))

  4. An Example in MetaML (* ‘run’ is a built-in function of the type <‘a> -> ‘a *) fun power (n: int) (x: <int>): <int> =if n = 0 then <1>else <~x * ~(power (n-1) x)> val square = run <fn x => ~(power 2 <x>)> val cube = run <fn x => ~(power 3 <x>)>

  5. Scheme vs. MetaML • Most significantly, there is a type system in MetaML but none in Scheme for verifying whether staging is done correctly. • However, ‘code’ can be readily represented in Scheme but not in ML

  6. Scheme vs. MetaML (continued) For instance, (define (power n x)(if (= n 0) 1 `(* ,x ,(power (- n 1) x)))) can really be defined as follows: (define (power n x)(if (= n 0) 1 (list ‘* x (power (- n 1) x))))

  7. G.R. Datatype Constructors • A simple and natural generalization of the notion of datatypes in ML • We use $D.t for a guarded type, where D may contain some constraints on type variables in t • A g.r. datatype constructor is used to construct g.r. datatypes, that is, sums of guarded types.

  8. A Representation for Types The g.r. datatype constructor TY is for representing simple types: typecon (type) TY = (int) TYint| {’a,’b}. (’a * ’b) TYtup of ’a TY * ’b TY| {’a,’b}. (’a-> ’b) TYfun of ’a TY * ’b TY| {’a}. (’a TY) TYtyp of ’a TY TYint: (int) TY TYtup: {’a,’b}. ’a TY * ’b TY -> (’a * ’b) TY TYfun: {’a,’b}. ’a TY * ’b TY -> (’a -> ’b) TY TYtyp: {’a}. ’a TY -> (’a TY) TY

  9. The Representation of Some Types • The type ‘int’ is represented as TYint • The type ‘int * int’ is represented as TYtup(TYint, TYint) • The type ‘int -> int * int’ is represented as TYfun(TYint, TYtup (TYint, TYint)) • The type ‘(int) TY’ is represented as TYtyp(TYint)

  10. A Program Example: val2string fun val2string pf x =case pf of TYint => int2string x| TYtup (pf1, pf2) => “(” ^ val2string pf1 (fst x) ^ “,” ^ val2string pf2 (snd x) ^ “)”| TYfun _ => “[a function]”| TYtyp _ => “[a type]” withtype {’a}. ’a TY -> ’a -> string

  11. H.O.A.S. Trees typecon (type) HOAS = {’a}. (’a) HOASlift of ’a| {’a}. (’a) HOASif of bool HOAS * ’a HOAS * ’a HOAS| {’a,’b}. (’a * ’b) HOAStup of ’a HOAS * ’b HOAS| {’a,’b}. (’a -> ’b) HOASlam of ’a HOAS -> ’b HOAS| {‘a,’b}. (‘b) HOASapp of (‘a ->’b) HOAS * ‘a HOAS| {’a}. (’a) HOASfix of ’a HOAS -> ’a HOAS HOASlift: {’a}. ’a -> ’a HOAS HOASif: {’a}. bool HOAS * ’a HOAS * ’a HOAS -> ’a HOAS HOAStup: {’a,’b}. ’a HOAS * ’b HOAS -> (’a * ’b) HOAS HOASlam: {’a,’b}. (’a HOAS -> ’b HOAS) -> (’a -> ’b) HOAS HOASapp: {‘a,’b}. (‘a -> ‘b) HOAS * ‘a HOAS -> ‘b HOAS HOASfix: {’a}. (’a HOAS -> ’a HOAS) -> ’a HOAS

  12. A Type-Preserving Evaluator fun eval (HOASlift v) = v| eval (HOASif (b, e1, e2)) = if eval (b) then eval (e1) else eval (e2)| eval (HOAStup (e1, e2)) = (eval (e1), eval (e2))| eval (HOASlam (f)) = fn x => eval (f (HOASlift x))| eval (HOASapp (e1,e2)) = (eval e1) (eval e2)| eval (HOASfix f) = eval (f (HOASfix f)) withtype {’a}. ’a HOAS -> ’a

  13. Compiling H.O.A.S. Trees • We need a compilation function that can compile h.o.a.s trees: run: {’a}. ’a HOAS -> ’a (think about normalization by evaluation) • For instance, this can be done in such a manner …

  14. A Staged Program • fun power1 n = HOASlam ( fn x: int HOAS => if n = 0 then HOASlift 1 else HOASapp ( HOASlift op *, HOAStup (x, HOASapp (power1 n-1, x)))) withtype int -> (int -> int) HOAS • val square1 = run (power1 2) • The function square1 is like being defined as: fun square1 x = x * f1 (x) and f1(x) = x * f0(x) and f0(x) = 1

  15. Another Staged Program • fun power2 n x = if n = 0 then HOASlift 1 else HOASapp (HOASlift op*, HOAStup (x, power2 (n-1) x)withtype int -> int HOAS -> int HOAS • val square2 = run (HOASlam (power2 2)) • The function square2 is like being defined as fun square2 x = x * (x * 1)

  16. Syntactic Sugar • <t> = (t) HOAS • `(x) = HOASlift (x) • `(c) = HOASlift (c) • `(e1, e2) = HOAStup (`(e1), `(e2)) • `(e1(e2)) = HOASapp(`(e1), `(e2)) • `(fn x => e) = HOASlam (fn x => `(e[x -> ^x])) • `(fix f => e) = HOASfix (fn f => `(e[f -> ^f])) • `(e: t) = (`(e): (t) HOAS) • `(^(e)) = e

  17. An Example in Sugared Syntax • fun power1 n = `(fn x => ^(if n = 0 then lift (1) else `(x * ^(power1 (n-1)) x))) withtype int -> <int -> int> • val square1: int -> int = run (power1 2)

  18. Another Example in Sugared Syntax • fun power2 n x = if n = 0 then lift (1) else `(^x * ^(power2 (n-1) x))withtype int -> <int> -> <int> • val square2: int -> int = run `(fn x => ^(power2 2 `(x))

  19. The Usual Ackermann Function fun acker m n =if m =0 then n+1else acker (m-1) (if n = 0 then 1 else acker m (n-1)) withtype int ->int -> int

  20. A Staged Ackermann Function • The Ackermann function can be staged as follows: fun acker m = `(fix f => fn n => ^(if m = 0 then `(n+1) else `(^(acker (m-1)) (if n = 0 then 1 else f (n-1))))) withtype int -><int -> int>

  21. A Staged Ackermann Function (contd.) • For instance, we can define a function acker2 as follows: fun acker2 = run (acker 2)This definition is similar to the following one:fun acker2 n = acker1 (if n = 0 then 1 else acker2 (n-1))and acker1 n = acker0 (if n = 0 then 1 else acker1 (n-1))and acker0 n = n+1

  22. A Problem with H.O.A.S. Trees • The expression e = `(fn x => ^(run `(x))), whose translation is HOASlam (fn x => run x), can be assigned the type: {‘a}. (‘a HOAS -> ‘a) HOAS • However, ‘run e’ causes a run-time error

  23. F.O.A.S. Trees typecon (type,type) FOAS =| {’a,’g}. (’a,’g) FOASlift of ’a| {’a,’g}. (‘a,’a*’g) FOASone| {’a,’b,’g}. (‘a,’b*’g) FOASshift of (‘a,’g) FOAS| {‘a,’b,’g}. (‘a -> ‘b,’g) FOASlam of (‘b,’a*’g) FOAS| … FOASlift: {’a,’g}. ’a -> (’a,’g) FOAS FOASone: {‘a,’g}. (‘a,’a*’g) FOAS FOASshift: {‘a,’b’,’g}. (‘a,’g) FOAS -> (‘a,’b*’g) FOAS FOASlam: {‘a,’b,’g}. (‘b,’a * ‘g) FOAS -> (‘a -> ‘b,’g) FOAS …

  24. Some Examples of F.O.A.S. Trees • The F.O.A.S. tree for ‘fn x => x’: FOASlam (FOASone) • The F.O.A.S. tree for ‘fn x => fn y => x+y’: FOASlam(FOASlam( FOASapp (FOASlift +, FOAStup (FOASshift (FOASone), FOASone))))

  25. Some Examples of F.O.A.S. Trees • FOASone can be assigned the type:(int, int * unit) FOAS • FOASapp (FOASone, FOASshift(FOASone)) can be assigned the type:(int, (int -> int) * (int * unit)) FOAS • FOASapp (FOASshift(FOASone), FOASone) can be assigned the type:(int, int * ((int -> int) * unit)) FOAS

  26. Compiling F.O.A.S trees • We need a function to compile closed F.O.A.S. trees: run: {‘a}. (‘a, unit) FOAS ->‘a • This can be readily implemented …

  27. A Simple Example fun power1 n =if n = 0 then FOASlam (FOASlift 1)else FOASlam ( FOASapp ( FOASlift *, FOAStup (FOASone, FOASapp (power1 (n-1), FOASone)))) withtype {‘g}. int -> (int -> int, ‘g) FOAS val square = run (power1 2)

  28. Another Simple Example fun power2 n x =if n = 0 then FOASlift (1)else FOASapp (FOASlift *, FOAStup (x, power2 (n-1) x)) withtype{‘g}. int -> (int, ‘g) FOAS -> (int, ‘g) FOAS val square = run (FOASlam (power2 2 FOASone))

  29. Conclusion • We have presented two approaches (h.o.a.s. and f.o.a.s.) to representing ‘code’ through the use of g.r. datatype constructors • With such concrete represention of code, we can implement staged computation by simply translating away staging notations in staged programs

  30. Related Work • Guarded Recursive Datatype Constructors (Xi et al) • MetalML (Sheard et al) • Staged Computation (Pfenning and Davis) • … …

  31. End of the Talk Thank you! Questions?

More Related