Thu Oct 20 12:09:27 EDT 2011

Compiling letrec

/* The following Scheme code illustrates what we want to do: allow for
   mutually recursive procedures that live in a shared lexical
   context, and that have private lexical content of their own.

   All variable bindings are final; no set! in the source language
   representation.  Assignment is used to bind function parameters.

(let ((a 0)
      (b 0))
      ((fun1 (lambda (x y)
               (let ((c x)
                     (d y))
                 (fun2 c d))))
       (fun2 (lambda (x y)
               (let ((c x)
                     (d y))
                 (fun1 c d)))))
    (fun1 a b)))

void test(void) {

    /* Top-level lexical env in which fun is defined.  These are
       visible from the fun1 and fun2 code bodies. */
    const int a = 0;
    const int b = 0;

    /* Function arguments for all functions defined on this level.

       Note that on the C level, all variables are visible to all
       functions defined in this basic block, which is an artifact of
       the compilation.  The original form of the code of course does
       not have such a lexical structure.  For this reason, the names
       are prefixed with the function name they belong to. */

    int fun1_x, fun1_y;
    int fun2_x, fun2_y;

    /* First call. */
    fun1_x = a;
    fun1_y = b;
    goto fun1;

    /* Function bodies. */
        // fun's internal lexical environment.
        const int c = fun1_x;
        const int d = fun1_y;
        // Recursive tail call
        fun2_x = c;
        fun2_y = d;
        goto fun2;
        // fun's internal lexical environment.
        const int c = fun2_x;
        const int d = fun2_y;
        // Recursive tail call
        fun1_x = c;
        fun1_y = d;
        goto fun1;