Está en la página 1de 10

A Correspondence between Continuation Passing Style

and Static Single Assignment Form

Richard A. Kelsey
NEC Research Institute
kelsey@research.nj.nec.com

Abstract 1 Introduction
We dene syntactic transformations that con- Continuation-passing style has been used as an
vert continuation passing style (CPS) programs intermediate language in a number of compilers
into static single assignment form (SSA) and vice for functional languages 1, 8, 12]. Static single
versa. Some CPS programs cannot be converted assignment form has been used in optimizations
to SSA, but these are not produced by the usual targeted towards imperative languages, for exam-
CPS transformation. The CPS!SSA transforma- ple eliminating induction variables 13] and par-
tion is especially helpful for compiling functional tial redundancies 2]. In this paper we dene syn-
programs. Many optimizations that normally re- tactic transformations for converting continuation
quire ow analysis can be performed directly on passing style (CPS) programs into static single as-
functional CPS programs by viewing them as SSA signment form (SSA) and vice versa.
programs. We also present a simple program The similarities between CPS and SSA have
transformation that merges CPS procedures to- been noted by others 1, 9]. In CPS there is
gether and by doing so greatly increases the scope exactly one binding form for every variable and
of the SSA ow information. This transformation variable uses are lexically scoped. In SSA there is
is useful for analyzing loops expressed as recursive exactly one assignment statement for every vari-
procedures. able, and that statement dominates all uses of the
Permission to copy without fee all or part of this material is variable. This is also the main dierence between
granted provided that the copies are not made or distributed the two: the restriction on variable references in
for direct commercial advantage, the ACM copyright notice CPS is lexical, while in SSA it is dynamic.
and the title of the publication and its date appear, and notice
is given that copying is by permission of the Association for The two forms have generally been used in very
Computing Machinery. To copy otherwise, or to republish, dierent contexts. CPS has been used in com-
requires a fee and/or specic permission.
pilers for functional languages, and SSA for im-
IR'95-1/95 San Francisco, California USA perative ones. As a result, the problem of ow
c 1995 ACM
analysis has come to be viewed as more dicult

13
in CPS. This is really an artifact of the programs dierences between SSA and CPS, followed by a
being compiled and not a problem with the CPS comparison to previous work.
intermediate language. Functional programs ex-
press control ow through the use of procedures, 2 Static Single Assignment
resulting in large collections of small procedures,
as opposed to small collections of large procedures SSA is an imperative form in which there is ex-
in imperative languages (by `large' procedure we actly one assignment for every variable and that
mean one large enough to contain a loop). The assignment dominates all uses of the variable (see
writers of compilers for imperative languages have 4] for a good overview of SSA).
been quite successful with using SSA to express To make the control-ow graph explicit, control
the results of intraprocedural ow-analysis and ow is expressed entirely in terms of if and goto.
then analyzing the SSA program. CPS uses pro- We allow expressions in some nonstandard places,
cedures to express practically everything, so any- for example as the arguments to the -functions
thing but the most local optimization appears to removing these only requires introducing a few
require interprocedural analysis, which is hard in additional assignment statements. The syntax of
any language. expressions does not matter and is left unspeci-
In this paper we are not going to concern our- ed, with the restriction that they may not con-
selves with interprocedural ow analysis. What tain procedure calls (and they typically don't in
we will do is restrict our notion of what consti- SSA languages).
tutes a procedure in CPS. The forms in CPS The grammar for a procedure in our SSA lan-
programs will be annotated to indicate which rep- guage is:
resent full procedures and which are continua-
tions. This reduces the number of full procedures P ::= proc(x*) f B L* g
and greatly simplies analyzing the program. L ::= l : I* B
Throughout the paper we will assume that any I ::= x  (E*)
use of lexical scoping in the source program has B ::= x  E B j x  E(E*) B j
been implemented by the introducing explicit en- goto l  j
vironments, as described in 1, 7]. We further return E j return E(E*) j
i

assume that in the CPS programs continuations if E then B else B


are created and used in a last-in/rst-out man- E ::= x j E+ Ej : : :
ner (see section 6 for a discussion). The lat- where x 2 variables
ter restriction only aects the way in which non- l 2 labels
local returns, such as longjumps in C or call-with-
current-continuation in Scheme, are expressed in The semantics is the `obvious' one.  is as-
CPS. signment, E(E, : : : ) is a procedure call, and
The paper proceeds as follows. Section 2 con- return returns from the current procedure. The
tains the denition of an SSA language. Section 3 -functions at the beginning of a block each take
denes a source language, an annotated CPS lan- one argument for each of the goto's that jump to
guage, and an algorithm for converting source that block. The i'th argument is returned when
programs into CPS programs. The following two control reaches the block from goto l .
sections dene functions that convert CPS proce- i

Cytron et al. 4] describe a translation al-


dures into SSA procedures and vice versa. The gorithm that eciently converts programs into
remainder of the paper is a discussion of practical SSA while introducing the minimum number of

14
-functions. suitable analysis (assuming the CPS program is
Because every variable has a unique assign- in a suitable form see section 6 below).
ment, denition$use chains are trivial to com- Our source language is a subset of Scheme 3],
pute. Many analyses and optimizations are sim- with the subset chosen as a compromise between
pler when applied to a program in SSA form than simplicity and realism. For simplicity we will as-
to the original source program. sume that the source and CPS languages use the
Below is an example SSA procedure that counts same expressions as in the SSA language of the
the number of times zero appears in the sequence previous section. In the context of Scheme pro-
f(0) : : : f(limit-1) for some function f and in- grams we will refer to the equivalents of the SSA
teger limit. Note that some of the computation expressions as trivial expressions, to keep from
occurs in the -functions. In particular the sec- confusing them with other Scheme expressions.
ond if makes sense only in the context of the As described above, the main restriction on (triv-
-function for c at label j. We will be using this
0
ial) expressions is that they cannot contain pro-
example throughout the paper. cedure calls.
proc (f limit) f To simplify the CPS algorithm the source lan-
guage is restricted to allow non-trivial expressions
goto l0 
l:i 
(0, i+1) only in tail position or as the bound value in a
c 
(0, c0 ) let. In an actual compiler the source program
could be put in this form either by a pre-pass or
if i = limit then
return c
as part of a more complex CPS algorithm. We
else
also assume that every identier is unique.
x f(i)  A loop expression is a version of Scheme's
named-let with the restriction that calls to the
if x = 0 then
goto j0 
label may only occur in tail position. It is in-
else
cluded to show how iterative constructs, such as
goto j1  g for and while loops, may be converted into CPS.
j:c0 
(c+1, c) The grammar for this Scheme subset is:
goto l1  g M ::= E j (E E*) j (if E M M) j
(let ((x M)) M) j
3 Annotated CPS (loop l ((x E)*) M) j
(l E*)
In continuation passing style procedures do not E ::= x j (+ E E) j : : :
return. Instead they are passed an additional ar- P ::= ( (x*) M)
gument, a continuation, which is applied to the where x 2 variables
procedure's return value (see chapter 8 of 5] for l 2 labels
a full discussion).
The correspondence between CPS and SSA re- The semantics of the source language is that
quires a slightly modied algorithm for converting of Scheme. This subset is sucient to implement
programs into CPS. The modied algorithm an- most of Scheme, with explicit cells added for any
notates the forms in the CPS code to show how variables that are the targets of set! expressions
they are used. The annotations have no semantic in the source program.
content and, if not introduced by the CPS algo- As was done in the Rabbit compiler 12] our
rithm, could be added to the program via some
15
F : MC!M 0

F ( E, k] ) = (k E)
F ( E, ( cont (x) M )] ) = (let ((x E)) M )
0 0

F ( (E : : : ), C]]) = (let ((v (E : : : ))) (j v)) if C = x and x is bound by letrec


= (E : : : C) otherwise
F ( (let ((x M )) M ), C]]) = F ( M , ( (x) F ( M , C]]))] )
F ( (if E M M ), k] ) = (if E F ( M , k] ) F ( M , k] ))
1 2 1 2

F ( (if E M M ), ( cont (x) M )] ) =


1 2 1 2
0

(letrec ((x ( jump (x) M ))) (if E F ( M , x] ) F ( M , x] )))


1 2
0

F ( (loop l ((x E ) : : : )M), C]]) =


1 2

(letrec ((l ( jump (x : : : ) F ( M, C]])))) (l E


initial

: : : ))
F ( (l E : : : ), C]]) = (l E : : : )
initial

V: P!P 0

V ( ( (x : : : ) M)] ) = ( proc (x : : : k) F ( M, k] ))
Figure 1: Conversion to CPS

conversion to CPS will treat trivial expressions as The grammar for the CPS language is as fol-
values and not introduce continuations for them. lows:
In the CPS grammar all 's are annotated as
being either proc, cont, or jump. The annotations M ::= (E E* C) j
0

indicate how the 's are used, and, equivalently, (k E) j


how they can be compiled. (if E M M ) j 0 0

Proc is used as the translation of the forms (let ((x E)) M ) j 0

in the source program. These are full procedures (letrec ((x P )) M ) 0 0

that eventually return a value and for this reason C ::= k j ( cont (x) M ) 0

take a continuation as an argument. The cont P ::= ( proc (x* k) M )j


0 0

and jump forms are continuations that are used ( jump (x*) M ) 0

in slightly dierent ways. The cont continuations where x,k 2 variables


are return points for calls to proc's. Jump indi-
cates that the continuation is called within the The semantics is the obvious call-by-value se-
current procedure instead of being passed to an- mantics. The annotated 's are all just , let is
other one. The CPS algorithm introduces jump syntactic sugar for , and so on.
continuations when the two arms of a conditional The identiers x and k used in the grammar
have to rejoin at a common point and for the bod- are members of the same syntactic class. Mak-
ies of loop's. ing them syntactically distinct, as is sometimes
In terms of compilation strategy, cont 's are re- done 8], restricts how continuations are used and
turn points, jump's can be compiled as gotos, and makes CPS and SSA entirely equivalent (see Sec-
proc's require a complete procedure-call mecha- tion 6).
nism. The function F dened in Figure 1 translates
source expressions M to CPS expressions M . It 0

16
( proc (f limit k)
(letrec ((l ( jump (i c)
(if (= i limit)
(k c)
(f i ( cont (x)
(letrec ((j ( jump (c )
0

(l (+ i 1) c0 ))))
(if (= x 0)
(j (+ c 1))
(j c)))))))))
(l 0 0)))

Figure 2: Example program in CPS

takes a continuation C, which is either an identi- which the jump 's are bound are calls to those
er or a cont , as its second argument. variables.
F has two rules for applications. The rst rule The following is the sample SSA procedure from
is used when the continuation argument is an above written in the source language for the CPS
identier bound by a letrec in the rule for if transformation:
and ensures that all uses of such identiers are
called directly. The second is used in all other ( (f limit)
cases. For let a new continuation is created for (loop l ((i 0) (c 0))
the value. Identier continuations are propagated (if (= i limit)
through if's to avoid code expansion continu- c
ations (as opposed to continuations that are just (let ((x (f i)))
an identier) are marked as jump and bound to (let ((c0 (if (= x 0)
an identier. Loop is translated into a recursive (+ c 1)
continuation. The loop begins by calling the con- c)))
tinuation on the initial values of the iterative vari- (l (+ i 1) c0 ))))))
ables. Calls to the loop's label become calls to the
recursive continuation, ignoring the current con- Figure 2 presents the CPS version of the same
tinuation. procedure. A cont is introduced as the continu-
As we are not interested in interprocedural ation for the call to f and jump 's are used as the
analysis we will treat each proc as a separate pro- join point for the if and for the loop.
gram (here we depend on the assumption that ex-
plicit environments have been introduced to take
care of lexical scoping for any nested proc 's). Be-
4 Converting CPS to SSA
cause they are called at the point they are created, In this section we dene a syntactic translation
cont 's can be considered as inlined procedures. that converts CPS procedures into SSA proce-
The call sites of jump 's are easily found: the dures.
jump 's only occur as the bound value in letrec's. The function G in Figure 3 translates non-
Furthermore, all references to the variables to trivial CPS expressions to SSA statements. The

17
G: M !B0

G( (let ((x E)) M )] ) = x  E G( M ] )


0 0

G( (E : : : ( cont (x) M ))] ) = x  E( : : : ) G( M ] )


0 0

G( (E : : : k)] ) = return E(: : : )


G( (k E)] ) = return E
G( (j E E : : : )] ) = goto j 
G( (if E M M )] ) = if E then G( M ] ) else G( M ] )
0i 1i i
0 0 0 0

G( (letrec ( : : : ) M )] ) = G( M ] )
1 2
0 0
1 2

Gproc : P ! P0

Gproc ( ( proc (x : : : ) M )] ) = proc(x : : : k)f G( M ] ) Gjump ( ( jump : : : )] ) : : : g


0 0

Gjump : j  ( jump (x : : : ) M ) ! L 0

Gjump ( j, ( jump (x : : : ) M )] ) = j : x (E , E , : : : ) : : : G( M ] ))


0
00 01
0

Figure 3: Translation of CPS to SSA. The E on the right-hand side of the denition of G jump are
those from the left-hand side of the denition of G ( (j : : : )] ).
ij

simple binding forms, let and cont , become as- the original SSA example from above.
signments. If is essentially the same in both syn-
taxes. Uses of a proc 's continuation variable be- 5 Converting SSA to CPS
come return's while calls to letrec-bound con-
tinuation variables are translated as gotos. We would like to produce an inverse of G to con-
The jump 's in the program are ignored when vert SSA programs to CPS. The function H in
found by G . Each jump is instead lifted up to be- Figure 4, produced by a simple editing of the def-
come a labeled block in the SSA procedure. The inition of G , is almost an inverse of G . The di-
arguments to the jump 's, which are also ignored culty is the rule for the letrec's that bind jump 's.
by G , become the arguments to the -function In translating jump 's to labeled blocks G ignores
that denes the value of the corresponding vari- their position in the CPS program. Translating a
able in the SSA program. In the denition of labeled block back into a jump is straightforward,
Gjump , E0 1 is the rst argument to the second

but we need to bind the jump with a letrec
call (in some arbitrary ordering) to j, the vari- somewhere in the newly created CPS program.
able bound to ( jump (x : : : ) M ). That call is0
The jump 's need to be placed such that no vari-
translated as goto j1 . able is referred to outside the form that binds it.
The translated program is syntactically correct, Our placement algorithm uses the dominator
and it obeys the SSA restriction that there is tree of the SSA program. Statement M0 is said
exactly one assignment per variable (since each to dominate M1 if M0 appears in every execution
variable is bound exactly once in the CPS pro- path between the start of the program and M1 . If
gram). Variables in the translated program are M2 also dominates M1 then either M2 dominates
assigned the values of the same expressions they M0 or vice versa. The dominator relation thus
were bound to in the CPS program, and evalua- organizes a program's statements into a tree. The
tion order is preserved, so the two programs pro- immediate dominator of M is M's parent in the
duce identical results. dominator tree.
Applying G proc to the CPS example produces Given a labeled block, J : I* B, in the SSA

18
H : B! M 0

H( x  E M]]) = (let ((x E)) H( M]]))


H( x  E( : : : ) M]]) = (E : : : ( cont (x) H( M]])))
H( if E then M else M ] ) = (if E H( M ] ) H( M ] ))
H( return E(: : : )] ) = (E : : : k)
1 2 1 2

H( return E] ) = (k E)
H( goto J ] ) = (j E E : : : )
Hproc : P ! P
i 0i 1i
0

Hproc ( proc(x : : : k)fB L*g] ) = ( proc (x : : : ) G( B]]))


Hjump : L ! ( jump (x : : : ) M ) 0

Hjump ( j : x (E , E , : : : ) : : : B]]) = ( jump (x : : : ) H( B]]))


00 01

Figure 4: Translation of SSA to CPS. The E on the right-hand side of the denition of H( goto J ] )
are those from the left-hand side of the denition of Hjump .
ij i

program, with M the immediate dominator of I* tor were a binding form, but this cannot happen.
B, we will replace H( M]]) with If (let ((x E)) M ) or (E : : : ( cont (x) M ))
0 0

(letrec ((j Hjump ( I* B]]))) H( M]])) dominates a jump , then M does as well.
0

in the CPS procedure. If two or more labels have The arguments to the -functions are also
the same immediate dominator their jump 's are placed so as to be lexically inferior to their dom-
placed in a single letrec. inators. QED.
Theorem: all uses of variables in the CPS pro- Using H to convert the original SSA example
gram produced by H are properly in scope. to CPS produces a program identical to the CPS
Proof: We know that every use of a variable in program shown in Figure 2.
the SSA program is dominated by the variable's
assignment statement. Assignment statements in
the SSA program correspond to binding forms in 6 Why CPS and SSA Are Not
the CPS program. By inspection H preserves the Identical
dominator tree, so it is sucient to show that
every statement in the CPS program is lexically The function G cannot be applied to all CPS pro-
inferior to its immediate dominator, and thus to grams. It depends on the 's being correctly an-
all its dominators, including the binding forms for notated, which in turn depends on continuations
any referenced variables. being used in a somewhat restricted fashion. If
Again inspecting the denition of H, we can non-local returns, such as longjumps in C or call-
see that when the M produced by H is the body
0 with-current-continuation in Scheme, are trans-
of either a LET, a proc , or a cont , or if it is ei- lated into uses of continuations in the CPS pro-
ther arm of an if, then it is lexically inferior to gram there is no way to label the continuations so
its immediate dominator. The remaining possible used. They are neither simply passed as a proce-
location for an M is as the body of a jump , and
0 dure's continuation, nor are all of their calls tail-
each jump is by construction lexically inferior to recursive calls within the procedure in which they
the dominators of its immediate dominator. This were created, so neither cont or jump is appro-
would lead to a problem if the immediate domina- priate. A fourth annotation could be introduced

19
( proc (f limit k)
(letrec ((l ( proc (i c k ) 0

(if (= i limit)
(k0 c)
(f i ( cont (x)
(letrec ((j ( jump (c )
0

(l (+ i 1) c0 k0 ))))
(if (= x 0)
(j (+ c 1))
(j c)))))))))
(l 0 0 k)))

Figure 5: Example program using Scheme's named-let translated into CPS.

for continuations that are created in one proce- 8 Compiling (Mostly) Func-
dure and called in another. There would still be
no direct way to represent the program in SSA.
tional Programs
For programs that do not side-aect the values
7 Compiling Imperative Pro- of variables, viewing CPS procedures as SSA pro-
cedures shows that CPS nicely reects intrapro-
grams cedural denition$use associations without any
We have shown that programs can be translated need for ow analysis. There is still a problem.
into CPS and from there to SSA programs by Programs written in languages such as ML and
a series of syntactic transformations. Producing Scheme tend to have few side-aected variables,
an SSA program normally requires ow-analysis, making dataow visible as discussed above. The
as the program directly expresses use$denition diculty is that these same languages use recur-
chaining. Where is the ow information in the sion to express iteration. They do not use itera-
CPS program coming from? tive constructs like loop in the CPS source lan-
The source program for the CPS transforma- guage used above. So while we get intraprocedu-
tion is a functional program, and as such con- ral ow information more or less for free, what we
tained the required ow information. If we had really want is interprocedural information.
started with an imperative program, meaning one Interprocedural analysis is dicult, but we can
using set! to modify the values of variables, instead take the approach of increasing the size of
translation into our CPS source language would the procedures. The idea is to nd a set of proce-
have required adding explicit cells to hold the val- dures all of which are always called with the same
ues of all variables that were the targets of set! continuation, and then to substitute that contin-
expressions. The jump 's in the resulting CPS pro- uation for the procedures' continuation variables.
gram would take no arguments and there would The procedures are then themselves continuations
be no -functions in the corresponding SSA pro- nested within a single large procedure, removing
gram, only a lot of stores and fetches. Transform- any need for interprocedural information.
ing such a program into a more useful form would More precisely, given a set procedures P0 : : : P n

require doing some ow-analysis, similar to that bound by one or more letrec forms to identiers
done in translating imperative programs to SSA. f0 : : : f and a continuation C such that every use
n

of f is either a tail-recursive call from within P or


i j

20
a non-tail-recursive call being passed continuation scoping, and all uses of the f are at or below the
i

C, we can perform the following transformation. inserted letrec that now binds them.
Let P = ( proc (: : : k ) M ). If C is ( cont : : : ),
i i i The function G can be applied to the trans-
let j be a new identier if C is an identier, let j formed program to produce an equivalent SSA
be that identier. version. We have created more jump 's, but they
obey the same restrictions as the ones created
1. Replace all references to the k with j and
i by the CPS algorithm: the jump 's are bound by
remove them from the variable lists of the letrec, all uses of the variables to which they are
P , changing the P from proc 's to jump 's.
i i bound are tail calls, and the bindings and uses all
2. Remove the continuation from all calls to the lie within a single proc (because any outlying P i

f.i
were moved in step 3 of the transformation).
3. Let M be the smallest form containing every
non-tail-recursive call to the f . Replace M 9 Related Work and Conclu-
i

with (letrec (: : : ) M) where (: : : ) binds j sion


to C if C = ( cont : : : ) and also binds f to
The similarity between CPS and SSA has been
i

P for every f whose original binding form is


noted by others. Appel 1] and O'Donnell 9]
i i

lexically apparent at M.
both briey describe the relationship between -
Because we restricted ourselves to having the f i functions and parameters to procedures whose
be bound by letrec and being called directly (as call sites are known. Here we have shown that the
opposed to being passed to another procedure and correspondence is exact, and, more importantly,
then being called, for example), this is a purely goes both ways. The main dierence between a
syntactic transformation. More sophisticated ver- CPS procedure and an SSA procedure is the syn-
sions are clearly possible. The simple syntactic tax. Compiler writers can use a single represen-
version presented here applies to many common tation and take advantage of both the work on
uses of recursive procedures. intraprocedural optimizations that has been done
If our CPS source program used Scheme's using SSA and the work on interprocedural opti-
named-let syntax instead of the restricted loop mizations done using CPS.
version used above, applying G to it would pro- The other contribution of this paper is that the
duce the program shown in Figure 5. The recur- correspondence can be made to be useful. As long
sive procedure is now a full procedure. Applying as procedures are too small to contain loops, con-
the above transformation to this program, with sidering them as SSA procedures does not help
P0 = ( proc (i c k ) : : : ) and C = j = l, pro-
0
much. We have shown how to merge looping pro-
duces the procedure shown in Figure 2. cedures together such that the result can treated
We need to show that the transformation is as a single procedure (a restricted and somewhat
correct and preserves the map to SSA. Substitut- more complex version of this transformation is
ing the value C (or an identier bound to C) for mentioned in two of our earlier papers, 6, 7], but
the variables k is safe, because the k are always
i i without any discussion of the implications for pro-
bound to that value. Scoping is preserved, be- gram analysis). Without this transformation ana-
cause any free identiers in C are in scope at M, lyzing loops that are expressed as recursive proce-
otherwise they would be out of scope at some oc- dures requires interprocedural analysis, as in 11],
currence of C in the original program. Moving and in this case using CPS may be more dicult
the P to a lexically inferior form also preserves
i than necessary 10].
21
References optimizing compiler for scheme. In
Proceedings SIGPLAN '86 Symposium on
1] Andrew W. Appel. Compiling with Compiler Construction, 1986. SIGPLAN
Continuations. Cambridge University Press, Notices 21 (7), July, 1986, 219-223.
Cambridge, 1992.
9] Ciaran O'Donnell. High level compiling for
2] Preston Briggs and Keith D. Cooper. low level machines. PhD thesis, Ecole
Eective partial redundancy elimination. In Nationale Sup!erieure des
Proceedings ACM SIGPLAN '94 Conference T!el!ecommunications, 1994.
on Programming Language Design and
Implementation, pages 159{170, 1994. 10] Amr Sabry and Matthias Felleisen. Is
continutation-passing useful for data ow
3] William Clinger and Jonathan Rees. analysis? In Proceedings of the ACM
Revised4 report on the algorithmic language SIGPLAN '94 Conference on Programming
Scheme. ACM Lisp Pointers, 4(3):1{55, Language Design and Implementation,
1991. pages 1{12, 1994.
4] Ron Cytron, Jeanne Ferrante, Barry K. 11] Olin Shivers. Control-Flow Analysis of
Rosen, Mark N. Wegman, and F. Kenneth Higher-Order Languages or Taming
Zadeck. Eciently computing static single Lambda. PhD thesis, School of Computer
assignment form and the control Science, Carnegie-Mellon University, 1991.
dependence graph. ACM Transactions on
Programming Languages and Systems, 12] Guy L. Steele. Rabbit: A compiler for
13(4):451{490, 1991. Scheme. Technical Report 474,
Massachusetts Institute of Technology,
5] Daniel P. Friedman, Mitchell Wand, and Cambridge, MA, May 1978.
Christopher T. Haynes. Essentials of
Programming Languages. MIT Press, 13] Michael Wolfe. Beyond induction variables.
Cambridge, MA, 1992. Also McGraw-Hill, In Proceedings of the ACM SIGPLAN '92
Chicago, 1992. Conference on Programming Language
Design and Implementation, pages 162{174,
6] Richard Kelsey. Compilation by program 1992.
transformation. Technical Report
YALEU/DCS/TR-702, Department of
Computer Science, Yale University, New
Haven, CT, 1989.
7] Richard Kelsey and Paul Hudak. Realistic
compilation by program transformation. In
Conf. Rec. 16 ACM Symposium on
Principles of Programming Languages,
pages 281{292, 1989.
8] David A. Kranz, Richard Kelsey,
Jonathan A. Rees, Paul Hudak, James
Philbin, and Norman I. Adams. Orbit: An

22

También podría gustarte