Nested Procedure
A Nested procedure is a procedure declared inside another procedure. With supported languages, nested procedures can to access variables outside of its scope, without having to pass the parameters explicitly.
The C Language does not support nested procedures, but many languages do, including languages as diverse as Scheme/Racket, Pascal, Ada, Modula-3, OCaml, Haskell, Python, Javascript, C#, Scala, and even Fortran 90.
Different languages implement nested procedures in different ways:
- Static Scope / Lexical Scope: The word static refers to the text of the program, as opposed to its execution. A statically scoped language searches the program text, starting from the current nested procedure, and moving outwards through its enclosing procedures until it finds a procedure that declares the variable.
- In the example below, accesses the variable of procedure with value .
- If you were to remove the declaration
val w = 5
for a statically-typed language, it would give you a"w" Not Found Error
, even though you declare it ing()
- Dynamic Scope: The word dynamic refers to run time, the execution of the program. A dynamically scoped language uses a stack-like structure to search for the variable to access. (This is more complicated to implement, because we have to consider all possible stacks that could occur at run time, so every single procedure, until you find one).
- accesses the variable of procedure with value
Most modern programming languages are defined with static scope because it is easier to reason about: to find the variable w
that procedure h
accesses, just start at h
and look outwards through the program text.
in CS241E, we implement statically scoped variables.
Implementing Nested Procedures in CS241E
We could use the idea of trying to follow the dynamicLink
variable, but we also don’t know how many frames are in between. We add another pointer called the static link.
Static Link: Holds the address of the most recent frame of its directly enclosing procedure.
Accessing outer variables
To generate code to access variable w
from inside procedure h
, a compiler generates the following accesses:
- Read the parameter pointer in the frame of
h
to find the parameters ofh
- Read the static link in the parameters of
h
to find the frame of the directly enclosing proceduref
. - Access the variable
w
in the frame off
Nesting depth of a procedure: Number of levels of outer procedures that enclose it
Computing Static Links
We group the static link with the parameters of a procedure.
We will make it the responsibility of the caller to compute the correct static link address and pass it to the callee in the same way as if it were just another extra argument.
We define depth as the deeper inside {}, the greater the depth.
To reach the frame of a procedure with the depth of enclosing from the caller procedure, we need to read static links times, where Since , we have the following in terms of caller and callee (but I think the above is more intuitive):
Example: Using the functions above, when procedure k
calls out to procedure g
, , so we read two static links to determine the static link for g
.