
1) Nested functions.

2) Nested functions with non-local references.

3) Nested functions with non-local references that are dynamically scoped.

4) Nested functions with non-local references that are statically scoped.

  a) Calling a nested function (with non-local references that are statically scoped) requires a "nesting link" in function activation records.

  b) Passing a nested function (with non-local references that are statically scoped) as a parameter to another function requires nesting links and the definition of a "closure".
  (This is called the "downward funarg problem".)

  c) Returning a nested function (with non-local references that are statically scoped) as a return value from another function requires nesting links, closures, and activation records that are allocated from the heap instead of being automatically allocated on a stack (that is, we need "heap frames" instead of "stack frames").
  (This is called the "upward funarg problem".)