Session 3 : Names, Bindings, and Scopes
Introduction
- Imperative languages are abstractions of von Neumann architecture
- Memory
- Processor
- Variables are characterized by attributes
To design a type, must consider scope, lifetime, type checking, initialization, and type compatibility
Names
- Length
- If too short, they cannot be connotative
- Language examples:
- FORTRAN 95: maximum of 31
- C99: no limit but only the first 63 are significant; also, external names are limited to a maximum of 31
- C#, Ada, and Java: no limit, and all are significant
- C++: no limit, but implementers often impose one
- Special characters
- PHP: all variable names must begin with dollar signs
- Perl: all variable names begin with special characters, which specify the variable’s type
- Ruby: variable names that begin with @ are instance variables; those that begin with @@ are class variables
Case sensitivity
Disadvantage: readability (names that look alike are different)
- Names in the C-based languages are case sensitive
- Names in others are not
- Worse in C++, Java, and C# because predefined names are mixed case
- A keyword is a word that is special only in certain contexts, e.g., in FortranSpecial wordsAn aid to readability; used to delimit or separate statement clauses
- Real VarName (Real is a data type followed with a name, therefore Real is a keyword)
- Real = 3.4 (Real is a variable)
- A reserved word is a special word that cannot be used as a user-defined name
- Potential problem with reserved words: If there are too many, many collisions occur (e.g., COBOL has 300 reserved words!)
Variables
- A variable is an abstraction of a memory cell
- Variables can be characterized as a sextuple of attributes:
- Name
- Address
- Value
- Type
- Lifetime
- Scope
The Concept of Binding
Possible Binding Times
- Language design time — bind operator symbols to operations
- Language implementation time– bind floating point type to a representation
- Compile time — bind a variable to a type in C or Java
- Load time — bind a C or C++ static variable to a memory cell)
- Runtime — bind a nonstatic local variable to a memory cell
- Storage Bindings & Lifetime
- Allocation – getting a cell from some pool of available cells
- Deallocation – putting a cell back into the pool
- The lifetime of a variable is the time during which it is bound to a particular memory cell
Categories of Variables by Lifetimes
- Static–bound to memory cells before execution begins and remains bound to the same memory cell throughout execution, e.g., C and C++ static variables in functions
- Advantages: efficiency (direct addressing), history-sensitive subprogram support
- Disadvantage: lack of flexibility (no recursion)
- Stack-dynamic–Storage bindings are created for variables when their declaration statements are elaborated.
- If scalar, all attributes except address are statically bound
local variables in C subprograms (not declared static) and Java methods
- Advantage: allows recursion; conserves storage
- Disadvantages:
- Overhead of allocation and deallocation
- Subprograms cannot be history sensitive
- Inefficient references (indirect addressing)
- Explicit heap-dynamic –– Allocated and deallocated by explicit directives, specified by the programmer, which take effect during execution
- Referenced only through pointers or references, e.g. dynamic objects in C++ (via new and delete), all objects in Java
- Advantage: provides for dynamic storage management
- Disadvantage: inefficient and unreliable
- Implicit heap-dynamic--Allocation and deallocation caused by assignment statements (all variables in APL; all strings and arrays in Perl, JavaScript, and PHP)
- Advantage: flexibility (generic code)
- Disadvantages:
- Inefficient, because all attributes are dynamic
- Loss of error detection
Variable Attributes: Scope
- The scope of a variable is the range of statements over which it is visible
- The local variables of a program unit are those that are declared in that unit
- The nonlocal variables of a program unit are those that are visible in the unit but not declared there
- Global variables are a special category of nonlocal variables
- The scope rules of a language determine how references to names are associated with variables
Static Scope
- Based on program text
- To connect a name reference to a variable, you (or the compiler) must find the declaration
- Search process: search declarations, first locally, then in increasingly larger enclosing scopes, until one is found for the given name
- Enclosing static scopes (to a specific scope) are called its static ancestors; the nearest static ancestor is called a static parent
- Some languages allow nested subprogram definitions, which create nested static scopes (e.g., Ada, JavaScript, Common LISP, Scheme, Fortran 2003+, F#, and Python)
- Variables can be hidden from a unit by having a “closer” variable with the same name
- Ada allows access to these “hidden” variables
Evaluation of Static Scoping
- Works well in many situations
- Problems:
- In most cases, too much access is possible
- As a program evolves, the initial structure is destroyed and local variables often become global; subprograms also gravitate toward become global, rather than nested