10/16/2015IT 3271 All about binding n Variables are bound (dynamically) to values n values must be...
-
Upload
isaac-ramsey -
Category
Documents
-
view
216 -
download
0
Transcript of 10/16/2015IT 3271 All about binding n Variables are bound (dynamically) to values n values must be...
04/20/23 IT 327 1
All about binding
Variables are bound (dynamically) to values values must be stored somewhere in the memory.
Memory Locations for Variables (ch 12)
04/20/23 IT 327 2
Imperative Functional Imperative languages
a := 0– Store a zero in a’s memory location
Functional languages
val a = 0 – Bind a to the value zero
a := 0;
a := 1;
val a = 0;
val a = 1;
04/20/23 IT 327 3
Function Activations Activation of a function :
The lifetime of one execution of the function, from call to corresponding return.
most modern languages
If each activation has its own binding for variables, the variables are called activation-specific variable
(dynamic or automatic)
04/20/23 IT 327 4
Block Activations
A variable might be specific to a particular block (within a function):
fun fact n = if (n=0) then 1 else let val b = fact (n-1) in n*b end;
Do we have it in C++/JAVA?
04/20/23 IT 327 5
Other 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() {
int inc = 1; count = count + inc; return count;}
04/20/23 IT 327 6
Scope Activation
George Washington
America A.D. 1732-1799
04/20/23 IT 327 7
In most modern languages, variables with local scope have activation-specific lifetimes, by default
some exception
int nextcount() { static int count = 0; int inc = 1;
count = count + inc; return count;}
not activation-specific
(lifetime) Scope ActivationGeorge Washington
America A.D. 1732-1799
04/20/23 IT 327 8
there are other lifetimes for variables
In OOP, some variables’ lifetimes are associated with object lifetimes
Some variables may last across multiple executions of the program
In addition to activation-specific variables
04/20/23 IT 327 9
Activation Records
Each function being executed has an activation record
An activation record contains information about :
1. Activation-specific variables
2. Return address (or pointer to the current instructions)
3. Link to caller’s activation record
04/20/23 IT 327 10
Block Activation Records
When a block is entered, space (memory) must be found for the local variables of that block
Possibile implementations:– Preallocate in the containing function’s
activation record– Extend the function’s activation record when
the block is entered (and revert when exited)– Allocate separate block activation records
04/20/23 IT 327 11
Static 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’s the problem?)
04/20/23 IT 327 12
Fortran 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
return address
ARR address
N address
I
SUM
AVG
Static activation record
04/20/23 IT 327 13
Drawback Each function has one activation record, thus
There can be only one activation.
Modern languages (including modern dialects Cobol and Fortran) do not obey this restriction for:
1. Recursion2. Multithreading
04/20/23 IT 327 14
Stacks 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
04/20/23 IT 327 15
Current Activation Recordthe 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
04/20/23 IT 327 16
C Example
int fact(int n) { int result; if (n<2) result = 1; else result = n * fact(n-1); return result;}
previous activation record
return address
n: 3
result: ?
current activation record
The evaluation of fact(3) before the 1st recursive call, fact(2)
....
cout << ... << fact(3) << ....
..... somewhere
calling fact(3)
04/20/23 IT 327 17
int fact(int n) { int result; if (n<2) result = 1; else result = n * fact(n-1); return result;}
before calling fact(1)previous
activation record
return address
n: 2
result: ?
current activation record
previous activation record
return address
n: 3
result: ?
After calling fact(2)
calling fact(3)calling fact(2)
04/20/23 IT 327 18
int fact(int n) { int result; if (n<2) result = 1; else result = n * fact(n-1); return result;}
previous activation record
return address
n: 2
result: ?
previous activation record
return address
n: 3
result: ?
previous activation record
return address
n: 1
result: 1
current activation record
Before fact(1)returns
calling fact(3)calling fact(2)calling fact(1)
04/20/23 IT 327 19
int fact(int n) { int result; if (n<2) result = 1; else result = n * fact(n-1); return result;}
The second activation is about to return.
previous activation record
return address
n: 2
result: 2
previous activation record
return address
n: 3
result: ?
previous activation record
return address
n: 1
result: 1
current activation record
12
2
04/20/23 IT 327 20
int fact(int n) { int result; if (n<2) result = 1; else result = n * fact(n-1); return result;}
The first activation is about to return with the result fact(3) = 6.
previous activation record
return address
n: 2
result: 2
previous activation record
return address
n: 3
result: 6
previous activation record
return address
n: 1
result: 1
current activation record
04/20/23 IT 327 21
ML Example
fun halve nil = (nil, nil)| halve [a] = ([a], nil)| halve (a::b::cs) = let val (x, y) = halve cs in (a::x, b::y) end;
halve [1,2,3,4]
previous activation record
return address
parameter: [1,2,3,4]
a: 1
b: 2
cs: [3,4]
x: ?
y: ?
value to return: ?
current activation record
04/20/23 IT 327 22
fun halve nil = (nil, nil)| halve [a] = ([a], nil)| halve (a::b::cs) = let val (x, y) = halve cs in (a::x, b::y) end;
previous activation record
return address
parameter: [3,4]
a: 3
b: 4
cs: []
x: ?
y: ?
previous activation record
return address
parameter: [1,2,3,4]
a: 1
b: 2
cs: [3,4]
x: ?
y: ?
value to return: ?
value to return: ?
current activation record
This shows the contents of memory just before the third activation.
halve [3,4]
04/20/23 IT 327 23
fun halve nil = (nil, nil)| halve [a] = ([a], nil)| halve (a::b::cs) = let val (x, y) = halve cs in (a::x, b::y) end;
previous activation record
return address
parameter: [3,4]
a: 3
b: 4
cs: []
x: ?
y: ?
previous activation record
return address
parameter: [1,2,3,4]
a: 1
b: 2
cs: [3,4]
x: ?
y: ?
value to return: ?
value to return: ?
previous activation record
return address
parameter: []
value to return: ([], [])
current activation record
This shows the contents of memory just before the third activation returns.
halve []
04/20/23 IT 327 24
fun halve nil = (nil, nil)| halve [a] = ([a], nil)| halve (a::b::cs) = let val (x, y) = halve cs in (a::x, b::y) end;
previous activation record
return address
parameter: [3,4]
a: 3
b: 4
cs: []
x: []
y: []
previous activation record
return address
parameter: [1,2,3,4]
a: 1
b: 2
cs: [3,4]
x: ?
y: ?
value to return: ([3], [4])
value to return: ?
previous activation record
return address
parameter: []
value to return: ([], [])
current activation record
The second activation is about to return.
04/20/23 IT 327 25
fun halve nil = (nil, nil)| halve [a] = ([a], nil)| halve (a::b::cs) = let val (x, y) = halve cs in (a::x, b::y) end;
previous activation record
return address
parameter: [3,4]
a: 3
b: 4
cs: []
x: []
y: []
previous activation record
return address
parameter: [1,2,3,4]
a: 1
b: 2
cs: [3,4]
x: [3]
y: [4]
value to return: ([3], [4])
value to return: ([1,3],[2,4])
previous activation record
return address
parameter: []
value to return: ([], [])
current activation record
The first activation is about to return with the result halve [1,2,3,4] =([1,3],[2,4])
04/20/23 IT 327 26
Nesting 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 don’t. (for good reasons)
04/20/23 IT 327 27
Called by another inner function
An easy solution: further trace down the previous activation record.
Called by a recursive call.
f(…) {int i = 3;
}
…… h(…) ……
g(…) {… i …
}
h(…) {
g(…)… …
}
f(…) {int i = 3;
… g(…) …}
g(…) {… g(…)…… i …
}
What is i in function g?
The tricky part is that, the previous activation record may not help
int i = 2;
04/20/23 IT 327 28
Static Scoping vs Dynamic Scoping
What is the vale of i in function g ? (suppose h f g)
f(…) {int i = 3;
}
h(…) {int i = 2;……f(…)……
}……g(…)……
g(…) {… i …
}dynamic scoping
static scoping
Static Scoping Dynamic Scoping
i = 3i = 3
04/20/23 IT 327 29
Static Scoping and Nesting Link
For Static Scoping: An inner function needs to find the address of the most recent activation of
the outer function, not the caller (caller is for dynamic) We can keep a nesting link in the activation record…
f(…) {int i = 3;
}
h(…) {int i = 2;……g(…)……
}……g(…)……
g(…) {… i …
}dynamic scoping
static scoping
04/20/23 IT 327 30
fun split nil = (nil,nil)| split [a] = ([a],nil)| split [a,b] =
if (a <= b) then ([a],[b])else ([b],[a])
| split (a::b::c) = let val (x,y) = split (a::c) in if (a < b) then (x, b::y) else (b::x, y) end; fun quicksort nil = nil| quicksort [a] = [a]| quicksort a = let val (x,y) = split a in quicksort(x)@quicksort(y) end;
Quick Sort in ML
pivot
04/20/23 IT 327 31
Better ML
fun quicksort nil = nil| quicksort (pivot::rest) = let fun split(nil) = (nil,nil) | split(x::xs) = let val (below, above) = split(xs) in if x < pivot then (x::below, above)
else (below, x::above) end; val (below, above) = split(rest) in quicksort below @ [pivot] @ quicksort above end;
04/20/23 IT 327 32
time
Current Activation Record
Register
Can’t find pivot here
QuickSort(…)
Return Address
Previous Activation Record
QuickSort local variable:pivote, rest,
…
Split(…)
Return Address
Previous Activation Record
QuickSort local variable:
x, xs,…
Split(…)
Return Address
Previous Activation Record
QuickSort local variable:
x, xs,…
Split(…)
Return Address
Previous Activation Record
QuickSort local variable:
x, xs,…
04/20/23 IT 327 33
time
Current Activation Record
QuickSort(…)
Return Address
Previous Activation Record
QuickSort local variable:pivote, rest,
…
Split(…)
Return Address
Previous Activation Record
QuickSort local variable:
x, xs,…
Split(…)
Return Address
Previous Activation Record
QuickSort local variable:
x, xs,…
Split(…)
Return Address
Previous Activation Record
QuickSort local variable:
x, xs,…
Nesting link Nesting link Nesting linkNesting link
null
The rules to setup the nesting links: 1, 2, 31
233
04/20/23 IT 327 34
How to Set Nesting Links
For one level of nesting:
– 1. Calling from outer to outer: (non-nesting function, e.g. main calls quicksort)
set to null
– 2. Calling from outer to inner: (e.g. quicksort calls split, where split is defined inside quicksort)
set nesting link same to caller’s activation record
– 3. Calling from inner to inner: (e.g. split calls split) set nesting link same to caller’s nesting link
04/20/23 IT 327 35
Multiple Levels Of Nesting
References n nesting levels away chain back through n nesting links
f(…) {int fi;
}
g(…) { int gi;
}
h(…) {int hi… …hi, gi, fi
}
04/20/23 IT 327 36
Common methods for referring to non-local variables in outer functions
– Nesting links in activation records
– Displays: no nesting links in the activation records, but collected in a single static array
– Lambda lifting: passing all needed variables as parameters (i.e., as hidden parameters)
04/20/23 IT 327 37
Functions As Parameters
What really gets passed?
Source code, compiled code, pointer to code, or implementation in some other form
macro expanding OOP objects C’s way
functional languages
04/20/23 IT 327 38
Example
fun addXToAll (x,theList) = let fun addX y = y + x; in map addX theList end;
addXToAll (call) map, map (call) addX, addX (refers) x
In the previous example: quicksort (call) split
5, [2,3,4] [7,8,9]
where to?
Nesting link
Nesting link
(in addXToAll’s activation record)
map’s activation record?
04/20/23 IT 327 39
When map addX, what nesting link will addX be given?– Not map’s activation record: because addX is not
nested inside map – Not map’s nesting link: because map is not nested
inside any other funcion
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
04/20/23 IT 327 40
Examplefun addXToAll (x,theList) = let fun addX y = y + x; in map addX theList end;
Right before the call to map.
The variable addX is bound to a function-value including code and nesting link.
Current Activation Record
y=>y+xNesting link
Parameter
Return address
Nesting link
Previous activation
record
x
theList
addX
04/20/23 IT 327 41
Not 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
04/20/23 IT 327 42
One 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 thatadd x
04/20/23 IT 327 43
fun funToAddX x = let fun addX y = y + x; in addX end;
fun test = let val f = funToAddX 3; in f 5 end;
Before funToAddX returns addx.
y=>y+xNesting link
Parameter :3
Return address
Nesting link:null
Previous activation record
x=3
addX
Current Activation Record
Parameter Return address
Nesting link…
f:?
04/20/23 IT 327 44
fun funToAddX x = let fun addX y = y + x; in addX end;
fun test = let val f = funToAddX 3; in f 5 end;
y=>y+xNesting link
Parameter :3
Return address
Nesting link:null
Previous activation record
x=3
addX
Current Activation Record
Parameter Return address
Nesting link…
f:
After funToAddX returns, f is the bound to the new function-value. Any Problem ?
04/20/23 IT 327 45
Problem -- This will fail if the language system deallocated that
activation record when the function returned
Solution: keep all activation records (ML’s way)
New problem:
Solution:
waste too much memory
Garbage collection
New problem: ??