Names, Scopes and Bindings Aaron Bloomfield CS 415 Fall 20051

Download Report

Transcript Names, Scopes and Bindings Aaron Bloomfield CS 415 Fall 20051

Names, Scopes and Bindings
Aaron Bloomfield
CS 415
Fall 20051
1
Binding
• A binding is an association between two things,
such as a name and the thing it represents
• Example: int x
– When this statement is compiled, x is bound to a
memory space
2
Binding Time
• The time at which the association between two
items is created
• There are many different binding times that can
be implemented:
–
–
–
–
–
–
–
Language design time
Language implementation time
Program writing time
Compile time
Link time
Load time
Run time
3
Binding Times
• Language design time
– These are control flow constructs, primitives, and
other semantics
– Think of reserved words: i.e. if, for, else, while, etc.
• Language implementation time
– These include I/O couplings
– System dependent things such as max heap and
stack sizes
– Think of constants: MAX_INT, etc.
– In Algol, this included the I/O procedure names
4
Binding Times
• Program writing time
– When you the programmer choose data structures
and names
• Compile time
– The compiler maps high level constructs to machine
code
– Think of the assembly for a compiled procedure
• Link time
– Separate compilation means not every part of a
program has to be compiled at the same time
– Libraries are linked to your program and bound
5
Binding Times
• Load time
– For primitive operating systems
– Binds physical addresses
– Most OSes do this during link time with virtual
addresses
• Run time
– Very broad term covering the span of execution
– Values to variable bindings occur here
6
Binding Times
• Very important to design and implementation of
programming languages
– Early bindings = greater efficiency
– Later bindings = greater flexibility
7
Scope rules
• The textual region of the program in which a
binding is active is its scope
• Static scoping is more common in modern
programming langauges
– Found in C, C++, Pascal
8
Static scope
• All scoping can be determined at compile time
• Most often this is done with a textual top-tobottom scan
• Most basic static scope rule: everything has
global scope
9
Fortran Implementation
• Global scopes
• Local scopes limited to their subroutines
• Local variable scope extends through the
execution of the subroutine unless the variable
is saved
10
Nested Subroutines
• Introduced in Algol 60 and is found in some
modern languages
– Pascal, Ada
• Subroutines can be declared inside other
subroutines
– This confuses the scope rules even more
11
Closest Nested Scope Rule
• A variable declared has its scope in the current
subroutine,
and
any
internally
nested
subroutines, unless there is a definition with the
same name more locally
12
Closest Nested Scope Rule
Example
procedure level1()
variable x;
procedure level2()
variable x;
begin
(* level 2 code *)
end
begin
(* level 1 code *)
end
procedure outside()
begin
(*outside code*)
end
13
Dynamic Scope Rules
• Generally less complicated to implement
• The “current” binding for a name is the one most
recently encountered during execution, and not
yet destroyed by returning from its scope
• APL, Snobol, early dialects of Lisp, and Perl
have dynamic scoping
14
Implications
• Semantic rules are dynamic rather than static
– Type checking is generally deferred until run time
• To accommodate these rules, dynamically
scoped languages are most often interpreted
• Very easy for an interpreter to look up the
meaning of a name
– All that is needed is a stack of declarations
• However, it makes it harder to understand
programs
– The modern consensus seems to be that dynamic
scoping is usually a bad idea
15
Dynamic scope example
int print_base = 10;
print_integer (int n) {
switch (print_base) {
case 10: ...
case 8: ...
case 16: ...
case 2: ...
}
}
foo {
print_integer (10);
int print_base = 16;
print_integer (10);
print_base = 2;
print_integer (4);
}
16
Alternatives to achieve the same
result
• Overloading and optional parameters
– print_integer takes an optional parameter (one with a
default value) that specifies the base
– print_integer is overloaded: one form prints in
decimal, the other form takes an additional parameter
that specifies the base
• Better or worse than dynamic scoping?
17
More implications
• With dynamic scoping, no program fragment that
makes use of non-local names is guaranteed a
predictable referencing environment
18
19
Referencing Environments
• A referencing environment is the complete set of
bindings in effect at a given point in a program
• Static scope rules:
– Referencing environment
nesting of program blocks
dependent
on
lexical
• Dynamic scope rules:
– Referencing environment dependent on the order in
which declarations are reached
20
What about references to
functions?
• When are dynamic scope rules applied?
– When the function is called?
• Shallow binding
– When the reference is created?
• Deep binding
21
int max_score;
float scale_score (int raw_score) {
return (float) raw_score / (float) max_score;
}
float highest_score (int[] scores, function_ptr scaling_function) {
float max_score = 0;
foreach score in scores {
float percent = scaling_function (score);
if ( percent > max_score )
max_score = percent;
function is called
}
return max_score;
}
main() {
reference is created
max_score = 50;
int[] scores = ...
print highest_score (scores, scale_score);
}
22
Deep Binding
• Generally the
languages
default
in
lexically
scoped
• Dynamically scoped languages tend to use
shallow binding
23
Implementing Deep Binding
• Subroutine Closure
24
The Symbol Table
• During compilation, keeps track of all the
identifiers
• Only matters in a statically scoped language!
– Why?
• Basic functions: lookup() and insert()
• Must keep track of scope as well
– Often by enter_scope() and leave_scope() functions
25
Activation records
• When a subroutine starts, a number of things
have to be stored:
–
–
–
–
A copy of the parameters (pass by value)
The return address when the subroutine exits
Local variables in the subroutine
Etc.
• This data is called the activation record
• Fortran (up until 90) only had space for one
activation record
– Thus, you couldn’t call more than one subroutine at a
time
26
Recursive vs. Iterative
• Ocaml will recognize tail recursion and convert it
to a while loop:
let foo x = if x = 0 then 0 else 1 + foo (x-1);;
• A call to foo 1000000 would require one million
activation records if called recursively
– That’s many, many megs of memory!
– In addition to the time spent creating them and
branching to the next recursive call of the subroutine
• An iterative solution avoids all that
– Although there is still the branch for the loop
27
Lifetimes
Lifetime = time from creation to deletion
• Bindings
• Objects
28
Storage Management
• Static - absolute address, retained throughout
program
• Stack - LIFO, subroutine calls
• Heap – allocation/deallocation at arbitrary times
29
Heap Management
• Free list
30
Who Manages the Heap?
• User
• System
31
Garbage Collection
• Mark and Sweep
• Reference Counting
32
Aliases
33