Ulf's  >  PLD  >  Names  >     
               
  Overview    Spelling    Binding    ^Domains    
     
     
lexical
syntactic
domain
 NAME   
binding
 
 DENOTABLE  characteristic
semantic
domain
     
   
«A binding is an association between two things, such as a name and the thing it names» [PLP 106].

Bindings can be

  • predefined,
  • explicitly specified by declarations in the program,
  • implicitly by the (first) use of a name.
  •    
       
       
    1. Bindings have a lifetime.
    Binding time «is the time at which a binding is created» [PLP 106] or, more generally, the time at which it is decided what a name stands for:
    1. predefined static binding: language design time, compiler development time (language implementation time)
    2. user-defined static binding: compile time, link time, load time, initialization time, declaration elaboration time
    3. dynamic binding: expression evaluation time, in particular subroutine call time
     
       
     
    Definitions:
    meaning
    form
    Definition = a syntactic construct whose meaning is the establishment of a binding, including possibly the creation of the bound-to memory object.

    Elaboration. "Algol 68 and Ada use the term elaboration to refer to the process by which declarations become active when [encountered in the flow of control]. Elaboration entails the creation of bindings. In many languages, it also entails the allocation of stack space for local objects, and possibly the assignment of initial values" [PLP 116].
    "If [a] subroutine [with local variable declarations] is called repeatedly, each invocation is said to create and destroy a separate instance of each local variable" [PLP 110].

    Compare the lifetime of the binding and the lifetime of what it is bound-to:
  • Eg. «Semantically, the lifetime of a local Fortran variable (both the object itself and the name-to-object binding) encompasses a single execution of the variable's subroutine. Programmers can override this rule by using an explicit save statement. A save-ed variable has a lifetime that encompasses the entire execution of the program. Instead of a logically separate object for every invocation of a subroutine, the save statement arranges for a single object that retains its value from one invocation of the subroutine to the next. (The name-to-variable binding, of course, is inactive when the subroutine is not executing, because the name is out of scope.)» [PLP 117].
  • In parameter passing by reference, the binding between formal parameter (NAME) and variable (MEMORY OBJECT) is destroyed at return time, but the passed variable (and maybe other bindings for it) still exists. [PLP 109].
  • We talk of a dangling [linguistic] reference if a binding exists but binds the name to a MEMORY OBJECT that has been destroyed [PLP 109].
  •  
       
     
    2. Bindings are not active everywhere/all-the-time
    «At any given point in a program's execution, the set of active bindings is called the current referencing environment» [PLP 116].
    NB: Not active is not the same as destroyed (end of lifetime): For example, «[b]indings to variables declared in a module are inactive outside the module, not destroyed» [PLP 123].
     
      Scope. «The textual region of the program in which a binding is active is its scope» [PLP 115]. The scope of a binding (not the binding itself) is determined by static or dynamic scope rules under the influence of declarations. The scope of a binding can have "holes", in which the binding is invisible (in the referencing environment), usually because it is hidden by (the scope of) another binding for the same name. «Some languages allow the programmer to access the outer meaning of a name by applying a qualifier or scope resolution operator» [PLP 121].
    «In addition to talking about the "scope of a binding," we sometimes use the word scope as a noun all by itself, without a specific binding in mind. Informally, a scope is a program region of maximal size in which no bindings change (or at least none are destroyed)» [PLP 116].
    «Modules into which [non-predefined] names must be explicitly imported are said to be closed scopes. By extension, scopes that do not require imports are said to be open scopes. Modules are closed in Modula (1, 2, and 3) but open in Ada. Nested subroutines are open scopes in most Algol families. Important exceptions are Euclid, in which both modules and subroutine scopes are closed, Turing and Modula (1), in which subroutines are optionally closed, and Clu, which outlaws the use of nonlocal variables entirely [but not nonlocal constants and subroutines]. ... Import lists serve to document the program: the use of names from surrounding scopes is really part of the interface between a subroutine and the rest of the program» [PLP 125].
       
       
     
    PL Design Decision: Your choice of scope rules
    (a) Static scoping. «In a language with static (lexical) scoping, the bindings between names and [memory] objects can be determined at compile time by examining the text of the program, without consideration of the flow of control at run time» [PLP 116].
    «Algol-style nesting [of blocks with local declarations] gives rise to the closest nested scope rule for resolving bindings from names to objects: a name that is introduced in a declaration is known in the scope in which it is declared, and in each internally nested scope, unless it is hidden by another declaration of the same name in one or more nested scopes. To find the object referenced by a given use of a name, we look for a declration with that name in the current, innermost scope. If there is one, it defines the active binding of the name. Otherwise, we look for a declaration in the immediately surrounding scope. We continue outward ... until we reach the outer nesting loevel of the program, where global objects are declared. If no declaration is found at any level, then the program is in error.
    ... It is common to consider [the language's built-in or predefined objects] to be declared in an extra, invisible, outermost scope, which surrounds the scope in which global objects are declared
    » [PLP 118].
      (b) Dynamic scoping. «In a language with dynamic scoping, the bindings between names and objects depend on the flow of control at run time, and in particular on the order in which subroutines are called ... the "current" binding for a given name is the one encountered most recently during execution and not yet destroyed by returning from its scope» [PLP 129].
    «It is not entriely clear whether the use of dynamic scoping in Lisp and other early interpreted languages was delibereate or accidental. ... The modern consensus seems to be that dynaic scoping is usually a bad idea ... The principal argument in favor of dynamic scoping is that it facilitates the customization of subroutines.» [PLP 131].
     
       
        The choice influences what semantic object are defined by nested procedure definitions with access to the names from the surrounding subprogram. Static scoping requires this to be a closure:    
    Closure
    A closure is a subroutine bundled together with a referencing environment. The deep binding rule for first-class procedures is that when a subroutine [name] is used as a value (a reference to the subroutine is created), then a closure is created by associating it with (a copy of) the current referencing environment [PLP 142].
     
       
     
    Static scoping design choice: Scope of binding = block. «Pascal specifies that the scope of a declaration is the entire block in which it is declared, including the space between the beginning of the block and the declaration (but excluding any holes in the scope, of course)» [PLP 150]. Modula-3 the same [PLP 151]. In Java, classes in a file can be used before their definition. «In a similar vein, members of a Java or C++ class are visible throughout the code of the member functions of the class, regardless of the order in which the members are declared» [PLP 151].
    In combination with Pascal's (but not Modula-3's) declaration-before-use rule, this may lead to additional error messages.
    const missing = -1;
    ...
    procedure foo;
    const  null = missing; (* error: foo.missing used before declared *)
           missing = 0;
    ...
    
    
    Static scoping design choice: Forward reference In Pascal, and similar in Modula-2, types used to construct pointer types need to be in scope (ie declared later in same block), but need not be declared before use [PLP 151].
    type Alink = ^A;
         A = record next: Alink; ...
    
    Static scoping design choice: Incomplete type forward declaration In Ada, C and C++, incomplete type declarations allow forward declarations of types defined later, so that they can be used before their definition. Pascal allows forward declaration of routines. [PLP 151]
    type A;
    type Alink is access A;
    type A is record next: Alink; ...
    
    procedure Q (); forward;
    procedure P (); begin ... Q() ... end;
    procedure Q (); begin ... P() ... end;
    
     
                     
    Ulf Schünemann; ulf@cs.mun.ca; 031004