next up previous
Next: Implementation and Practicalities Up: But Mom, I don't Previous: Analysis

Transformation

First, let's recall the global CPS transformation:

\begin{displaymath}\begin{array}{rcl}
\mathcal{C}[\![ x ]\!]k & = & k\mbox{\tt ...
...)} ]\!]k & = & f\mbox{\tt (}k,\vec{x}\mbox{\tt )}
\end{array} \end{displaymath}

How does this translate into local CPS conversion? First, we choose the set of functions that are eligible for CPS conversion:

\begin{displaymath}\mathcal{E} = \{ f : \Gamma(f) \in \mathsf{Label} \} \end{displaymath}

Now, we define the local CPS conversion as follows:

\begin{displaymath}\begin{array}{rcl}
\mathcal{L}[\![ x ]\!]k & = & k\mbox{\tt ...
...)} & & f \not\in \mathcal{E}
\end{array} \right.
\end{array} \end{displaymath}


\begin{displaymath}\begin{array}{rcl}
Split(x) & = & \mathsf{false} \\
Split(...
...e} & & f \not\in \mathcal{E}
\end{array} \right.
\end{array} \end{displaymath}

Returning to our running example, local CPS transformation results in the following program:

fun applyf (f, n) =
  fun lp_i i = 
    if i < n
      then fun lp_j (k, j) =
             if j < n
               then let foo = f (i, j) in
                    lp_j (k, j + 1)
               else k () in
           fun k' (bar) = lp_i (i + 1) in
           lp_j (k', 0)
      else () in
  lp_i 0

Well, that's nice, but have we gained anything? It depends on how we compute $\mathcal{F} \subseteq \mathsf{Known}$. A course analysis says that not all call sites of k' are known (because k' escapes at the tail-call lp_j (k', 0)), so k' becomes it's own cluster; lp_i neest to be accessible from k''s cluster and applyf's cluster, so it will be placed in its own cluster, but lp_j can be in lp_i's cluster. Unfortunately, were still required to make a full function call during each iteration of the outer loop (when lp_j returns via it's continuation).

But, we know that lp_j has one continuation; if we reverse the definitions of lp_j and k', we can drop lp_j's explicit continuation argument:

fun applyf (f, n) =
  fun lp_i i = 
    if i < n
      then fun k' (bar) = lp_i (i + 1) in
           fun lp_j (j) =
             if j < n
               then let foo = f (i, j) in
                    lp_j (j + 1)
               else k' () in
           lp_j 0
      else () in
  lp_i 0

In general, this requires mutual recursion in the target language.

Finally, we use light-weight closure conversion to generate the final cluster representation:

fun applyf (f, n) = lp_i (0, f, n)
and lp_i (i, f, n) = 
  if i < n
    then lp-j (0, i, f, n)
    else ()
and lp_j (j, i, f, n) =
  if j < n
    then let foo = f (i, j) in lp_j (j + 1, i, f, n)
    else k (i, f, n)
and k (i, f, n) = lp_i (i + 1, f, n)


next up previous
Next: Implementation and Practicalities Up: But Mom, I don't Previous: Analysis
Matthew Fluet 2002-02-22