CD Notes
In-depth guide to scope management: nested scopes, scope chains, symbol table implementation, scope resolution, variable shadowing, lifetime management, practical compiler symbol management techniques.
Core Concepts
Scope determines where a name is visible and how names are resolved. Scope management implements scoping rules in compilers.
Scope Hierarchy
Scope Chain and Name Resolution
Scope Chain Algorithm
| 4. If reached global scope and not found | ERROR |
| Scopes | [Local Block, Function, Global] |
| 1. Check Local Block | not found |
| 2. Check Function | not found |
| 3. Check Global | found! return global x |
Symbol Table Implementation
Hash Table + Scope Chain
Symbol Entry Structure
| name | string |
| type | Type |
| scope_level | int (0=global, 1+=nested) |
| kind | "variable" | "function" | "class" | etc |
| attributes | { |
| address | memory location |
| size | bytes |
| initialized | bool |
| used | bool |
Variable Shadowing
Shadowing Rules
| Global | int x = 5; |
| Function | { |
| Resolution | Use innermost (closest) definition |
Handling Shadowing
Nested Scopes
Block Scope Entry/Exit
Function Scope
Parse function:
save_current_scope = current_scope
current_scope = current_scope.enter_scope() // New function scope
add_parameters_to_scope()
parse_function_body()
current_scope = save_current_scope // RestoreScope Visibility Rules
Static Scope (Lexical Scope)
Visibility determined by program text:
function outer():
int x = 1
function inner():
print x // Sees outer's x
inner()
Result: x = 1 (determined at compile-time by nesting)Dynamic Scope (for reference)
Visibility determined by call stack:
function outer():
int x = 1
call middle()
function middle():
call inner()
function inner():
print x // Which x?
Static: Error (x undefined)
Dynamic: x = 1 (from outer call stack)Scope Management in Practice
Example: Declaration Processing
def process_declaration(var_name, var_type):
current_symbol = SymbolTable.lookup_local(var_name)
if current_symbol:
error(f"{var_name} already declared")
SymbolTable.add_symbol({
name: var_name,
type: var_type,
scope_level: current_scope.level
})
def process_usage(var_name):
symbol = SymbolTable.lookup(var_name)
if not symbol:
error(f"{var_name} undefined")
return symbol.type // Use for type checkingQuick Revision Notes
- Scope: Region where name is visible
- Scope chain: Search path for name resolution
- Scope level: Nesting depth (0=global, 1+=nested)
- Symbol table: Maps names to attributes
- Shadowing: Inner scope hides outer names
- Name resolution: Find innermost matching definition
- Scope exit: Clear local symbols, return to parent
Interview Q&A
Q1: How do compilers implement scope management efficiently?
A: Using hash tables for O(1) lookups within a scope, plus parent pointers for scope chain traversal. Typical lookup: search local scope (hash), then follow parent pointers up. Amortized O(chain_length) where chain_length ≈ nesting depth.
Q2: What's the difference between static and dynamic scoping?
A: Static (lexical): determined by code structure (where declared). Dynamic: determined by call stack (which function called this). Almost all modern languages use static scoping for predictability.
Q3: How do you handle forward declarations in scope management?
A: Two-pass compilation: first pass collects all declarations (functions, classes), second pass checks usage. Or single-pass with forward lookup: when seeing usage, check if name will be declared later.
Q4: What happens to local variables when a scope ends?
A: Their symbol table entries are removed (scope exits). Memory may be reclaimed (stack frame popped). If variable's address is still referenced, it's dangling reference (compiler error or runtime issue).
Q5: Can you have the same name in two non-nested scopes?
A: Yes! Different scopes don't conflict. Example: two functions can have local variable x without conflict. Scope chain prevents confusion—each lookup starts from current scope.
Q6: How do class members and namespaces affect scope management?
A: They add additional scope levels. Class members are in class scope; functions are in class + function scope. Namespaces create new top-level scopes. Lookup follows scope hierarchy: local → enclosing → class (if inside class) → namespace → global.
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Scope Management: Symbol Table Design for Language Implementation.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this Compiler Design topic.
Search Terms
compiler-design, compiler design, compiler, design, semantic, analysis, scope, management
Related Compiler Design Topics