of 167

# Name binding with scope graphs

Slides about name binding with scope graphs for a tutorial presented at POPL 2016 in St Petersburg, Florida
Published on: Mar 3, 2016
Published in: Software

#### Transcripts - Name binding with scope graphs

• 1. Declare Your Language Part 2: Name Binding with Scope Graphs Eelco Visser Tutorial at POPL 2016 January 18, 2016
• 2. Static Name Resolution module A { def s = 5 } module B { import A def x = 6 def y = 3 + s def f = fun x { x + y } }
• 3. Static Name Resolution module module def import def def defA A B 6 y funf x + x y x + 3 s 5s module A { def s = 5 } module B { import A def x = 6 def y = 3 + s def f = fun x { x + y } }
• 4. Static Name Resolution module module def import def def defA A B 6 y funf x + x y x + 3 s 5s module A { def s = 5 } module B { import A def x = 6 def y = 3 + s def f = fun x { x + y } }
• 5. Static Name Resolution module module def import def def defA A B 6 y funf x + x y x + 3 s 5s module A { def s = 5 } module B { import A def x = 6 def y = 3 + s def f = fun x { x + y } }
• 6. Static Name Resolution module module def import def def defA A B 6 y funf x + x y x + 3 s 5s module A { def s = 5 } module B { import A def x = 6 def y = 3 + s def f = fun x { x + y } }
• 7. Static Name Resolution module module def import def def defA A B 6 y funf x + x y x + 3 s 5s module A { def s = 5 } module B { import A def x = 6 def y = 3 + s def f = fun x { x + y } }
• 8. Based On … • Declarative Name Binding and Scope Rules - NaBL name binding language - Gabriël D. P. Konat, Lennart C. L. Kats, Guido Wachsmuth, Eelco Visser - SLE 2012 • A Language Designer's Workbench - A one-stop-shop for implementation and veriﬁcation of language designs - Eelco Visser, Guido Wachsmuth, Andrew P. Tolmach, Pierre Neron, Vlad A. Vergu, Augusto Passalaqua, Gabriël D. P. Konat - Onward 2014 • A Theory of Name Resolution - Pierre Néron, Andrew Tolmach, Eelco Visser, Guido Wachsmuth - ESOP 2015 • A Constraint Language for Static Semantic Analysis based on Scope Graphs - Hendrik van Antwerpen, Pierre Neron, Andrew P. Tolmach, Eelco Visser, Guido Wachsmuth - PEPM 2016
• 9. Detour: Declare Your Syntax (an analogy for formalizing declarative name binding) Pure and declarative syntax deﬁnition: paradise lost and regained Lennart C. L. Kats, Eelco Visser, Guido Wachsmuth Onward 2010
• 10. Language = Set of Sentences fun (x : Int) { x + 1 } Text is a convenient interface for writing and reading programs
• 11. Language = Set of Trees Fun AddArgDecl VarRefId Int “1” VarDeclId “x” TXINT “x” Tree is a convenient interface for transforming programs
• 12. Tree Transformation Tree is a convenient interface for transforming programs Semantic transform translate eval analyze refactor type check Syntactic coloring outline view completion
• 13. Language = Sentences and Trees parse format different representations convenient for different purposes
• 14. SDF3 deﬁnes Trees and Sentences parse(s) = t where format(t) == s (modulo layout) Expr.Int = INT Expr.Add = <<Expr> + <Expr>> Expr.Mul = <<Expr> * <Expr>> trees (structure) parse (text to tree) format (tree to text) + =>
• 15. Grammar Engineering in Spoofax
• 16. Ambiguity
• 17. Ambiguity t1 != t2 / format(t1) = format(t2) Add VarRef VarRef “y”“x” Mul Int “3” Add VarRef VarRef “y” “x” Mul Int “3” 3 * x + y
• 18. Declarative Disambiguation parse ﬁlter Disambiguation Filters Klint & Visser (1994), Van den Brand, Scheerder, Vinju, Visser (CC 2002)
• 19. Priority and Associativity context-free syntax Expr.Int = INT Expr.Add = <<Expr> + <Expr>> {left} Expr.Mul = <<Expr> * <Expr>> {left} context-free priorities Expr.Mul > Expr.Add Recent improvement: safe disambiguation of operator precedence Afroozeh et al. (SLE 2013, Onward 2015) Add VarRef VarRef “y”“x” Mul Int “3” Add VarRef VarRef “y” “x” Mul Int “3” 3 * x + y
• 20. Declarative Syntax Deﬁnition • Representation: (Abstract Syntax) Trees - Standardized representation for structure of programs - Basis for syntactic and semantic operations • Formalism: Syntax Deﬁnition - Productions + Constructors + Templates + Disambiguation - Language-speciﬁc rules: structure of each language construct • Language-Independent Interpretation - Well-formedness of abstract syntax trees ‣ provides declarative correctness criterion for parsing - Parsing algorithm ‣ No need to understand parsing algorithm ‣ Debugging in terms of representation - Formatting based on layout hints in grammar
• 21. Declare Your Names A Theory of Name Resolution Pierre Néron, Andrew Tolmach, Eelco Visser, Guido Wachsmuth ESOP 2015
• 22. Language = Set of Trees Fun AddArgDecl VarRefId Int “1” VarDeclId “x” TXINT “x” Tree is a convenient interface for transforming programs
• 23. Language = Set of Graphs Fun AddArgDecl VarRefId Int “1” VarDeclId TXINT Edges from references to declarations
• 24. Fun AddArgDecl VarRefId Int “1” VarDeclId “x” TXINT “x” Language = Set of Graphs Names are placeholders for edges in linear / tree representation
• 25. Name Resolution is Pervasive • Used in many different language artifacts - compiler - interpreter - semantics - IDE - refactoring • Binding rules encoded in many different and ad-hoc ways - symbol tables - environments - substitutions • No standard approach to formalization - there is no BNF for name binding • No reuse of binding rules between artifacts - how do we know substitution respects binding rules?
• 26. NaBL Name Binding Language binding rules // variables Param(t, x) : defines Variable x of type t Let(bs, e) : scopes Variable Bind(t, x, e) : defines Variable x of type t Var(x) : refers to Variable x Declarative Name Binding and Scope Rules Gabriël D. P. Konat, Lennart C. L. Kats, Guido Wachsmuth, Eelco Visser SLE 2012 Declarative speciﬁcation Abstracts from implementation Incremental name resolution But: How to explain it to Coq? What is the semantics of NaBL?
• 27. NaBL Name Binding Language Declarative Name Binding and Scope Rules Gabriël D. P. Konat, Lennart C. L. Kats, Guido Wachsmuth, Eelco Visser SLE 2012 Especially: What is the semantics of imports? binding rules // classes Class(c, _, _, _) : defines Class c of type ClassT(c) scopes Field, Method, Variable Extends(c) : imports Field, Method from Class c ClassT(c) : refers to Class c New(c) : refers to Class c
• 28. A Theory of Name Resolution • Representation: Scope Graphs - Standardized representation for lexical scoping structure of programs - Path in scope graph relates reference to declaration - Basis for syntactic and semantic operations - Supports ambiguous / erroneous programs • Formalism: Name Binding Speciﬁcation - References + Declarations + Scopes + Reachability + Visibility - Language-speciﬁc rules: mapping constructs to scope graph • Language-Independent Interpretation - Resolution calculus ‣ Correctness of path with respect to scope graph ‣ Separation of reachability and visibility (disambiguation) - Name resolution algorithm ‣ sound wrt calculus - Transformation ‣ Alpha equivalence, substitution, refactoring, …
• 29. Outline • Reachability - References, Declarations, Scopes, Resolution Paths - Lexical, Imports, Qualiﬁed Names • Visibility - Ambiguous resolutions - Disambiguation: path speciﬁcity, path wellformedness • Examples - let, def-before-use, inheritance, packages, imports, namespaces • Formal framework - Generalizing reachability and visibility through labeled scope edges - Resolution algorithm - Alpha equivalence • Names and Types - Type-dependent name resolution • Constraint Language
• 30. Reachability (Slides by Pierre Néron)
• 31. A Calculus for Name Resolution S R1 R2 SR SRS I(R1) S’S S’S P Sx Sx R xS xS D Path in scope graph connects reference to declaration Scopes, References, Declarations, Parents, Imports
• 32. Simple Scopes def y1 = x2 + 1 def x1 = 5
• 33. Simple Scopes def y1 = x2 + 1 def x1 = 5
• 34. Simple Scopes def y1 = x2 + 1 def x1 = 5
• 35. Simple Scopes S0 def y1 = x2 + 1 def x1 = 5
• 36. Simple Scopes Scope S0 def y1 = x2 + 1 def x1 = 5 S0 S
• 37. Simple Scopes Declaration Scope S0 def y1 = x2 + 1 def x1 = 5 y1 x1S0 S x
• 38. Simple Scopes Reference Declaration Scope S0 def y1 = x2 + 1 def x1 = 5 y1 x1S0x2 S x x
• 39. Simple Scopes Reference Declaration Scope Reference Step S0 def y1 = x2 + 1 def x1 = 5 Sx Sx R y1 x1S0x2 S x x
• 40. Simple Scopes Reference Declaration Scope Reference Step S0 def y1 = x2 + 1 def x1 = 5 Sx Sx R R y1 x1S0x2 S x x
• 41. Simple Scopes Reference Declaration Scope Reference Step Declaration Step S0 def y1 = x2 + 1 def x1 = 5 Sx Sx R xS xS D R y1 x1S0x2 S x x
• 42. Simple Scopes Reference Declaration Scope Reference Step Declaration Step S0 def y1 = x2 + 1 def x1 = 5 Sx Sx R xS xS D R D y1 x1S0x2 S x x
• 43. Lexical Scoping def x1 = z2 5 def z1 = fun y1 { x2 + y2 }
• 44. Lexical Scoping S0 def x1 = z2 5 def z1 = fun y1 { x2 + y2 }
• 45. Lexical Scoping S1 S0 def x1 = z2 5 def z1 = fun y1 { x2 + y2 }
• 46. Lexical Scoping S1 S0 def x1 = z2 5 def z1 = fun y1 { x2 + y2 } z1 x1S0z2
• 47. Lexical Scoping S1 S0 def x1 = z2 5 def z1 = fun y1 { x2 + y2 } S1 y1y2 x2 z1 x1S0z2
• 48. Lexical Scoping S1 S0 Parent def x1 = z2 5 def z1 = fun y1 { x2 + y2 } S1 y1y2 x2 z1 x1S0z2 S’S
• 49. Lexical Scoping S1 S0 Parent def x1 = z2 5 def z1 = fun y1 { x2 + y2 } S1 y1y2 x2 z1 x1S0z2 S’S
• 50. Lexical Scoping S1 S0 Parent def x1 = z2 5 def z1 = fun y1 { x2 + y2 } S1 y1y2 x2 z1 x1S0z2 S’S
• 51. Lexical Scoping S1 S0 Parent def x1 = z2 5 def z1 = fun y1 { x2 + y2 } S1 y1y2 x2 z1 x1S0z2 R S’S
• 52. Lexical Scoping S1 S0 Parent def x1 = z2 5 def z1 = fun y1 { x2 + y2 } S1 y1y2 x2 z1 x1S0z2 R D S’S
• 53. Lexical Scoping S1 S0 Parent def x1 = z2 5 def z1 = fun y1 { x2 + y2 } S1 y1y2 x2 z1 x1S0z2 R S’S
• 54. Lexical Scoping S1 S0 Parent def x1 = z2 5 def z1 = fun y1 { x2 + y2 } S’S S’S P S1 y1y2 x2 z1 x1S0z2 R S’S Parent Step
• 55. Lexical Scoping S1 S0 Parent def x1 = z2 5 def z1 = fun y1 { x2 + y2 } S’S S’S P S1 y1y2 x2 z1 x1S0z2 R P S’S Parent Step
• 56. Lexical Scoping S1 S0 Parent def x1 = z2 5 def z1 = fun y1 { x2 + y2 } S’S S’S P S1 y1y2 x2 z1 x1S0z2 R P D S’S Parent Step
• 57. Imports S0 SB SA module A1 { def z1 = 5 } module B1 { import A2 def x1 = 1 + z2 }
• 58. Imports S0 SB SA module A1 { def z1 = 5 } module B1 { import A2 def x1 = 1 + z2 } A1 SA z1 B1 SB z2 S0 A2 x1
• 59. Imports Associated scope S0 SB SA module A1 { def z1 = 5 } module B1 { import A2 def x1 = 1 + z2 } R2 SR A1 SA z1 B1 SB z2 S0 A2 x1
• 60. Imports Associated scope Import S0 SB SA module A1 { def z1 = 5 } module B1 { import A2 def x1 = 1 + z2 } S R1 R2 SR A1 SA z1 B1 SB z2 S0 A2 x1
• 61. Imports Associated scope Import S0 SB SA module A1 { def z1 = 5 } module B1 { import A2 def x1 = 1 + z2 } S R1 R2 SR A1 SA z1 B1 SB z2 S0 A2 x1
• 62. Imports Associated scope Import S0 SB SA module A1 { def z1 = 5 } module B1 { import A2 def x1 = 1 + z2 } S R1 R2 SR A1 SA z1 B1 SB z2 S0 A2 x1
• 63. Imports Associated scope Import S0 SB SA module A1 { def z1 = 5 } module B1 { import A2 def x1 = 1 + z2 } S R1 R2 SR A1 SA z1 B1 SB z2 S0 A2 x1 R
• 64. Imports Associated scope Import S0 SB SA module A1 { def z1 = 5 } module B1 { import A2 def x1 = 1 + z2 } S R1 R2 SR A1 SA z1 B1 SB z2 S0 A2 x1 R S R1 R2 SR SRS I(R1) Import Step
• 65. Imports Associated scope Import S0 SB SA module A1 { def z1 = 5 } module B1 { import A2 def x1 = 1 + z2 } S R1 R2 SR A1 SA z1 B1 SB z2 S0 A2 x1 R R S R1 R2 SR SRS I(R1) Import Step
• 66. Imports Associated scope Import S0 SB SA module A1 { def z1 = 5 } module B1 { import A2 def x1 = 1 + z2 } S R1 R2 SR A1 SA z1 B1 SB z2 S0 A2 x1 R R P S R1 R2 SR SRS I(R1) Import Step
• 67. Imports Associated scope Import S0 SB SA module A1 { def z1 = 5 } module B1 { import A2 def x1 = 1 + z2 } S R1 R2 SR A1 SA z1 B1 SB z2 S0 A2 x1 R R P D S R1 R2 SR SRS I(R1) Import Step
• 68. Imports Associated scope Import S0 SB SA module A1 { def z1 = 5 } module B1 { import A2 def x1 = 1 + z2 } S R1 R2 SR A1 SA z1 B1 SB z2 S0 A2 x1 I(A2 )R R P D S R1 R2 SR SRS I(R1) Import Step
• 69. Imports Associated scope Import S0 SB SA module A1 { def z1 = 5 } module B1 { import A2 def x1 = 1 + z2 } S R1 R2 SR A1 SA z1 B1 SB z2 S0 A2 x1 I(A2 )R R D P D S R1 R2 SR SRS I(R1) Import Step
• 70. Qualiﬁed Names module N1 { def s1 = 5 } module M1 { def x1 = 1 + N2.s2 } S0
• 71. Qualiﬁed Names module N1 { def s1 = 5 } module M1 { def x1 = 1 + N2.s2 } S0
• 72. Qualiﬁed Names module N1 { def s1 = 5 } module M1 { def x1 = 1 + N2.s2 } S0 N1 SN s2 S0 N2 X1 s1
• 73. Qualiﬁed Names module N1 { def s1 = 5 } module M1 { def x1 = 1 + N2.s2 } S0 N1 SN s2 S0 N2 X1 s1
• 74. Qualiﬁed Names module N1 { def s1 = 5 } module M1 { def x1 = 1 + N2.s2 } S0 N1 SN s2 S0 N2 R D X1 s1
• 75. Qualiﬁed Names module N1 { def s1 = 5 } module M1 { def x1 = 1 + N2.s2 } S0 N1 SN s2 S0 N2 R D R I(N2) D X1 s1
• 76. A Calculus for Name Resolution S R1 R2 SR SRS I(R1) S’S S’S P Sx Sx R xS xS D Reachability of declarations from references through scope graph edges How about ambiguities? References with multiple paths
• 77. Visibility (Disambiguation) (Slides by Pierre Néron)
• 78. A Calculus for Name Resolution S R1 R2 SR SRS I(R1) S’S S’S P Sx Sx R xS xS D I(_).p’ < P.p D < I(_).p’ D < P.p s.p < s.p’ p < p’ Reachability VisibilityWell formed path: R.P*.I(_)*.D
• 79. Ambiguous Resolutions S0def x1 = 5 def x2 = 3 def z1 = x3 + 1
• 80. Ambiguous Resolutions z1 x2 x1S0x3 S0def x1 = 5 def x2 = 3 def z1 = x3 + 1
• 81. Ambiguous Resolutions z1 x2 x1S0x3 RS0def x1 = 5 def x2 = 3 def z1 = x3 + 1
• 82. Ambiguous Resolutions z1 x2 x1S0x3 R DS0def x1 = 5 def x2 = 3 def z1 = x3 + 1
• 83. Ambiguous Resolutions z1 x2 x1S0x3 R D S0def x1 = 5 def x2 = 3 def z1 = x3 + 1
• 84. Ambiguous Resolutions z1 x2 x1S0x3 R D D S0def x1 = 5 def x2 = 3 def z1 = x3 + 1
• 85. Ambiguous Resolutions match t with | A x | B x => … z1 x2 x1S0x3 R D D S0def x1 = 5 def x2 = 3 def z1 = x3 + 1
• 86. Shadowing def x3 = z2 5 7 def z1 = fun x1 { fun y1 { x2 + y2 } }
• 87. Shadowing S0 S1 S2 def x3 = z2 5 7 def z1 = fun x1 { fun y1 { x2 + y2 } }
• 88. Shadowing S0 S1 S2 S1 S2 x1 y1 y2 x2 z1 x3S0z2 def x3 = z2 5 7 def z1 = fun x1 { fun y1 { x2 + y2 } }
• 89. Shadowing S0 S1 S2 S1 S2 x1 y1 y2 x2 z1 x3S0z2 def x3 = z2 5 7 def z1 = fun x1 { fun y1 { x2 + y2 } }
• 90. Shadowing S0 S1 S2 def x3 = z2 5 7 def z1 = fun x1 { fun y1 { x2 + y2 } } S1 S2 x1 y1 y2 x2 z1 x3S0z2 R P P D
• 91. Shadowing S0 S1 S2 def x3 = z2 5 7 def z1 = fun x1 { fun y1 { x2 + y2 } } S1 S2 x1 y1 y2 x2 z1 x3S0z2 D P R R P P D
• 92. Shadowing S0 S1 S2 D < P.p def x3 = z2 5 7 def z1 = fun x1 { fun y1 { x2 + y2 } } S1 S2 x1 y1 y2 x2 z1 x3S0z2 D P R R P P D
• 93. Shadowing S0 S1 S2 D < P.p s.p < s.p’ p < p’ def x3 = z2 5 7 def z1 = fun x1 { fun y1 { x2 + y2 } } S1 S2 x1 y1 y2 x2 z1 x3S0z2 D P R R P P D
• 94. Shadowing S0 S1 S2 D < P.p s.p < s.p’ p < p’ def x3 = z2 5 7 def z1 = fun x1 { fun y1 { x2 + y2 } } S1 S2 x1 y1 y2 x2 z1 x3S0z2 D P R R P P D R.P.D < R.P.P.D
• 95. Imports shadow Parents S0def z3 = 2 module A1 { def z1 = 5 } module B1 { import A2 def x1 = 1 + z2 } SA SB
• 96. Imports shadow Parents A1 SA z1 B1 SB z2 S0 A2 x1 z3 S0def z3 = 2 module A1 { def z1 = 5 } module B1 { import A2 def x1 = 1 + z2 } SA SB
• 97. Imports shadow Parents A1 SA z1 B1 SB z2 S0 A2 x1 z3 S0def z3 = 2 module A1 { def z1 = 5 } module B1 { import A2 def x1 = 1 + z2 } SA SB
• 98. Imports shadow Parents A1 SA z1 B1 SB z2 S0 A2 x1 I(A2 )R D z3 S0def z3 = 2 module A1 { def z1 = 5 } module B1 { import A2 def x1 = 1 + z2 } SA SB
• 99. Imports shadow Parents A1 SA z1 B1 SB z2 S0 A2 x1 I(A2 )R D P D z3 R S0def z3 = 2 module A1 { def z1 = 5 } module B1 { import A2 def x1 = 1 + z2 } SA SB
• 100. Imports shadow Parents I(_).p’ < P.p A1 SA z1 B1 SB z2 S0 A2 x1 I(A2 )R D P D z3 R S0def z3 = 2 module A1 { def z1 = 5 } module B1 { import A2 def x1 = 1 + z2 } SA SB
• 101. Imports shadow Parents I(_).p’ < P.p R.I(A2).D < R.P.D A1 SA z1 B1 SB z2 S0 A2 x1 I(A2 )R D P D z3 R S0def z3 = 2 module A1 { def z1 = 5 } module B1 { import A2 def x1 = 1 + z2 } SA SB
• 102. Imports vs. Includes S0def z3 = 2 module A1 { def z1 = 5 } import A2 def x1 = 1 + z2 SA
• 103. Imports vs. Includes S0def z3 = 2 module A1 { def z1 = 5 } import A2 def x1 = 1 + z2 SA A1 SA z1 z2 S0 A2 x1z3
• 104. Imports vs. Includes S0def z3 = 2 module A1 { def z1 = 5 } import A2 def x1 = 1 + z2 SA A1 SA z1 z2 S0 A2 x1 R z3 D
• 105. Imports vs. Includes S0def z3 = 2 module A1 { def z1 = 5 } import A2 def x1 = 1 + z2 SA A1 SA z1 z2 S0 A2 x1 I(A2 ) R D z3 R D
• 106. Imports vs. Includes S0def z3 = 2 module A1 { def z1 = 5 } import A2 def x1 = 1 + z2 SA A1 SA z1 z2 S0 A2 x1 I(A2 ) R D z3 R D D < I(_).p’
• 107. Imports vs. Includes S0def z3 = 2 module A1 { def z1 = 5 } import A2 def x1 = 1 + z2 SA A1 SA z1 z2 S0 A2 x1 I(A2 ) R D z3 R D D < I(_).p’ R.D < R.I(A2).D
• 108. Imports vs. Includes A1 SA z1 z2 S0 A2 x1 I(A2 ) R D z3 R D D < I(_).p’ R.D < R.I(A2).D S0def z3 = 2 module A1 { def z1 = 5 } include A2 def x1 = 1 + z2 SA
• 109. Imports vs. Includes A1 SA z1 z2 S0 A2 x1 I(A2 ) R D z3 R D D < I(_).p’ R.D < R.I(A2).D S0def z3 = 2 module A1 { def z1 = 5 } include A2 def x1 = 1 + z2 SA X
• 110. Imports vs. Includes A1 SA z1 z2 S0 A2 x1 I(A2 ) R D z3 R D D < I(_).p’ S0def z3 = 2 module A1 { def z1 = 5 } include A2 def x1 = 1 + z2 SA X
• 111. Import Parents def s1 = 5 module N1 { } def x1 = 1 + N2.s2 S0 SN
• 112. Import Parents def s1 = 5 module N1 { } def x1 = 1 + N2.s2 S0 SN
• 113. Import Parents def s1 = 5 module N1 { } def x1 = 1 + N2.s2 S0 SN N1 SN s2 S0 N2 X1 s1
• 114. Import Parents def s1 = 5 module N1 { } def x1 = 1 + N2.s2 S0 SN N1 SN s2 S0 N2 X1 s1 R I(N2) D P
• 115. Import Parents def s1 = 5 module N1 { } def x1 = 1 + N2.s2 S0 SN N1 SN s2 S0 N2 X1 s1 R I(N2) D P
• 116. Import Parents def s1 = 5 module N1 { } def x1 = 1 + N2.s2 S0 SN Well formed path: R.P*.I(_)*.D N1 SN s2 S0 N2 X1 s1 R I(N2) D P
• 117. Transitive vs. Non-Transitive module A1 { def z1 = 5 } module B1 { import A2 } module C1 { import B2 def x1 = 1 + z2 } SA SB SC
• 118. Transitive vs. Non-Transitive module A1 { def z1 = 5 } module B1 { import A2 } module C1 { import B2 def x1 = 1 + z2 } SA SB SC
• 119. Transitive vs. Non-Transitive ?? module A1 { def z1 = 5 } module B1 { import A2 } module C1 { import B2 def x1 = 1 + z2 } SA SB SC
• 120. Transitive vs. Non-Transitive A1 SA z1 B1 SB S0 A2 C1 SCz2 x1 B2 ?? module A1 { def z1 = 5 } module B1 { import A2 } module C1 { import B2 def x1 = 1 + z2 } SA SB SC
• 121. Transitive vs. Non-Transitive A1 SA z1 B1 SB S0 A2 I(A2 ) D C1 SCz2 I(B2 ) R x1 B2 ?? module A1 { def z1 = 5 } module B1 { import A2 } module C1 { import B2 def x1 = 1 + z2 } SA SB SC
• 122. Transitive vs. Non-Transitive With transitive imports, a well formed path is R.P*.I(_)*.D With non-transitive imports, a well formed path is R.P*.I(_)? .D A1 SA z1 B1 SB S0 A2 I(A2 ) D C1 SCz2 I(B2 ) R x1 B2 ?? module A1 { def z1 = 5 } module B1 { import A2 } module C1 { import B2 def x1 = 1 + z2 } SA SB SC
• 123. A Calculus for Name Resolution S R1 R2 SR SRS I(R1) S’S S’S P Sx Sx R xS xS D I(_).p’ < P.p D < I(_).p’ D < P.p s.p < s.p’ p < p’ Reachability VisibilityWell formed path: R.P*.I(_)*.D
• 124. Examples (From TUD-SERG-2015-001. Adapted for this screen)
• 125. Let Bindings 1 2 b2a1 c3 a4 b6 c12a10 b11 c5 b9 a7 c8 def a1 = 0 def b2 = 1 def c3 = 2 letpar a4 = c5 b6 = a7 c8 = b9 in a10+b11+c12 1 b2a1 c3 a4 b6 c12a10 b11 c5 b9 a7 c8 2 def a1 = 0 def b2 = 1 def c3 = 2 letrec a4 = c5 b6 = a7 c8 = b9 in a10+b11+c12 1 b2a1 c3 a4 b6 c12a10 b11 c5 b9 a7 c8 2 4 3 def a1 = 0 def b2 = 1 def c3 = 2 let a4 = c5 b6 = a7 c8 = b9 in a10+b11+c12
• 126. Deﬁnition before Use / Use before Deﬁnition class C1 { int a2 = b3; int b4; void m5 (int a6) { int c7 = a8 + b9; int b10 = b11 + c12; } int c12; } 0 C1 1 2 a2 b4 c12 b3 m5 a6 3 4 c7 b10 b9 a8 b11 c12
• 127. Inheritance class C1 { int f2 = 42; } class D3 extends C4 { int g5 = f6; } class E7 extends D8 { int f9 = g10; int h11 = f12; } 32 1 C4 C1 4D3 E7 D8 f2 g5 f6 f9 g10 f12 h11
• 128. Java Packages package p3; class D4 {} package p1; class C2 {} 1 p3p1 2 p1 p3 3 D4C2
• 129. Java Import package p1; imports r2.*; imports q3.E4; public class C5 {} class D6 {} 4 p1 D6C5 3 2r2 1 p1 E4 q3
• 130. C# Namespaces and Partial Classes namespace N1 { using M2; partial class C3 { int f4; } } namespace N5 { partial class C6 { int m7() { return f8; } } } 1 3 6 4 7 8 C3 C6 N1 N5 f4 m7 N1 N5 C3 C6 f8 2 M2 5
• 131. More Examples? Here the audience proposes binding patterns that they think are not covered by the scope graph framework (and they may be right?)
• 132. Formal Framework (with labeled scope edges)
• 133. Issues with the Reachability Calculus S R1 R2 SR SRS I(R1) S’S S’S P Sx Sx R xS xS D I(_).p’ < P.p D < I(_).p’ D < P.p s.p < s.p’ p < p’ Well formed path: R.P*.I(_)*.D Disambiguating import paths Fixed visibility policy Cyclic Import Paths Multi-import interpretation
• 134. Resolution Calculus with Edge Labels s the resolution relation for graph G. collection JNKG is the multiset deﬁned DG(S)), JR(S)KG = ⇡(RG(S)), and `G p : S 7 ! xD i }) where ⇡(A) is ojecting the identiﬁers from a set A of iven a multiset M, 1M (x) denotes the nes the resolution of a reference to a as a most speciﬁc, well-formed path n through a sequence of edges. A path ng the atomic scope transitions in the of steps: l, S2) is a direct transition from the pe S2. This step records the label of s used. , yR , S) requires the resolution of ref- n with associated scope S to allow a rrent scope and scope S. nds with a declaration step D(xD ) that path is leading to. ion in the graph from reference xR i `G p : xR i 7 ! xD i according to . These rules all implicitly apply to omit to avoid clutter. The calculus n in terms of edges in the scope graph, isible declarations. Here I is the set of vice needed to avoid “out of thin air” Well-formed paths WF(p) , labels(p) 2 E Visibility ordering on paths label(s1) < label(s2) s1 · p1 < s2 · p2 p1 < p2 s · p1 < s · p2 Edges in scope graph S1 l S2 I ` E(l, S2) : S1 ! S2 (E) S1 l yR i yR i /2 I I ` p : yR i 7 ! yD j yD j S2 I ` N(l, yR i , S2) : S1 ! S2 (N) Transitive closure I, S ` [] : A ⇣ A (I) B /2 S I ` s : A ! B I, {B} [ S ` p : B ⇣ C I, S ` s · p : A ⇣ C (T) Reachable declarations I, {S} ` p : S ⇣ S0 WF(p) S0 xD i I ` p · D(xD i ) : S ⇢ xD i (R) Visible declarations I ` p : S ⇢ xD i 8j, p0 (I ` p0 : S ⇢ xD j ) ¬(p0 < p)) I ` p : S 7 ! xD i (V ) Reference resolution xR i S {xR i } [ I ` p : S 7 ! xD j I ` p : xR i 7 ! xD j (X) G, |= !N JN1KG ✓ JN2KG G, |= N1 ⇢ ⇠ N2 (C-SUBNAME) t1 = t2 G, |= t1 ⌘ t2 (C-EQ) Figure 8. Interpretation of resolution and typing constraints Resolution paths s := D(xD i ) | E(l, S) | N(l, xR i , S) p := [] | s | p · p (inductively generated) [] · p = p · [] = p (p1 · p2) · p3 = p1 · (p2 · p3) Well-formed paths WF(p) , labels(p) 2 E Visibility ordering on paths label(s1) < label(s2) s1 · p1 < s2 · p2 p1 < p2 s · p1 < s · p2 Edges in scope graph S1 l S2 I ` E(l, S2) : S1 ! S2 (E) S1 l yR i yR i /2 I I ` p : yR i 7 ! yD j yD j S2 I ` N(l, yR i , S2) : S1 ! S2 (N) Transitive closure I, S ` [] : A ⇣ A (I) B /2 S I ` s : A ! B I, {B} [ S ` p : B ⇣ C I, S ` s · p : A ⇣ C (T) Reachable declarations I, {S} ` p : S ⇣ S0 WF(p) S0 xD i I ` p · D(xD i ) : S ⇢ xD i (R) Visible declarations I ` p : S ⇢ xD i 8j, p0 (I ` p0 : S ⇢ xD j ) ¬(p0 < p)) I ` p : S 7 ! xD i (V ) Reference resolution xR S {xR } [ I ` p : S 7 ! xD C := CG | CTy | CRes | C ^ C | True CG := R S | S D | S l S | D S | S l R CRes := R 7! D | D S | !N | N ⇢ ⇠ N CTy := T ⌘ T | D : T D := | xD i R := xR i S := & | n T := ⌧ | c(T, ..., T) with c 2 CT N := D(S) | R(S) | V(S) Figure 7. Syntax of constraints scope graph resolution calculus (described in Section 3.3). Finally, we apply |= with G set to CG . To lift this approach to constraints with variables, we simply apply a multi-sorted substitution , mapping type variables ⌧ to ground types, declaration variables to ground declarations and scope variables & to ground scopes. Thus, our overall deﬁnition of satisfaction for a program p is: (CG ), |= (CRes ) ^ (CTy ) (⇧)
• 135. Visibility Policies Lexical scope L := {P} E := P⇤ D < P Non-transitive imports L := {P, I} E := P⇤ · I? D < P, D < I, I < P Transitive imports L := {P, TI} E := P⇤ · TI⇤ D < P, D < TI, TI < P Transitive Includes L := {P, Inc} E := P⇤ · Inc⇤ D < P, Inc < P Transitive includes and imports, and non-transitive imports L := {P, Inc, TI, I} E := P⇤ · (Inc | TI)⇤ · I? D < P, D < TI, TI < P, Inc < P, D < I, I < P, Figure 10. Example reachability and visibility policies by instan- tiation of path well-formedness and visibility. 3.4 Parameterization R Envre [ EnvL re [ EnvD re [ Envl re [ I
• 136. Seen Imports hout import tracking. ﬁcity order on paths is e visibility policies can e and speciﬁcity order. module A1 { module A2 { def a3 = ... } } import A4 def b5 = a6 Fig. 11. Self im- port tion the dule far, few ! t A4 ody ? 13 AD 2 :SA2 2 D(SA1 ) AR 4 2 I(Sroot) AR 4 2 R(Sroot) AD 1 :SA1 2 D(Sroot) AR 4 7 ! AD 1 :SA1 Sroot ! SA1 (⇤) Sroot ⇢ AD 2 :SA2 AR 4 2 R(Sroot) Sroot 7 ! AD 2 :SA2 AR 4 7 ! AD 2 :SA2 Fig. 10. Derivation for AR 4 7 ! AD 2 :SA2 in a calculus without import tracking. The complete deﬁnition of well-formed paths and speciﬁcity order on paths is given in Fig. 2. In Section 2.5 we discuss how alternative visibility policies can be deﬁned by just changing the well-formedness predicate and speciﬁcity order. module A1 { module A2 { def a3 = ... } } import A4 def b5 = a6 Seen imports. Consider the example in Fig. 11. Is declaration a3 reachable in the scope of reference a6? This reduces to the question whether the import of A4 can resolve to module A2. Surprisingly, it can, in the calculus as discussed so far, as shown by the derivation in Fig. 10 (which takes a few shortcuts). The conclusion of the derivation is that AR 4 7 ! AD :S . This conclusion is obtained by using the import at A as shown by the derivation in Fig. 10 (which takes shortcuts). The conclusion of the derivation is that AR 4 AD 2 :SA2 . This conclusion is obtained by using the import to conclude at step (*) that Sroot ! SA1 , i.e. that the of module A1 is reachable! In other words, the import is used in its own resolution. Intuitively, this is nonsen To rule out this kind of behavior we extend the cal to keep track of the set of seen imports I using judgem of the form I ` p : xR i 7 ! xD j . We need to extend all ru pass the set I, but only the rules for resolution and im are truly aﬀected: xR i 2 R(S) {xR i } [ I ` p : S 7 ! xD j I ` p : xR i 7 ! xD j yR i 2 I(S1) I I ` p : yR i 7 ! yD j :S2 I ` I(yR i , yD j :S2) : S1 ! S2 With this ﬁnal ingredient, we reach the full calcul
• 137. 4 def b5 = a6 Fig. 11. Self im- port module A1 { module B2 { def x3 = 1 } } module B4 { module A5 { def y6 = 2 } } module C7 { import A8 import B9 def z10 = x11 + y12 } Fig. 12. Anoma- lous resolution . The conclusion of the derivation is that AR 4 7 ! This conclusion is obtained by using the import at A4 de at step (*) that Sroot ! SA1 , i.e. that the body A1 is reachable! In other words, the import of A4 its own resolution. Intuitively, this is nonsensical. e out this kind of behavior we extend the calculus ack of the set of seen imports I using judgements m I ` p : xR i 7 ! xD j . We need to extend all rules to et I, but only the rules for resolution and import aﬀected: xR i 2 R(S) {xR i } [ I ` p : S 7 ! xD j I ` p : xR i 7 ! xD j (X) yR i 2 I(S1) I I ` p : yR i 7 ! yD j :S2 I ` I(yR i , yD j :S2) : S1 ! S2 (I) this ﬁnal ingredient, we reach the full calculus in is not hard to see that the resolution relation is ded. The only recursive invocation (via the I rule) ictly larger set I of seen imports (via the X rule); since the set R(G) Anomaly 4 def b5 = a6 Fig. 11. Self im- port module A1 { module B2 { def x3 = 1 } } module B4 { module A5 { def y6 = 2 } } module C7 { import A8 import B9 def z10 = x11 + y12 } Fig. 12. Anoma- lous resolution R 4 7 ! at A4 body of A4 sical. culus ments les to mport (X) (I) us in on is rule) rule); since the set R(G) 2 1 3 1 3 2
• 138. Resolution Algorithm < P P, nstan- R[I](xR ) := let (r, s) = EnvE [{xR } [ I, ;](Sc(xR ))} in ( U if r = P and {xD |xD 2 s} = ; {xD |xD 2 s} Envre [I, S](S) := ( (T, ;) if S 2 S or re = ? Env L[{D} re [I, S](S) EnvL re [I, S](S) := [ l2Max(L) ⇣ Env {l0 2L|l0 <l} re [I, S](S) Envl re [I, S](S) ⌘ EnvD re [I, S](S) := ( (T, ;) if [] /2 re (T, D(S)) Envl re [I, S](S) := 8 >< >: (P, ;) if S I l contains a variable or ISl[I](S) = U S S02 ⇣ ISl[I](S)[S I l ⌘ Env(l 1re)[I, {S} [ S](S0) ISl [I](S) := ( U if 9yR 2 (S B l I) s.t. R[I](yR ) = U {S0 | yR 2 (S B l I) ^ yD 2 R[I](yR ) ^ yD S0}
• 139. Alpha Equivalence
• 140. Language-independent 𝜶-equivalence Program similarity Equivalence deﬁne ↵-equivalence using scope graphs. Except for the leaves rep iﬁers, two ↵-equivalent programs must have the same abstract write P ' P’ (pronounced “P and P’ are similar”) when the AS re equal up to identiﬁers. To compare two programs we ﬁrst c T structures; if these are equal then we compare how identiﬁers programs. Since two potentially ↵-equivalent programs are simi s occur at the same positions. In order to compare the identiﬁers’ eﬁne equivalence classes of positions of identiﬁers in a program: p me equivalence class are declarations of or reference to the same ract position ¯x identiﬁes the equivalence class corresponding to x. n a program P, we write P for the set of positions correspon s and declarations and PX for P extended with the artiﬁcial p We deﬁne the P ⇠ equivalence relation between elements of PX if have same AST ignoring identiﬁer names
• 141. Language-independent 𝜶-equivalence Position equivalence e same equivalence class are declarations of or reference to the same enti abstract position ¯x identiﬁes the equivalence class corresponding to the fr ble x. Given a program P, we write P for the set of positions corresponding ences and declarations and PX for P extended with the artiﬁcial positio ¯x). We deﬁne the P ⇠ equivalence relation between elements of PX as t xive symmetric and transitive closure of the resolution relation. nition 7 (Position equivalence). ` p : r i x 7 ! di0 x i P ⇠ i0 i0 P ⇠ i i P ⇠ i0 i P ⇠ i0 i0 P ⇠ i00 i P ⇠ i00 i P ⇠ i his equivalence relation, the class containing the abstract free variable d ion can not contain any other declaration. So the references in a particu are either all free or all bound. mma 6 (Free variable class). The equivalence class of a free variable do contain any other declaration, i.e. 8 di x s.t. i P ⇠ ¯x =) i = ¯x xi xi' Program similarity Equivalence deﬁne ↵-equivalence using scope graphs. Except for the leaves rep iﬁers, two ↵-equivalent programs must have the same abstract write P ' P’ (pronounced “P and P’ are similar”) when the AS re equal up to identiﬁers. To compare two programs we ﬁrst c T structures; if these are equal then we compare how identiﬁers programs. Since two potentially ↵-equivalent programs are simi s occur at the same positions. In order to compare the identiﬁers’ eﬁne equivalence classes of positions of identiﬁers in a program: p me equivalence class are declarations of or reference to the same ract position ¯x identiﬁes the equivalence class corresponding to x. n a program P, we write P for the set of positions correspon s and declarations and PX for P extended with the artiﬁcial p We deﬁne the P ⇠ equivalence relation between elements of PX if have same AST ignoring identiﬁer names
• 142. Language-independent 𝜶-equivalence Position equivalence e same equivalence class are declarations of or reference to the same enti abstract position ¯x identiﬁes the equivalence class corresponding to the fr ble x. Given a program P, we write P for the set of positions corresponding ences and declarations and PX for P extended with the artiﬁcial positio ¯x). We deﬁne the P ⇠ equivalence relation between elements of PX as t xive symmetric and transitive closure of the resolution relation. nition 7 (Position equivalence). ` p : r i x 7 ! di0 x i P ⇠ i0 i0 P ⇠ i i P ⇠ i0 i P ⇠ i0 i0 P ⇠ i00 i P ⇠ i00 i P ⇠ i his equivalence relation, the class containing the abstract free variable d ion can not contain any other declaration. So the references in a particu are either all free or all bound. mma 6 (Free variable class). The equivalence class of a free variable do contain any other declaration, i.e. 8 di x s.t. i P ⇠ ¯x =) i = ¯x xi xi' Program similarity Equivalence deﬁne ↵-equivalence using scope graphs. Except for the leaves rep iﬁers, two ↵-equivalent programs must have the same abstract write P ' P’ (pronounced “P and P’ are similar”) when the AS re equal up to identiﬁers. To compare two programs we ﬁrst c T structures; if these are equal then we compare how identiﬁers programs. Since two potentially ↵-equivalent programs are simi s occur at the same positions. In order to compare the identiﬁers’ eﬁne equivalence classes of positions of identiﬁers in a program: p me equivalence class are declarations of or reference to the same ract position ¯x identiﬁes the equivalence class corresponding to x. n a program P, we write P for the set of positions correspon s and declarations and PX for P extended with the artiﬁcial p We deﬁne the P ⇠ equivalence relation between elements of PX if have same AST ignoring identiﬁer names ed proof is in appendix A.5, we ﬁrst prove: r i x 7 ! d ¯x x ) =) 8 p di0 x , p ` r i x 7 ! di0 x =) i0 = ¯x ^ p = eed by induction on the equivalence relation. ce classes deﬁned by this relation contain references to me entity. Given this relation, we can state that two p f the identiﬁers at identical positions refer to the same e he same equivalence class: (↵-equivalence). Two programs P1 and P2 are ↵-equi 2) when they are similar and have the same ⇠-equivalen P1 ↵ ⇡ P2 , P1 ' P2 ^ 8 e e0 , e P1 ⇠ e0 , e P2 ⇠ e0 is an equivalence relation since ' and , are equivalenc(with some further details about free variables) Alpha equivalence
• 143. Preserving ambiguity 25 module A1 { def x2 := 1 } module B3 { def x4 := 2 } module C5 { import A6 B7 ; def y8 := x9 } module D10 { import A11 ; def y12 := x13 } module E14 { import B15 ; def y16 := x17 } P1 module AA1 { def z2 := 1 } module BB3 { def z4 := 2 } module C5 { import AA6 BB7 ; def s8 := z9 } module D10 { import AA11 ; def u12 := z13 } module E14 { import BB15 ; def v16 := z17 } P2 module A1 { def z2 := 1 } module B3 { def x4 := 2 } module C5 { import A6 B7 ; def y8 := z9 } module D10 { import A11 ; def y12 := z13 } module E14 { import B15 ; def y16 := x17 } P3 Fig. 23. ↵-equivalence and duplicate declarationP1 Lemma 6 (Free variable class). The equivalence class of a fr ot contain any other declaration, i.e. 8 di x s.t. i P ⇠ ¯x =) i = ¯x Proof. Detailed proof is in appendix A.5, we ﬁrst prove: 8 r i x, (` > : r i x 7 ! d ¯x x ) =) 8 p di0 x , p ` r i x 7 ! di0 x =) i0 = ¯x nd then proceed by induction on the equivalence relation. The equivalence classes deﬁned by this relation contain reference ions of the same entity. Given this relation, we can state that t ↵-equivalent if the identiﬁers at identical positions refer to the s s belong to the same equivalence class: Deﬁnition 8 (↵-equivalence). Two programs P1 and P2 are ↵ oted P1 ↵ ⇡ P2) when they are similar and have the same ⇠-equi P1 ↵ ⇡ P2 , P1 ' P2 ^ 8 e e0 , e P1 ⇠ e0 , e P2 ⇠ e0P2 P2 Lemma 6 (Free variable class). The e not contain any other declaration, i.e. 8 d Proof. Detailed proof is in appendix A.5, 8 r i x, (` > : r i x 7 ! d ¯x x ) =) 8 p di0 x , p ` and then proceed by induction on the equ The equivalence classes deﬁned by this rel tions of the same entity. Given this relatio ↵-equivalent if the identiﬁers at identical is belong to the same equivalence class: Deﬁnition 8 (↵-equivalence). Two pro noted P1 ↵ ⇡ P2) when they are similar and P1 ↵ ⇡ P2 , P1 ' P2 ^ 8P3
• 144. Names and Types
• 145. Types from Declaration def x : int = 6 def x : int = 6 def f = fun (y : int) { x + y } Static type-checking (or inference) is one obvious client for name resolution In many cases, we can perform resolution before doing type analysis
• 146. Types from Declaration def x : int = 6 def f = fun (y : int) { x + y } def f = fun (y : int) { x + y } def x : int = 6 def f = fun (y : int) { x + y } Static type-checking (or inference) is one obvious client for name resolution In many cases, we can perform resolution before doing type analysis
• 147. Types from Declaration def x : int = 6 def f = fun (y : int) { x + y } def x : int = 6 def f = fun (y : int) { x + y } Static type-checking (or inference) is one obvious client for name resolution In many cases, we can perform resolution before doing type analysis
• 148. Type-Dependent Name Resolution But sometimes we need types before we can do name resolution record A1 { x1 : int } record B1 { a1 : A2 ; x2 : bool} def z1 : B2 = ... def y1 = z2.x3 def y2 = z3.a2.x4
• 149. Type-Dependent Name Resolution But sometimes we need types before we can do name resolution record A1 { x1 : int } record B1 { a1 : A2 ; x2 : bool} def z1 : B2 = ... def y1 = z2.x3 def y2 = z3.a2.x4
• 150. Type-Dependent Name Resolution But sometimes we need types before we can do name resolution record A1 { x1 : int } record B1 { a1 : A2 ; x2 : bool} def z1 : B2 = ... def y1 = z2.x3 def y2 = z3.a2.x4
• 151. Type-Dependent Name Resolution But sometimes we need types before we can do name resolution record A1 { x1 : int } record B1 { a1 : A2 ; x2 : bool} def z1 : B2 = ... def y1 = z2.x3 def y2 = z3.a2.x4
• 152. Type-Dependent Name Resolution But sometimes we need types before we can do name resolution record A1 { x1 : int } record B1 { a1 : A2 ; x2 : bool} def z1 : B2 = ... def y1 = z2.x3 def y2 = z3.a2.x4
• 153. Type-Dependent Name Resolution But sometimes we need types before we can do name resolution record A1 { x1 : int } record B1 { a1 : A2 ; x2 : bool} def z1 : B2 = ... def y1 = z2.x3 def y2 = z3.a2.x4
• 154. Type-Dependent Name Resolution But sometimes we need types before we can do name resolution record A1 { x1 : int } record B1 { a1 : A2 ; x2 : bool} def z1 : B2 = ... def y1 = z2.x3 def y2 = z3.a2.x4
• 155. Type-Dependent Name Resolution But sometimes we need types before we can do name resolution record A1 { x1 : int } record B1 { a1 : A2 ; x2 : bool} def z1 : B2 = ... def y1 = z2.x3 def y2 = z3.a2.x4
• 156. Type-Dependent Name Resolution But sometimes we need types before we can do name resolution record A1 { x1 : int } record B1 { a1 : A2 ; x2 : bool} def z1 : B2 = ... def y1 = z2.x3 def y2 = z3.a2.x4
• 157. Type-Dependent Name Resolution But sometimes we need types before we can do name resolution record A1 { x1 : int } record B1 { a1 : A2 ; x2 : bool} def z1 : B2 = ... def y1 = z2.x3 def y2 = z3.a2.x4
• 158. Type-Dependent Name Resolution But sometimes we need types before we can do name resolution record A1 { x1 : int } record B1 { a1 : A2 ; x2 : bool} def z1 : B2 = ... def y1 = z2.x3 def y2 = z3.a2.x4 Our approach: interleave partial name resolution with type resolution (also using constraints) See PEPM 2016 paper / talk
• 159. Constraint Language
• 160. Constraint Language C := CG | CTy | CRes | C ^ C | True CG := R S | S D | S l S | D S | S l R CRes := R 7! D | D S | !N | N ⇢ ⇠ N CTy := T ⌘ T | D : T D := | xD i R := xR i S := & | n T := ⌧ | c(T, ..., T) with c 2 CT N := D(S) | R(S) | V(S) Figure 7. Syntax of constraints scope graph resolution calculus (described in Section 3.3). Finally, we apply |= with G set to CG .
• 161. LMR: Language with Modules and Records prog = decl⇤ decl = module id {decl⇤ } | import id | def bind | record id {fdecl⇤ } fdecl = id : ty ty = Int | Bool | id | ty ! ty exp = int | true | false | id | exp exp | if exp then exp else exp | fun ( id : ty ) {exp} | exp exp | letrec tbind in exp | new id {fbind⇤ } | with exp do exp | exp . id bind = id = exp | tbind tbind = id : ty = exp fbind = id = exp Figure 5. Syntax of LMR. [[ds]]prog := [[module xi {ds}]]decl s := [[import xi]]decl s := [[def b]]decl s := [[record xi {fs}]]decl s := [[xi = e]]bind s := [[xi : t = e]]bind s := [[xi:t]]fdecl sr,sd := [[Int]]ty s,t := [[Bool]]ty s,t := [[t1 ! t2]]ty s,t := [[xi]]ty s,t := [[fun (xi:t1){e}]]exp s,t :=
• 162. Constraints for Declarations p [[ds]]prog := !D(s) ^ [[ds]]decl⇤ s [[module xi {ds}]]decl s := s xD i ^ xD i s0 ^ s0 P s ^ !D(s0) ^ [[ds]]decl⇤ s0 [[import xi]]decl s := xR i s ^ s I xR i [[def b]]decl s := [[b]]bind s [[record xi {fs}]]decl s := s xD i ^ xD i s0 ^ s0 P s ^ !D(s0) ^ [[fs]]fdecl⇤ s,s0 [[xi = e]]bind s := s xD i ^ xD i : ⌧ ^ [[e]]exp s,⌧ [[xi : t = e]]bind s := s xD i ^ xD i : ⌧ ^ [[t]]ty s,⌧ ^ [[e]]exp s,⌧ [[xi:t]]fdecl sr,sd := sd xD i ^ xD i : ⌧ ^ [[t]]ty sr,⌧ [[Int]]ty s,t := t ⌘ Int [[Bool]]ty s,t := t ⌘ Bool [[t1 ! t2]]ty s,t := t ⌘ Fun[⌧1,⌧2] ^ [[t1]]ty s,⌧1 ^ [[t2]]ty s,⌧2 [[xi]]ty := t ⌘ Rec( ) ^ xR s ^ xR 7!
• 163. Constraints for Expressions LMR. be the algo- R’s concrete deﬁned by a by syntactic ach function nt and possi- parameters, sibly involv- ables or new s are deﬁned ach possible gory. For ex- rules, and is e s in which the expres- ected type t the notation ms of syntac- result of ap- and return- esulting con- pty sequence. 1 2 s,t 1 2 1 s,⌧1 2 s,⌧2 [[xi]]ty s,t := t ⌘ Rec( ) ^ xR i s ^ xR i 7! [[fun (xi:t1){e}]]exp s,t := t ⌘ Fun[⌧1,⌧2] ^ s0 P s ^ !D(s0) ^ s0 xD i ^ xD i : ⌧1 ^ [[t1]]ty s,⌧1 ^ [[e]]exp s0,⌧2 [[letrec bs in e]]exp s,t := s0 P s ^ !D(s0) ^ [[bs]]bind s0 ^ [[e]]exp s0,t [[n]]exp s,t := t ⌘ Int [[true]]exp s,t := t ⌘ Bool [[false]]exp s,t := t ⌘ Bool [[e1 e2]]exp s,t := t ⌘ t3 ^ ⌧1 ⌘ t1 ^ ⌧2 ⌘ t2 ^ [[e1]]exp s,⌧1 ^ [[e2]]exp s,⌧2 (where has type t1 ⇥ t2 ! t3) [[if e1 then e2 else e3]]exp s,t := ⌧1 ⌘ Bool ^ [[e1]]exp s,⌧1 ^ [[e2]]exp s,t ^ [[e3]]exp s,t [[xi]]exp s,t := xR i s ^ xR i 7! ^ : t [[e1 e2]]exp s,t := ⌧ ⌘ Fun[⌧1,t] ^ [[e1]]exp s,⌧ ^ [[e2]]exp s,⌧1 [[e.xi]]exp s,t := [[e]]exp s,⌧ ^ ⌧ ⌘ Rec( ) ^ & ^ s0 I & ^ [[xi]]exp s0,t [[with e1 do e2]]exp s,t := [[e1]]exp s,⌧ ^ ⌧ ⌘ Rec( ) ^ & ^ s0 P s ^ s0 I & ^ [[e2]]exp s0,t [[new xi {bs}]]exp s,t := xR i s ^ xR i 7! ^ s0 I xR i ^ [[bs]]fbind⇤ s,s0 ^ V(s0) ⇡ R(s0) ^ t ⌘ Rec( ) [[xi = e]]fbind s,s0 := xR i s0 ^ xR i 7! ^ : ⌧ ^ [[e]]exp s,⌧
• 164. Closing
• 165. Summary: A Theory of Name Resolution • Representation: Scope Graphs - Standardized representation for lexical scoping structure of programs - Path in scope graph relates reference to declaration - Basis for syntactic and semantic operations • Formalism: Name Binding Constraints - References + Declarations + Scopes + Reachability + Visibility - Language-speciﬁc rules map AST to constraints • Language-Independent Interpretation - Resolution calculus: correctness of path with respect to scope graph - Name resolution algorithm - Alpha equivalence - Mapping from graph to tree (to text) - Refactorings - And many other applications
• 166. Validation • We have modeled a large set of example binding patterns - deﬁnition before use - different let binding ﬂavors - recursive modules - imports and includes - qualiﬁed names - class inheritance - partial classes • Next goal: fully model some real languages - Java - ML
• 167. Future Work • Scope graph semantics for binding speciﬁcation languages - starting with NaBL - or rather: a redesign of NaBL based on scope graphs • Resolution-sensitive program transformations - renaming, refactoring, substitution, … • Dynamic analogs to static scope graphs - how does scope graph relate to memory at run-time? • Supporting mechanized language meta-theory - relating static and dynamic bindings