Sequence 3.3 – Stack frames

Pablo Oliveira & Samuel Tardieu

Accessing variables

let function fact(n: int): int =
      if n <= 1 then 1 else n * fact(n-1)
in
  fact(5)
end

Function frames

Back to our example

let function fact(n: int): int =
      if n <= 1 then 1 else n * fact(n-1)
in
  fact(5)
end

The stack frames

let function fact(n: int): int =
      if n <= 1 then 1 else n * fact(n-1)
in
  fact(5)
end

You can ignore the up pointer for the moment

Putting everything together

Accessing outside variables

let var a := 3
    function add(b: int) = a := a + b
in
  add(2);
  print_int(a)  /* Prints 5 */
end

Accessing variables more than one level above

let var a := 3
    function f(b: int) =
      let function add() = a := a + b
    in add() end
in
  f(2); print_int(a)  /* Prints 5 */
end

Visualizing the stack frames

let var a := 3
    function f(b: int) =
      let function add() = a := a + b
    in add() end
in
  f(2); print_int(a)  /* Prints 5 */
end

Knowing how far to walk the frames chain up

Annotated example

let var a/*e*/ := 3
    function f(b/*e*/: int) = 
      let function add() = a/*2*/ := a/*2*/+b/*1*/
      in add() end
in
  f(2); print_int(a)  /* Prints 5 */
end

Sibling functions

let var a := 3
    function f(): int = a + a
    function g(): int = f() + f()
in
  print_int(g())  /* Prints 12 */
end

Choosing the extra frame parameter to pass

For example, a recursive call to the current function will walk the frames chain one time (a function is its own sibling). As a consequence, it will give itself the same frame that it has received.

Visualizing the sibling stack frames

let var a/*e*/ := 3
    function f(): int = a/*1*/ + a/*1*/
    function g(): int = f() + f()
in
  print_int(g())  /* Prints 12 */
end

Conclusion