Implementation of variable access

  • (Algol-style) Most-closely nested rule: 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.
  • In C++, ::X referes to a global declaration of X, regardless of whether the current xubroutine also has an X
  • Use static links in each frame on the stack that points to the “parent” frame; the most recent invocation of the lexically surrounding subroutine. The resulting static chain can be traversed by deferencing the chain j times in order to find a variable declared j subroutine scopes outward.

Declaration order

  • Is a declaration in a scope valid in the entire scope? Or just in the text following the definition? This is different for each language!
  • If a name must be declared before used, then how can we allow recursive types and subroutines? C and C++ handles this by separating declaration and definition.

Pascal

  • Forward references for procedures
  • Allow the use of recursive types in definitions with pointers only
  • Pointers are fixed size; this + forward referencing allowed for 1-pass compilation

C, C++

  • Differentiate between declaration and definition
  • declaration-introduces name and defines scope
  • definition-introduces object to which name is bound
  • The declaration is enough to allow you to use the name recursively to define a type

Decoupling lifetime from visibility

  • Single subroutine abstraction-variables are only visible in the subroutine
    • static variables in C
    • save in Fortran
  • Modules-(package, cluster, namespace)
    • Objects in module are visible to each other
    • Explicit importing/exporting is required to interact with external modules
    • Local/Global modules were used initially. Global modules divided a module into Definition and Implementation parts. Originally only allowed for 1 instance of the defined object in the module.
    • Turn modules into managers of types-still a separation between the manager for the type and the type itself. Procedures accept the (record) type as a parameter
  • Classes-similar to modules except they statically bind procedures to a type
    • Inside the implementation module, use a keyword to refer to this implicit argument, often self or this

Independent/Separate compilation

  • Independent compilation-can compile different parts of a program independently, but no type checking across compilation units
  • Separate-type checking across compilation units
    • Definition module is compiled to produce a symbol file
    • Clients can compile their code w/ symbol file to produce an object file
  • Symbol files must remain consistent; common to use keys to match
  • Java
    • Symbol files are extracted from class files by the compiler
    • Compatibility checks are performed as part of byte code verification.