Implementation of nested functions can be more involved than it may appear, as a reference to a nested function that references non-local variables creates a
closure. For this reason nested functions are not supported in some languages such as C, C++ or Java as this makes compilers more difficult to implement. However, some compilers do support them, as a compiler specific extension. A well known example of this is the
GNU C implementation of C which shares code with compilers for languages such as Pascal, Ada and Modula.
Access of non-local objects There are several ways to implement nested procedures in a lexically scoped language, but the classic way is as follows: :Any
non-local object, X, is reached via access-links in the
activation frames on the machine stack. The caller, C, assists the called procedure, P, by pushing a
direct link to the
latest activation of P's immediate lexical encapsulation, (P), prior to the call itself. P may then quickly find the right activation for a certain X by following a
fixed number (P.depth – X.depth) of links (normally a small number). :The caller creates this direct link by (itself) following C.depth – P.depth + 1 older links, leading up to the latest activation of (P), and then
temporarily bridging over these with a direct link to that activation; the link later disappears together with P, whereby the older links beneath it may come into use again. :Note that P is visible for, and may therefore be called by, C if (P) = C / (C) / ((C)) / etc. This original method is faster than it may seem, but it is nevertheless often optimized in practical modern compilers (using
displays or similar techniques). Another way to implement nested functions that is used by some compilers is to convert ("lift") nested functions into non-nested functions (where extra, hidden, parameters replace the access links) using a process known as
lambda lifting during an intermediate stage in the compilation.
Functions as values In order for local functions with
lexically scoped nonlocals to be passed as results, the language runtime code must also implicitly pass the environment (data) that the function sees inside its encapsulating function, so that it is reachable also when the current activation of the enclosing function no longer exists. This means that the environment must be stored in another memory area than (the subsequently reclaimed parts of) a chronologically based execution stack, which, in turn, implies some sort of freely
dynamic memory allocation. Many older Algol based languages (or dialects thereof) does therefore not allow local functions that access nonlocals to be passed as return values, or do they not allow functions as return values at all, although passing of such functions as arguments may still be possible.
No-execute stacks GCC's implementation of nested functions causes a loss of
no-execute stacks (NX stacks). This implementation calls nested functions through a
jump instruction placed on the machine stack at runtime. This requires the stack to be executable. No-execute stacks and nested functions are therefore mutually exclusive in GCC. If a nested function is used in the development of a program, then the NX stack is silently lost, unless GCC is called with the ‑Wtrampoline option to alert of the condition. Software engineered using
Secure Development Lifecycle often do not allow the use of nested functions in this particular compiler due to the loss of NX stacks. == See also ==