Title: All about binding
1All about binding
Memory Locations for Variables (ch 12)
- Variables are bound (dynamically) to values
- values must be stored somewhere in the memory.
2Imperative ??Functional
- Imperative languages
- a 0
- Store a zero in as memory location
- Functional languages
- val a 0
- Bind a to the value zero
Big deal?
Yes!
3Function Activations
- Activation of a function
- The lifetime of one execution of the function,
from call to corresponding return.
If each activation has its own binding for
variables, the variables are called
activation-specific variable (dynamic or
automatic)
most modern languages
4Block Activations
- A variable might be specific to a particular
block within a function
fun fact n if (n0) then 1 else let val b
fact (n-1) in nb end
Do we have it in C/JAVA?
5Other Lifetimes For Variables
- We usually have a way to declare a variable that
is bound to an independent memory (independent
from any functions) - static allocation, the loader does the job of
allocation
int count 0 int nextcount() count count
1 return count
6Scope ?? Activation
George Washington
America ?? A.D. 1732-1799
7(lifetime)
Scope ?? Activation
George Washington America ?? A.D. 1732-1799
- In most modern languages, variables with local
scope have activation-specific lifetimes, by
default - some exception
int nextcount() static int count 0 count
count 1 return count
not activation-specific
8there are other lifetimes for variables
In addition to activation-specific variables
- In OOP, some variables lifetimes are associated
with object lifetimes - Some variables may last across multiple
executions of the program -
9Activation Records
- Each function being executed has an activation
record
- An activation record contains information about
- Activation-specific variables
- Return address (or pointer to the current
instructions) - Link to callers activation record
10Block Activation Records
- When a block is entered, space must be found for
the local variables of that block - Possibile implementations
- Preallocate in the containing functions
activation record - Extend the functions activation record when the
block is entered (and revert when exited) - Allocate separate block activation records
11Static Allocation
- The simplest approach allocate one activation
record for every function, statically - Older dialects of Fortran and Cobol used this
system - Simple and fast, but....(what!)
12Fortran Example
FUNCTION AVG (ARR, N) DIMENSION ARR(N)
SUM 0.0 DO 100 I 1, N SUM
SUM ARR(I)100 CONTINUE AVG SUM /
FLOAT(N) RETURN END
13Drawback
- Each function has one activation record, thus
There can be only one activation alive at a time
- Modern languages (including modern dialects Cobol
and Fortran) do not obey this restriction for - Recursion
- Multithreading
14Stacks Of Activation Records
- To support recursion, we need to allocate a new
activation record for each activation - Dynamic allocation
- allocate ?? deallocate
- A stack of activation records stack frames
- push ?? pop
15Current Activation Record the one for the
function that is running
- Static location of activation record was
determined before runtime - Dynamic location of the current activation
record is not known until runtime - A function must know how to find the address of
its current activation record. A machine register
is reserved to hold this
16C Example
The evaluation of fact(3) before the recursive
call
int fact(int n) int result if (nlt2) result
1 else result n fact(n-1) return
result
.... cout ltlt ... ltlt fact(3) ltlt .... .....
somewhere
17int fact(int n) int result if (nlt2) result
1 else result n fact(n-1) return
result
After calling fact(2)
before calling fact(1)
18int fact(int n) int result if (nlt2) result
1 else result n fact(n-1) return
result
Before fact(1)returns
19The second activation is about to return.
int fact(int n) int result if (nlt2) result
1 else result n fact(n-1) return
result
2
1
2
20The first activation is about to return with the
result fact(3) 6.
int fact(int n) int result if (nlt2) result
1 else result n fact(n-1) return
result
21ML Example
fun halve nil (nil, nil) halve a (a,
nil) halve (abcs) let val
(x, y) halve cs in (ax, by)
end
halve 1,2,3,4
22halve 3,4
This shows the contents of memory just before the
third activation.
fun halve nil (nil, nil) halve a (a,
nil) halve (abcs) let val
(x, y) halve cs in (ax, by)
end
23halve
This shows the contents of memory just before the
third activation returns.
fun halve nil (nil, nil) halve a (a,
nil) halve (abcs) let val
(x, y) halve cs in (ax, by)
end
24The second activation is about to return.
fun halve nil (nil, nil) halve a (a,
nil) halve (abcs) let val
(x, y) halve cs in (ax, by)
end
25The first activation is about to return with the
result halve 1,2,3,4 (1,3,2,4)
fun halve nil (nil, nil) halve a (a,
nil) halve (abcs) let val
(x, y) halve cs in (ax, by)
end
26Nesting Functions
- Function definitions can be nested inside other
function definitions - Inner functions can refer to local variables of
the outer functions (under the usual block
scoping rule) - ML, Ada, Pascal provide such feature
- C, Java dont. (for good reasons)
27The tricky part is the previous activation
record may not help
f() int i 3
- Called by another inner function
g() i
Called by a recursive call.
h() g()
f() int i 3 g()
g() g() i
h()
28Static Scoping and Nesting Link
static scoping
f() int i 3
h() int i 2 f()
g() i
dynamic scoping
g()
- An inner function needs to be able to find the
address of the most recent activation of the
outer function (not just the caller function) - We can keep a nesting link in the activation
record
29Example
fun quicksort nil nil quicksort
(pivotrest) let fun split(nil)
(nil,nil) split(xxs)
let val (below, above)
split(xs) in if xlt
pivot then (xbelow, above)
else (below, xabove) end
val (below, above) split(rest) in
quicksort below _at_ pivot _at_ quicksort above
end
30time
Current Activation Record
QuickSort()
Split()
Split()
Split()
Return Address
Return Address
Return Address
Return Address
Previous Activation Record
Previous Activation Record
Previous Activation Record
Previous Activation Record
QuickSort local variable pivote, rest,
QuickSort local variable x, xs,
QuickSort local variable x, xs,
QuickSort local variable x, xs,
Cant find pivot here
31time
Current Activation Record
QuickSort()
Split()
Split()
Split()
Return Address
Return Address
Return Address
Return Address
Previous Activation Record
Previous Activation Record
Previous Activation Record
Previous Activation Record
QuickSort local variable pivote, rest,
QuickSort local variable x, xs,
QuickSort local variable x, xs,
QuickSort local variable x, xs,
Nesting link
Nesting link
Nesting link
Nesting link null
3
3
2
1
The rules to setup the nesting links 1, 2, 3
32How to Set Nesting Links
- For one level of nesting
- 1. Calling outer function (non-nesting
function, e.g. main calls quicksort) - ? set to null
- 2. Calling from outer to inner (e.g. quicksort
calls split) - ? set nesting link same as callers
activation record - 3. Calling from inner to inner (e.g. split
calls split) - ? set nesting link same as callers nesting
link
33Multiple Levels Of Nesting
f() int fi
g() int gi
h() int hi hi, gi, fi
- References n nesting levels away chain back
through n nesting links
34- Common methods for referring to non-local
variables in outer functions - Nesting links in activation records
- Displays nesting links not in the activation
records, but collected in a single static array - Lambda lifting passing all needed variables as
parameters (i.e., as hidden parameters)
35Functions As Parameters
- What really gets passed?
- Source code, compiled code, pointer to code, or
implementation in some other form
macro expanding
OOP objects
Cs way
functional languages
36Example
fun addXToAll (x,theList) let fun addX y
y x in map addX theList end
5, 2,3,4 ? 7,8,9
where to?
Nesting link
maps activation record?
In the previous example quicksort ?(call) split
Nesting link
addXToAll ? map, map ? addX, addX ? (refers) x
(in addXToAlls activation record)
37- When map ? addX, what nesting link will addX be
given? - Not maps activation record addX is not nested
inside map - Not maps nesting link map is not nested inside
anything - Therefore, the parameter addX passed to map must
include the nesting link to use when addX is
called,
i.e., the nesting link of addx should be prepared
when addToAll tries to pass it as an argument to
map
38Example
fun addXToAll (x,theList) let fun addX y
y x in map addX theList end
Current Activation Record
Right before the call to map. The variable
addX is bound to a function-value including code
and nesting link.
ygtyx Nesting link
39Not Just For Parameters
- Functional languages allow many more kinds of
operations on function-values - passed as parameters,
- returned from functions,
- constructed by expressions, etc.
- Function-values include both code to call, and
nesting link to use when calling it
40One More Complication
- What happens if a function created is to be
returned as a value?
fun funToAddX x let fun addX y y
x in addX end
fun test let val f funToAddX 3 in
f 5 end
return a function that add x
41Current Activation Record
fun test let val f funToAddX 3 in
f 5 end
fun funToAddX x let fun addX y y
x in addX end
ygtyx Nesting link
Before funToAddX returns addx.
42Current Activation Record
fun test let val f funToAddX 3 in
f 5 end
fun funToAddX x let fun addX y y
x in addX end
ygtyx Nesting link
After funToAddX returns, f is the bound to the
new function-value.
Any Problem ?
43Problem --
- This will fail if the language system deallocated
that activation record when the function returned
Solution
keep all activation records (MLs way)
New problem
waste too much memory
Solution
Garbage collection
New problem ??