1 / 50

A Fix for Dynamic Scope

A Fix for Dynamic Scope. Ravi Chugh U. of California, San Diego. Backstory. Goal: Types for “Dynamic” Languages. Syntax and Semantics of JavaScript. Translation à la Guha et al. (ECOOP 2010). Core λ -Calculus + Extensions. Backstory. Goal: Types for “Dynamic” Languages.

Download Presentation

A Fix for Dynamic Scope

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. A Fix for Dynamic Scope Ravi Chugh U. of California, San Diego

  2. Backstory Goal: Types for “Dynamic” Languages Syntax and Semantics of JavaScript Translation à la Guha et al.(ECOOP 2010) Core λ-Calculus + Extensions

  3. Backstory Goal: Types for “Dynamic” Languages • Approach: Type Check Desugared Programs • Simple Imperative, RecursiveFunctions are Difficult to Verify Core λ-Calculus + Extensions

  4. varfact = function(n) { if (n<= 1) {return 1;} else {returnn* fact(n-1);} }; • Translate to statically typed calculus?

  5. varfact = function(n) { if (n <= 1) {return 1; } else { return n* fact(n-1);} }; • Translate to statically typed calculus? • Option 1: λ-Calculus (λ) ✗ letfact =λn. if n<= 1 then 1 else n * fact(n-1) • fact is not bound yet…

  6. varfact = function(n) { if (n <= 1) {return 1; } else { return n* fact(n-1);} }; • Translate to statically typed calculus? • Option 2: λ-Calculus + Fix (λfix) ✗ letfact = fix (λfact. λn. if n<= 1 then 1 else n * fact(n-1) ) • Desugared fact should be mutable…

  7. varfact = function(n) { if (n <= 1) {return 1; } else { return n* fact(n-1);} }; • Translate to statically typed calculus? • Option 3: λ-Calculus + Fix + Refs (λfix,ref) ✗ letfact = ref (fix (λfact. λn. if n<= 1 then 1 else n * fact(n-1) )) • Recursive call doesn’t go through reference… • Okay here, but prevents mutual recursion

  8. varfact = function(n) { if (n <= 1) {return 1; } else { return n* fact(n-1);} }; • Translate to statically typed calculus? • Option 4: λ-Calculus + Fix + Refs (λref) ✓ letfact = ref (λn. if n<= 1 then 1 else n * !fact(n-1) ) • Yes, this captures the semantics! • But how to type check ???

  9. letfact = ref (λn. if n<= 1 then 1 else n * !fact(n-1) )

  10. Backpatching Pattern in λref • fact :: Ref (Int  Int) letfact = ref (λn. 0) in fact := λn. if n<= 1 then 1 else n * !fact(n-1) ; • Assignment relies on and guaranteesthe reference invariant

  11. Backpatching Pattern in λref • Simple types suffice if reference isinitialized with dummy function… letfact = ref (λn. 0) in fact := λn. if n <= 1 then 1 else n * !fact(n-1) ; • But we want to avoid initializers to: • Facilitate JavaScript translation • Have some fun!

  12. Proposal: Open Types for λref fact :: (fact :: Ref (Int  Int)) Ref (Int  Int) Assuming fact points to an integer function, fact points to an integer function letfact = ref (λn. if n<= 1 then 1 else n * !fact(n-1) )

  13. Proposal: Open Types for λref fact :: (fact :: Ref (Int  Int)) Ref (Int  Int) Assuming fact points to an integer function, fact points to an integer function letfact = ref (λn. if n<= 1 then 1 else n * !fact(n-1) ) in !fact(5) • Type system must checkassumptions at every dereference

  14. Proposal: Open Typesfor λref Motivated by λref programs that result fromdesugaring JavaScript programs letfact = ref (λn. if n<= 1 then 1 else n * !fact(n-1) )

  15. Proposal: Open Typesfor λref Motivated by λref programs that result from desugaring JavaScript programs Proposal also applies to, and is easier to show for,the dynamically-scoped λ-calculus (λdyn) letfact =λn. if n<= 1 then 1 else n * fact(n-1) • Bound at the time of call… • No need for fix or references

  16. Lexical vs. Dynamic Scope λ • Environment at definition is frozen in closure… • And is used to evaluate function body • Explicit evaluation rule for recursion

  17. Lexical vs. Dynamic Scope λ λdyn • Bare lambdas, so allfree variables resolved in calling environment

  18. Lexical vs. Dynamic Scope λ λdyn • No need forfix construct

  19. Open Types for λdyn Types (Base or Arrow) Open Types Type Environments Open Type Environments

  20. Open Types for λdyn • Open function type describes environment for function body Open Typing

  21. Open Types for λdyn • Open function type describes environment for function body • Type environment at function definition is irrelevant Open Typing

  22. Open Types for λdyn Open Typing • In some sense, extreme generalization of [T-Fix] STLC + Fix

  23. Open Types for λdyn Open Typing STLC + Fix

  24. Open Types for λdyn For every • Rely-set contains • Guarantee-set contains (most recent, if multiple) Open Typing

  25. Open Types for λdyn For every • Rely-set contains • Guarantee-set contains (most recent, if multiple) Open Typing Open Typing • Discharge all assumptions

  26. Open Types for λdyn Open Typing

  27. Examples letfact =λn. if n<= 1 then 1 else n * fact(n-1) in fact 5 fact :: (fact :: Int  Int) Int  Int

  28. Examples letfact = λn. if n <= 1 then 1 else n * fact(n-1) in fact 5 fact :: (fact :: Int  Int) Int  Int Guarantee Rely ✓

  29. Examples lettick n = if n> 0 then “tick ” ++ tock n else “” in tick 2; Error: var [tock] not found

  30. Examples lettick n = if n> 0 then “tick ” ++ tock n else “” in tick 2; tick :: (tock :: Int  Str) Int  Str

  31. Examples lettick n = if n > 0 then “tick ” ++ tock n else “” in tick 2; tick :: (tock :: Int  Str) Int  Str ✗ Guarantee Rely

  32. Examples lettick n = if n> 0 then “tick ” ++ tock n else “” in let tock n = “tock ” ++ tick (n-1) in tick 2; “tick tock tick tock ”

  33. Examples lettick n = if n> 0 then “tick ” ++ tock n else “” in let tock n = “tock ” ++ tick (n-1) in tick 2; tick :: (tock :: Int  Str) Int  Str tock :: (tick :: Int  Str) Int  Str

  34. Examples lettick n = if n > 0 then “tick ” ++ tock n else “” in let tock n = “tock ” ++ tick (n-1) in tick 2; tick :: (tock :: Int  Str) Int  Str tock :: (tick :: Int  Str) Int  Str Guarantee Rely ✓

  35. Examples lettick n = if n> 0 then “tick ” ++ tock n else “” in let tock n = “tock ” ++ tick (n-1) in let tock = “bad” in tick 2; Error: “bad” not a function

  36. Examples lettick n = if n> 0 then “tick ” ++ tock n else “” in let tock n = “tock ” ++ tick (n-1) in let tock = “bad” in tick 2; tick :: (tock :: Int  Str) Int  Str tock :: (tick :: Int  Str) Int  Str tock :: Str

  37. Examples lettick n = if n > 0 then “tick ” ++ tock n else “” in let tock n = “tock ” ++ tick (n-1) in let tock = “bad” in tick 2; tick :: (tock :: Int  Str) Int  Str tock :: (tick :: Int  Str) Int  Str tock :: Str Guarantee Rely ✗

  38. Examples lettick n = if n> 0 then “tick ” ++ tock n else “” in let tock n = “tock ” ++ tick (n-1) in let tock = tick (n-1) in tick 2; “tick tick ”

  39. Examples lettick n = if n> 0 then “tick ” ++ tock n else “” in let tock n = “tock ” ++ tick (n-1) in let tock = tick (n-1) in tick 2; tick :: (tock :: Int  Str) Int  Str tock :: (tick :: Int  Str) Int  Str tock :: (tick :: Int  Str) Int  Str

  40. Examples lettick n = if n > 0 then “tick ” ++ tock n else “” in let tock n = “tock ” ++ tick (n-1) in let tock = tick (n-1) in tick 2; tick :: (tock :: Int  Str) Int  Str tock :: (tick :: Int  Str) Int  Str tock :: (tick :: Int  Str) Int  Str Guarantee Rely ✓

  41. Recap • Open Types capture“late packaging” of recursive definitions indynamically-scoped languages • (Metatheory has not yet been worked) • Several potential applications inlexically-scoped languages…

  42. Open Types for λref • References in λrefare similar to dynamically-scoped bindings in λdyn • For open types in this setting,type system must supportstrong updates to mutable variables • e.g. Thiemann et al. (ECOOP 2010), Chugh et al. (OOPSLA 2012)

  43. Open Types for λref lettick = ref null in lettock = ref null in tick :=λn. if n> 0 then “tick ” ++ !tock(n) else “”; tock :=λn. “tock ” ++ !tick(n-1); !tick(2); tick :: Ref Null tick :: Ref Null tock :: Ref Null tick :: (tock :: Ref (Int  Str)) Ref (Int  Str) tock :: Ref Null tick :: (tock :: Ref (Int  Str)) Ref (Int  Str) tock :: (tick :: Ref (Int  Str)) Ref (Int  Str) Guarantee Rely ✓ tick :: (tock :: Ref (Int  Str)) Ref (Int  Str) tock :: (tick :: Ref (Int  Str)) Ref (Int  Str)

  44. Open Types for Methods lettick n = if n> 0 then “tick ” ++ this.tock(n) else “” in let tock n = “tock ” ++ this.tick(n-1) in let obj = {tick=tick; tock=tock} in obj.tick(2); tick :: (this :: {tock: Int  Str}) Int  Str tock :: (this :: {tick: Int  Str}) Int  Str

  45. Related Work • Dynamic scope in lexical settings for: • Software updates • Dynamic code loading • Global flags • Implicit Parameters of Lewis et al. (POPL 2000) • Open types mechanism resembles their approach • We aim to support recursion and references • Other related work • Bierman et al. (ICFP 2003) • Dami (TCS 1998), Harper (Practical Foundations for PL) • …

  46. Thanks! Open Types for Checking Recursion in: • Dynamically-scoped λ-calculus • Lexically-scoped λ-calculus with references • Thoughts? Questions?

  47. EXTRA SLIDES

  48. Higher-Order Functions • Disallows function arguments with free variables • This restriction precludes “downwards funarg problem” • To be less restrictive:

  49. Partial Environment Consistency letnegateInt () = 0 - x in letnegateBool () = not x in letx = 17 in negateInt (); • Safe at run-timeeven though not all assumptions satisfied -17 negateInt :: (x :: Int) Unit  Int negateBool :: (x :: Bool) Unit  Bool x :: Int

  50. Partial Environment Consistency • To be less restrictive: • Only andits transitivedependencies in

More Related