so far we’ve only been writing statements at the top level of the program. there’s no notion of a callable chunk of code. with the introduction of functions in chapter 24, all the current top level states like the compiler, locals, and chunks / instructions are moved into function objects
previously with locals we were effectively operating in a single function world. this effectively meant that all locals were allocated at the beginning of the global call stack. with functions that each have their own local environments, the author introduces an early idea that was implemented by fortran where different functions had their own fixed set of locals
this works if there’s no recursion and i’ll demo an example that shows why fixed, separate slots break down once you start to recurse:
fun factorial(n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}
factorial(3);
assume we give factorial
its own fixed set of stack slots
Slot 0: parameter n
Slot 1: temporary result for multiplication (the value in slot 0 * factorial (slot 0 – 1))
now call factorial(2)
. this produces slot 0 = 2 and slot 1 = 2 * factorial(1)
then call factorial(1)
. this produces slot 0 = 1
OH CRAP, but that just overwrote slot 0 = 2 which we need to compute 2 * factorial (1)
from the previous call. except now it ends up calling 1 * factorial(0)
and screws up the entire expression
bob notes that fortran was able to get away with fixed stack slots simply because they didn’t support recursion!