Dynamic Scope

Recall, scope is determined at runtime and depends on flow of execution.

Disadvantages

  • Breaks encapsulation
  • Can’t statically check type references to non locals
  • More difficult to understand, requires knowing the calling sequence
  • Access to non-locals is slower in dynamically scoped languages

Note - Lisp became Scheme and transitioned from dynamic to static scoping! Most modern languages are statically scoped.

Implementing static scope in a compiler

  • Use a data structure called a symbol table that contains (name, attribute) pairs. The compiler uses this table at compile time to track bindings.
  • Flat block structure-organize table by name, scope (local, global), and attributes
    • Add/remove entries in table as they leave and enter local scope
  • A stack is a natural data structure for handling nested blocks (many scope levels)
    • Fast add and removal, but slow look-up. This is backwards from what we want!
  • Use Leblanc-Cook symbol table (hash table)

LeBlanc-Cook symbol tables

  • Each scope is assigned a serial number. The outermost scope is given number 0. The scope containing programmer-declared global names is given number 1. Additional scopes are given successive numbers.
  • All names, regardless of scope, are entered into a single has table, keyed by name. Each entry in the table then contains the symbol name, its category (variable, constant, type, procedure, field name, parameter, etc.), scope number, type (a pointer to another symbol table entry), and additional, category-specific fields.
  • In addition to the hash table, the symbol table has a scope stack that indicates, in order, the scopes that compose the current referencing environment.