The idea of the Scheme stack is central to a lot of debugging. The Scheme stack is a reified representation of the pending function returns in an expression’s continuation. As Guile implements function calls using a stack, this reification takes the form of a number of nested stack frames, each of which corresponds to the application of a procedure to a set of arguments.
A Scheme stack always exists implicitly, and can be summoned into
concrete existence as a first-class Scheme value by the
make-stack call, so that an introspective Scheme program – such
as a debugger – can present it in some way and allow the user to query
its details. The first thing to understand, therefore, is how Guile’s
function call convention creates the stack.
Broadly speaking, Guile represents all control flow on a stack. Calling a function involves pushing an empty frame on the stack, then evaluating the procedure and its arguments, then fixing up the new frame so that it points to the old one. Frames on the stack are thus linked together. A tail call is the same, except it reuses the existing frame instead of pushing on a new one.
In this way, the only frames that are on the stack are “active” frames, frames which need to do some work before the computation is complete. On the other hand, a function that has tail-called another function will not be on the stack, as it has no work left to do.
Therefore, when an error occurs in a running program, or the program hits a breakpoint, or in fact at any point that the programmer chooses, its state at that point can be represented by a stack of all the procedure applications that are logically in progress at that time, each of which is known as a frame. The programmer can learn more about the program’s state at that point by inspecting the stack and its frames.
|• Stack Capture:||Reifying a continuation.|
|• Stacks:||Accessors for the stack data type.|
|• Frames:||Likewise, accessors for stack frames.|