KEMBAR78
Declarative Name Binding and Scope Rules | PDF
Language-Parametric Name
         Resolution Based on
       Declarative Name Binding
           and Scope Rules

Gabriël Konat, Lennart Kats, Guido Wachsmuth, Eelco Visser
Language-Parametric Name
         Resolution Based on
       Declarative Name Binding
           and Scope Rules

Gabriël Konat, Lennart Kats, Guido Wachsmuth, Eelco Visser
Name Binding and Scope



function power(x: Int, n: Int): Int {
  if(n == 0) {
    return 1;
  } else {
    return x * power(x, n - 1);
  }
}
Fundamentalist Domain-Specific
       Programming
Populist Domain-Specific Programming

Internal DSL

Programmatic encoding

Limited abstraction from implementation strategy

Bound to specific host language

Captures implementation, not understanding
Context-free Grammars

"return" Exp ";"                                    -> Stm {"Return"}
Type ID ";"                                         -> Stm {"VarDef"}
Type ID "=" Exp ";"                                 -> Stm {"VarDef"}
ID "=" Exp ";"	 	 	 	 	 	                           -> Stm {"Assign"}
"if" "(" Exp ")" Block                              -> Stm {"If"}
"if" "(" Exp ")" Block "else" Block                 -> Stm {"IfElse"}
"for" "(" Type ID "=" Exp ";" Exp ";" Stm ")" Block -> Stm {"For"}
"{" Stm* "}"                                        -> Block {"Block"}
Block                                               -> Stm



                            for (int i = i; i <10 ; i = i + 1;) {
                              int i;
                              i = i + 1;
                            }



 Pure and declarative syntax definition: paradise lost and regained. Lennart C. L. Kats, Eelco Visser, Guido Wachsmuth.
 Onward 2010: 918-932
Fundamentalist Domain-Specific Programming


    External DSL

    Abstraction from implementation strategy

    Not bound to specific host language

    Captures understanding
    (and room for many implementations)
Name Binding and Scope
Name Binding and Scope


static checking

editor services

transformation

  refactoring

code generation
Reference Resolution (Navigation)
Code Completion
Classical Approaches
Type Systems




Source: Luca Cardelli. Type Systems. In Handbook of Computer Science and Engineering,
Chapter 103. CRC Press, 1997.
Modular Structural Operational Semantics




Source: Peter Mosses. Modular SOS: Differences from SOS.
First APPSEM-II Workshop, Nottingham, March 2003
Reference Attribute Grammars
Source: Görel Hedin


                                                                                   eq	
  Program.getBlock().lookup(String	
  id)	
  =	
  
                     Program                                                       	
  	
  null;
                  eq	
  lookup	
  =	
  …	
  


                                                                                   syn	
  Block.localLookup(String	
  id)	
  {
                                                                                   	
  	
  for	
  (Decl	
  d	
  :	
  getDecls())	
  {
                                           lookup(String)                          	
  	
  	
  	
  if	
  (d.getID().equals(id))
                        Block             localLookup(String)                      	
  	
  	
  	
  	
  	
  return	
  d;
                                                                                   	
  	
  }
               eq	
  lookup	
  =	
  …	
  
                                                                                   	
  	
  return	
  null;
                                                                                   }


  Decl                                                            lookup(String)
                                            Block            localLookup(String)
                                     eq	
  lookup	
  =	
  …	
  
                                                                                   eq	
  Block.getChild(int	
  i).lookup(String	
  id)	
  {
                                                                                   	
  	
  Decl	
  d	
  =	
  localLookup(id);
                                                                                   	
  	
  if	
  (d	
  !=	
  null)	
  return	
  d;
                                                                                   	
  	
  return	
  lookup(id);
           Decl                                                                    }

                         lookup(String)
                                                        Use                        syn	
  Decl	
  Use.decl	
  =	
  lookup(getID());
                                               decl
                                                                                   inh	
  Decl	
  Use.lookup(String);
Rewriting Strategies with Dynamic Rules
    rename-top = alltd(rename)

    rename :
      |[ var x : srt ]| -> |[ var y : srt ]|
      where y := <add-naming-key(|srt)> x

    rename :
      |[ define page x (farg1*) { elem1* } ]| ->
      |[ define page x (farg2*) { elem2* } ]|
      where {| Rename
             : farg2* := <map(rename-page-arg)> farg1*
             ; elem2* := <rename-top> elem1*
             |}

    rename = Rename

    add-naming-key(|srt) : x -> y
      where y := x{<newname> x}
          ; rules (
              Rename : Var(x) -> Var(y)
              TypeOf : y -> srt
            )
What is the Problem?
What is the Problem?

Mental model:

Name binding is defined in terms of
programmatic encoding of name resolution

Rules encoded in many language operations

Abstractions try to reduce overhead
of the programmatic encoding
Name Binding in Xtext

grammar DomainModel with Terminals

Domainmodel :
  elements += Type*
;
Type:
  DataType | Entity
;
DataType:
  'datatype' name = ID
;
Entity:
  'entity' name = ID ('extends' superType = [Entity])? '{'
     features += Feature*
  '}'
;
Feature:
  many?='many'? name = ID ':' type = [Type]
;
Name Binding Language
Definitions and Reference


                           class C {
Class(_, c, _, _):         }
  defines Class c
                           class D {
ClassType(c) :               C x;
  refers to Class c        }

Base(c) :                  class E : D {
  refers to Class c          C x;
                           }
Design Choice: Grammar Annotations


"class" Type@=ID "{" ClassBodyDecl* "}" -> Definition {"Class"}

Type@ID                                   -> Type {"ClassType"}




                      Class(_, c, _) :
                        defines Class c

                      ClassType(c) :
                        refers to Class c
Unique and Non-Unique Definitions

                                 class D {
                                   C1 x;
Class(NonPartial(), c, _, _) :   }
  defines unique Class c         class C1 {
                                   D d;
Class(Partial(), c, _, _) :      }
  defines non-unique Class c     class C2: C1 {
                                   Int i;
Base(c) :                        }
  refers to Class c              partial class C3: C2 {
                                   Int j;
ClassType(c) :                   }
  refers to Class c              partial class C3 {
                                   Int k;
                                 }
Namespaces
namespaces
  Class Method Field Variable

Class(NonPartial(), c, _, _):
  defines unique Class c

Field(_, f) :
                                    class x {
  defines unique Field f
                                      int x;
                                      void x() {
Method(_, m, _, _):
                                        int x; x = x + 1;
  defines unique Method m
                                      }
Call(m, _) :
                                    }
  refers to Method m

VarDef(_, v):
  defines unique Variable v
VarRef(x):
   refers to Variable x
   otherwise refers to Field x
Scope

                                       class C {
Class(NonPartial(), c, _, _):            int y;
  defines unique Class c                 void m() {
  scopes Field, Method                     int x;
                                           x = y + 1;
Class(Partial(), c, _, _):               }
  defines non-unique Class c           }
  scopes Field, Method
                                       class D {
Method(_, m, _, _):                      void m() {
  defines unique Method m                  int x;
  scopes Variable                          int y;
                                           { int x; x = y + 1; }
Block(_):                                  x = y + 1;
  scopes Variable                        }
                                       }
C# Namespaces are Scopes




                            namespace N {
                              class N {}
Namespace(n, _):
                              namespace N {
  defines Namespace n
                                class N {}
  scopes Namespace, Class
                              }
                            }
Imports



                                        using N;
Using(qn):
  imports Class from Namespace ns       namespace M {
  where qn refers to Namespace ns         class C { int f; }
                                        }
Base(c):
  imports   Field                       namespace O {
     from   Class c {transitive}          class E: M.C {
  imports   Method                          void m() {}
     from   Class c {transitive}          }
                                          class F:E { }
                                        }
Definition Context




                            class C {
Foreach(t, v, exp, body):     void m(int[] x) {
  defines Variable v            foreach (int x in x)
       of type t                  WriteLine(x);
       in body                }
                            }
Interaction with Type System (1)


                                  class C {
                                    int i;
                                  }

FieldAccess(e, f):                class D {
  refers to Field f in c            C c;
  where e has type ClassType(c)     int i;
                                    void init() {
                                      i = c.i;
                                    }
                                  }
Interaction with Type System (2)


                                  class C {
                                    int i;
                                    int get() { return i; }
Method(t, m, ps, _) :
                                  }
  defines Method m of type t

                                  class D {
MethodCall(e, m, _):
                                    C c;
  refers to Method m
                                    int i;
      of type t in c
                                    void init() {
  where e has type ClassType(c)
                                      i = c.get();
                                    }
                                  }
Interaction with Type System (3)

Method(t, m, ps, _) :             class C {
  defines unique Method m           void m() {}
       of type (ts, t)              void m(int x) {}
  where ps has type ts              void m(bool x) {}
                                    void m(int x, int y) {}
Param(t, p):                        void m(bool x, bool y) {}
  defines unique Variable p         void x() {
       of type t                      m();
                                      m(42);
MethodCall(e, m, es):                 m(true);
  refers to Method m                  m(21, 21);
      of type (ts, t) in c            m(true, false);
  where e has type ClassType(c)     }
  where es has type ts            }
Name Binding
                               class
 defines                    partial class
                               type
  refers                    inheritance

namespaces
                            namespace
                              using
  scopes
                             method
                               field
 imports                     variable
                            parameter
                              block
Name Binding Language in Spoofax (*)
Name Binding Language in Spoofax (*)


         derivation of editor services
                          checking
                      code completion
                    reference resolution


                   multi-file analysis

                  parallel evaluation

              incremental evaluation


      (*) alpha; NBL is compiled to Stratego implementation of
      name resolution algorithm (ask me for pointers)
Outlook

Language definition = CFG + NBD + TS + DS

           Single source for

        Language reference manual

      Efficient (incremental) compiler

      Execution engine (interpreter)

   Integrated development environment

Declarative Name Binding and Scope Rules

  • 1.
    Language-Parametric Name Resolution Based on Declarative Name Binding and Scope Rules Gabriël Konat, Lennart Kats, Guido Wachsmuth, Eelco Visser
  • 2.
    Language-Parametric Name Resolution Based on Declarative Name Binding and Scope Rules Gabriël Konat, Lennart Kats, Guido Wachsmuth, Eelco Visser
  • 3.
    Name Binding andScope function power(x: Int, n: Int): Int { if(n == 0) { return 1; } else { return x * power(x, n - 1); } }
  • 4.
  • 5.
    Populist Domain-Specific Programming InternalDSL Programmatic encoding Limited abstraction from implementation strategy Bound to specific host language Captures implementation, not understanding
  • 6.
    Context-free Grammars "return" Exp";" -> Stm {"Return"} Type ID ";" -> Stm {"VarDef"} Type ID "=" Exp ";" -> Stm {"VarDef"} ID "=" Exp ";" -> Stm {"Assign"} "if" "(" Exp ")" Block -> Stm {"If"} "if" "(" Exp ")" Block "else" Block -> Stm {"IfElse"} "for" "(" Type ID "=" Exp ";" Exp ";" Stm ")" Block -> Stm {"For"} "{" Stm* "}" -> Block {"Block"} Block -> Stm for (int i = i; i <10 ; i = i + 1;) { int i; i = i + 1; } Pure and declarative syntax definition: paradise lost and regained. Lennart C. L. Kats, Eelco Visser, Guido Wachsmuth. Onward 2010: 918-932
  • 7.
    Fundamentalist Domain-Specific Programming External DSL Abstraction from implementation strategy Not bound to specific host language Captures understanding (and room for many implementations)
  • 8.
  • 9.
    Name Binding andScope static checking editor services transformation refactoring code generation
  • 10.
  • 11.
  • 12.
  • 13.
    Type Systems Source: LucaCardelli. Type Systems. In Handbook of Computer Science and Engineering, Chapter 103. CRC Press, 1997.
  • 14.
    Modular Structural OperationalSemantics Source: Peter Mosses. Modular SOS: Differences from SOS. First APPSEM-II Workshop, Nottingham, March 2003
  • 15.
    Reference Attribute Grammars Source:Görel Hedin eq  Program.getBlock().lookup(String  id)  =   Program    null; eq  lookup  =  …   syn  Block.localLookup(String  id)  {    for  (Decl  d  :  getDecls())  { lookup(String)        if  (d.getID().equals(id)) Block localLookup(String)            return  d;    } eq  lookup  =  …      return  null; } Decl lookup(String) Block localLookup(String) eq  lookup  =  …   eq  Block.getChild(int  i).lookup(String  id)  {    Decl  d  =  localLookup(id);    if  (d  !=  null)  return  d;    return  lookup(id); Decl } lookup(String) Use syn  Decl  Use.decl  =  lookup(getID()); decl inh  Decl  Use.lookup(String);
  • 16.
    Rewriting Strategies withDynamic Rules rename-top = alltd(rename) rename : |[ var x : srt ]| -> |[ var y : srt ]| where y := <add-naming-key(|srt)> x rename : |[ define page x (farg1*) { elem1* } ]| -> |[ define page x (farg2*) { elem2* } ]| where {| Rename : farg2* := <map(rename-page-arg)> farg1* ; elem2* := <rename-top> elem1* |} rename = Rename add-naming-key(|srt) : x -> y where y := x{<newname> x} ; rules ( Rename : Var(x) -> Var(y) TypeOf : y -> srt )
  • 17.
    What is theProblem?
  • 18.
    What is theProblem? Mental model: Name binding is defined in terms of programmatic encoding of name resolution Rules encoded in many language operations Abstractions try to reduce overhead of the programmatic encoding
  • 19.
    Name Binding inXtext grammar DomainModel with Terminals Domainmodel :   elements += Type* ; Type:   DataType | Entity ; DataType:   'datatype' name = ID ; Entity:   'entity' name = ID ('extends' superType = [Entity])? '{'      features += Feature*   '}' ; Feature:   many?='many'? name = ID ':' type = [Type] ;
  • 20.
  • 21.
    Definitions and Reference class C { Class(_, c, _, _): } defines Class c class D { ClassType(c) : C x; refers to Class c } Base(c) : class E : D { refers to Class c C x; }
  • 22.
    Design Choice: GrammarAnnotations "class" Type@=ID "{" ClassBodyDecl* "}" -> Definition {"Class"} Type@ID -> Type {"ClassType"} Class(_, c, _) : defines Class c ClassType(c) : refers to Class c
  • 23.
    Unique and Non-UniqueDefinitions class D { C1 x; Class(NonPartial(), c, _, _) : } defines unique Class c class C1 { D d; Class(Partial(), c, _, _) : } defines non-unique Class c class C2: C1 { Int i; Base(c) : } refers to Class c partial class C3: C2 { Int j; ClassType(c) : } refers to Class c partial class C3 { Int k; }
  • 24.
    Namespaces namespaces ClassMethod Field Variable Class(NonPartial(), c, _, _): defines unique Class c Field(_, f) : class x { defines unique Field f int x; void x() { Method(_, m, _, _): int x; x = x + 1; defines unique Method m } Call(m, _) : } refers to Method m VarDef(_, v): defines unique Variable v VarRef(x): refers to Variable x otherwise refers to Field x
  • 25.
    Scope class C { Class(NonPartial(), c, _, _): int y; defines unique Class c void m() { scopes Field, Method int x; x = y + 1; Class(Partial(), c, _, _): } defines non-unique Class c } scopes Field, Method class D { Method(_, m, _, _): void m() { defines unique Method m int x; scopes Variable int y; { int x; x = y + 1; } Block(_): x = y + 1; scopes Variable } }
  • 26.
    C# Namespaces areScopes namespace N { class N {} Namespace(n, _): namespace N { defines Namespace n class N {} scopes Namespace, Class } }
  • 27.
    Imports using N; Using(qn): imports Class from Namespace ns namespace M { where qn refers to Namespace ns class C { int f; } } Base(c): imports Field namespace O { from Class c {transitive} class E: M.C { imports Method void m() {} from Class c {transitive} } class F:E { } }
  • 28.
    Definition Context class C { Foreach(t, v, exp, body): void m(int[] x) { defines Variable v foreach (int x in x) of type t WriteLine(x); in body } }
  • 29.
    Interaction with TypeSystem (1) class C { int i; } FieldAccess(e, f): class D { refers to Field f in c C c; where e has type ClassType(c) int i; void init() { i = c.i; } }
  • 30.
    Interaction with TypeSystem (2) class C { int i; int get() { return i; } Method(t, m, ps, _) : } defines Method m of type t class D { MethodCall(e, m, _): C c; refers to Method m int i; of type t in c void init() { where e has type ClassType(c) i = c.get(); } }
  • 31.
    Interaction with TypeSystem (3) Method(t, m, ps, _) : class C { defines unique Method m void m() {} of type (ts, t) void m(int x) {} where ps has type ts void m(bool x) {} void m(int x, int y) {} Param(t, p): void m(bool x, bool y) {} defines unique Variable p void x() { of type t m(); m(42); MethodCall(e, m, es): m(true); refers to Method m m(21, 21); of type (ts, t) in c m(true, false); where e has type ClassType(c) } where es has type ts }
  • 32.
    Name Binding class defines partial class type refers inheritance namespaces namespace using scopes method field imports variable parameter block
  • 33.
    Name Binding Languagein Spoofax (*)
  • 34.
    Name Binding Languagein Spoofax (*) derivation of editor services checking code completion reference resolution multi-file analysis parallel evaluation incremental evaluation (*) alpha; NBL is compiled to Stratego implementation of name resolution algorithm (ask me for pointers)
  • 35.
    Outlook Language definition =CFG + NBD + TS + DS Single source for Language reference manual Efficient (incremental) compiler Execution engine (interpreter) Integrated development environment