1 / 19

Closure and Environment

Closure and Environment. Compiler Baojian Hua bjhua@ustc.edu.cn. 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

forbes
Télécharger la présentation

Closure and Environment

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. 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

More Related