Presentation is loading. Please wait.

Presentation is loading. Please wait.

Closure and Environment Compiler Baojian Hua

Similar presentations


Presentation on theme: "Closure and Environment Compiler Baojian Hua"— Presentation transcript:

1 Closure and Environment Compiler Baojian Hua bjhua@ustc.edu.cn

2 Higher-order functions (HOF) Higher-order functions are not just for call can be passed as arguments can be returned as results can be stored in data structures objects! we ’ d discuss later If functions don ’ t nest, then the implementation is simple a simple code address e.g., the “ function pointer ” in C What about nesting with HOF?

3 Nesting (* ML code. *) (* Staging. Harper, section 11.5: *) val add = fn x => (fn y => x + y) val inc = add 1 (* fn y => 1 + y *) (* Can be more abstract: *) val bop = fn f => (fn x => (fn y => f (x, y))) val add = fn (op +) val inc = add 1

4 Nesting // C code. // GNU C extension supports this. But its // implementation is rather limited and incorrect! int (*(add)(int x))(int) { int f (int y) { return x + y; } return f; } // Don’t expect GCC behaves normally, hummmm… int (*inc) (int) = add (1);

5 Moral Nested HOL is a key feature in modern functional programming languages And now has grown into other language e.g., C# and Java7 Key observation: function arguments and locals can NOT be reclaimed after the call fn x => (fn y => x + y) they may be used in the returned nested function!

6 Closure A closure is a data structure to represent a function at runtime A closure is essentially a heap-allocated struct/tuple containing a code pointer, as well as a (L-)values for the function ’ s free variables (environment) The process of converting a function to a closure is called closure conversion

7 Lambda again e -> n -> x -> \x.e -> e e // or in ML: datatype e = Int of int | Var of string | Lam of string * e | App of e * e

8 Rules C (n) = n C (x) = #x env C (\x.e) = let fun f (env_t, x) = let val x1 = #x1 env_t … val xn = #xn env_t val env’ = {x=x, x1=x1, …, xn=xn} in C (e) end in (f, env) end C (e1 e2) = C(e1) C(e2)

9 Example #1 // for code: \x.x // the initial call: C (\x.x) = let fun f (env_t, x) = let val env’ = {x = x} in C (x) end in (f, env) end

10 Recursive transformation // for code: \x.x // the initial call: C (\x.x) = let fun f (env_t, x) = let val env = {x = x} in #x env end in (f, env) end

11 Hoisting // for code: \x.x // hoist all code to top-level: fun f (env_t, x) = let val env = {x = x} in #x env end (f, {})

12 Function call // consider the code: (\x.x) 5 // \x.x as before: fun f (env_t, x) = let val env’ = {x = x} in #x env end (f, env) // Leave it to you to verify the whole becomes: (f, env) 5 // and the call becomes: f (env, 5)

13 Summary so far Three steps in closure conversion: apply the conversion rules to make every function closed a function become a closure: (code, env) Hoisting: all functions at top-level like those in C function call become closure application (code, env) x ==> code (env, x)

14 Example #2 // code: \x.\y.x+y // conversion: C (\x.\y.x+y) = let fun f1 (env_t, x) = let val env = {x = x} in C (\y.x+y) end in (f1, env) end // Leave to you to finish other steps!

15 Example #2 // code: \x.\y.x+y // final result: fun f2 (ent_t, y) = let val x = #x ent_t val env = {x=x, y=y} in #x env + #y env end fun f1 (env_t, x) = let val env = {x = x} in (f2, env) end (f1, env)

16 In picture // for \x.\y.\z.x+y+z f1 /\ f2 f3

17 Linked vs flatten closure The flatten model of closure is bad: it evolves too much “ copy ” operations it ’ s space inefficient Instead, we could make the closure linked by sharing environment just as the static link

18 Linked Environment // revised rules: C (\x.e) = let fun f (env_t, x) = let val env = Cons (env_t, x) in C (e) end in (f, env) end

19 In picture // for \x.\y.\z.x+y+z f1 /\ f2 f3


Download ppt "Closure and Environment Compiler Baojian Hua"

Similar presentations


Ads by Google