24
An Introduction to Partial Evaluation NEIL D. JONES University of Copenhagen Partial evaluation provides a unifying paradigm for a broad spectrum of work in program optimization, compiling, interpretation and the generation of automatic program generators [Bjørner et al. 1987; Ershov 1992; and Jones et al. 1993]. It is a program optimization technique, perhaps better called program specialization, closely related to but different from Jørring and Scherlis’ staging transformations [1986]. It emphasizes, in comparison with Burstall and Darlington [1977] and Jørring and Scherlis [1986] and other program transformation work, full automation and the generation of program generators as well as transforming single programs. Much partial evaluation work to date has concerned automatic compiler generation from an interpretive definition of a programming language, but it also has important applications to scientific computing, logic programming, metaprogramming, and expert systems; some pointers are given later. Categories and Subject Descriptors: D.2.M [Software Engineering]: Miscellaneous—rapid prototyping; D.3.4 [Programming Languages]: Processors General Terms: Experimentation, Performance, Verification Additional Key Words and Phrases: Compilers, compiler generators, interpreters, partial evaluation, program specialization 1. INTRODUCTION 1.1 Partial Evaluation 5 Program Specialization In Figure 1 a partial evaluator mix is given a subject program p together with part of its input data in1. Its effect is to construct a new program p in1 which, when given p’s remaining input in2, will yield the same result that p would have produced given both inputs. 1 Correctness of p in1 can be described equationally: for this p, in1, and all in2 vpb [in1, in2] 5 vp in1 b in2 In other words a partial evaluator is a program specializer. Intuitively, specialization is done by performing those of p’s calculations that depend only on in1, and by generating code for those calculations that depend 1 Notation: data values are in ovals and programs are in boxes. The specialized program p in1 is first considered as data and then considered as code, whence it is enclosed in both. Further, single arrows indicate program input data and double arrows indicate outputs. Thus mix has two inputs while p in1 has only one; p in1 is the output of mix. This work was partly supported by the Danish Natural Sciences Research Council and ESPRIT Basic Research Action 3124, “Semantique.” Author’s address: DIKU, Dept. of Computer Science., Univ. of Copenhagen Universitetsparken 1, DK-2100 Copenhagen East, Denmark. ^email:[email protected]&. Permission to make digital / hard copy of part or all of this work for personal or classroom use is granted without fee provided that the copies are not made or distributed for profit or commercial advantage, the copyright notice, the title of the publication, and its date appear, and notice is given that copying is by permission of the ACM, Inc. To copy otherwise, to republish, to post on servers, or to redistribute to lists, requires prior specific permission and / or a fee. © 1996 ACM 0360-0300/96/0900–0480 $03.50 ACM Computing Surveys, Vol. 28, No. 3, September 1996

AnIntroductiontoPartialEvaluationdevanbu/teaching/260/jones...Multiple language partial evaluation withdifferentinput,output,andimple-mentation languages (say S, L, T, respectively)isalsomeaningful.Anex-ampleisAMIX,apartialevaluatorwith

  • Upload
    others

  • View
    2

  • Download
    0

Embed Size (px)

Citation preview

Page 1: AnIntroductiontoPartialEvaluationdevanbu/teaching/260/jones...Multiple language partial evaluation withdifferentinput,output,andimple-mentation languages (say S, L, T, respectively)isalsomeaningful.Anex-ampleisAMIX,apartialevaluatorwith

An Introduction to Partial EvaluationNEIL D. JONES

University of Copenhagen

Partial evaluation provides a unifying paradigm for a broad spectrum of work inprogram optimization, compiling, interpretation and the generation of automaticprogram generators [Bjørner et al. 1987; Ershov 1992; and Jones et al. 1993]. It is aprogram optimization technique, perhaps better called program specialization, closelyrelated to but different from Jørring and Scherlis’ staging transformations [1986]. Itemphasizes, in comparison with Burstall and Darlington [1977] and Jørring andScherlis [1986] and other program transformation work, full automation and thegeneration of program generators as well as transforming single programs.Much partial evaluation work to date has concerned automatic compiler generationfrom an interpretive definition of a programming language, but it also hasimportant applications to scientific computing, logic programming,metaprogramming, and expert systems; some pointers are given later.

Categories and Subject Descriptors: D.2.M [Software Engineering]:Miscellaneous—rapid prototyping; D.3.4 [Programming Languages]: Processors

General Terms: Experimentation, Performance, Verification

Additional Key Words and Phrases: Compilers, compiler generators, interpreters,partial evaluation, program specialization

1. INTRODUCTION

1.1 Partial Evaluation 5 ProgramSpecialization

In Figure 1 a partial evaluator mix isgiven a subject program p together withpart of its input data in1 . Its effect is toconstruct a new program pin1 which,when given p’s remaining input in2 ,will yield the same result that p wouldhave produced given both inputs.1

Correctness of pin1 can be describedequationally: for this p, in1 , and allin2

vpb [in1, in2] 5 vpin1 b in2

In other words a partial evaluator is aprogram specializer.Intuitively, specialization is done by

performing those of p’s calculations thatdepend only on in1 , and by generatingcode for those calculations that depend

1 Notation: data values are in ovals and programsare in boxes. The specialized program pin1 is firstconsidered as data and then considered as code,

whence it is enclosed in both. Further, singlearrows indicate program input data and doublearrows indicate outputs. Thus mix has two inputswhile pin1 has only one; pin1 is the output of mix .

This work was partly supported by the Danish Natural Sciences Research Council and ESPRIT BasicResearch Action 3124, “Semantique.”Author’s address: DIKU, Dept. of Computer Science., Univ. of Copenhagen Universitetsparken 1,DK-2100 Copenhagen East, Denmark. ^email:[email protected]&.Permission to make digital /hard copy of part or all of this work for personal or classroom use is grantedwithout fee provided that the copies are not made or distributed for profit or commercial advantage, thecopyright notice, the title of the publication, and its date appear, and notice is given that copying is bypermission of the ACM, Inc. To copy otherwise, to republish, to post on servers, or to redistribute tolists, requires prior specific permission and / or a fee.© 1996 ACM 0360-0300/96/0900–0480 $03.50

ACM Computing Surveys, Vol. 28, No. 3, September 1996

Page 2: AnIntroductiontoPartialEvaluationdevanbu/teaching/260/jones...Multiple language partial evaluation withdifferentinput,output,andimple-mentation languages (say S, L, T, respectively)isalsomeaningful.Anex-ampleisAMIX,apartialevaluatorwith

on the as yet unavailable input in2 .Figure 2 shows a program to computexn, and a faster program p5 resultingfrom specializing p to n 5 5 (ignore theunderlines for now).The technique is to precompute all

expressions involving n, to unfold therecursive calls to function f , and to re-duce x*1 to x . This optimization waspossible because the program’s controlis completely determined by n. If on theother hand x 5 5 but n is unknown,then specialization gives no significantspeedup.A partial evaluator performs a mix-

ture of execution and code generationactions—surely why Ershov called theprocess “mixed computation” [Ershov1982], hence the name mix .An equational description. Programs

are both input to and output from otherprograms. We will discuss several lan-guages and so assume given a fixed setD of data values including all programtexts. A suitable choice of D is the set ofLisp’s “list” data as defined by D 5LispAtom 1 D*, e.g., (1 (2 3) 4) is a listof three elements, whose second ele-ment is also a list.We use the typewriter font for pro-

grams and for their input and output. If

p is a program in language L, then vpbLdenotes its meaning—typically a func-tion from several inputs to an output.The subscript L indicates how p is to beinterpreted. When only one language isbeing discussed we often omit the sub-script so vpbL 5 vpb. Standard languagesused in the remainder of this article are:

L: an implementation languageS: a source languageT: a target language

The program meaning function v_bL is oftype D* 3 V. Thus

output 5vpbL [in 1, in 2, . . . , in n]

results from running p on input valuesin 1, in 2, . . . , in n, where n $ 0 (out-put is undefined if p goes into an infi-nite loop).The Defining Equation. The essential

property of a partial evaluator mix isnow formulated more precisely. Supposep is a source program expecting twoinputs, in1 is the data known at stageone (static), and in2 is data known atstage two (dynamic). Then computationin one stage is described by

out 5vpb [in1, in2]

Figure 1. A partial evaluator.

Introduction to Partial Evaluation • 481

ACM Computing Surveys, Vol. 28, No. 3, September 1996

Page 3: AnIntroductiontoPartialEvaluationdevanbu/teaching/260/jones...Multiple language partial evaluation withdifferentinput,output,andimple-mentation languages (say S, L, T, respectively)isalsomeaningful.Anex-ampleisAMIX,apartialevaluatorwith

Computation in two stages using special-izer mix (as in Figure 1) is described by

pin1 5 vmix b [p, in1]out 5 vpin1 b in2

Combining these two we obtain anequational definition of mix :

vpb [in1, in2] 5vvmix b [p, in1] b in2

specialized program

Here equality needs a broader interpreta-tion than usual: it means that if one sideof the equation is defined, then the otherside is also defined and has the samevalue. This is easily generalizable to var-ious numbers of static and dynamic in-puts with a more complex notation.2

Multiple language partial evaluationwith different input, output, and imple-mentation languages (say S, L, T,respectively) is also meaningful. An ex-ample is AMIX, a partial evaluator witha functional language as input andstack code as output [Holst 1988]:

vpbS[in1, in2] 5

vvamix bL[p, in1] bT in2

specialized program

1.2 Speedups by Partial Evaluation

The chief motivation for doing partialevaluation is speed: program pin1 is of-ten faster than p. To describe this moreprecisely, for any p, d1, . . . , dn [ D, lettp (d1, . . . , dn) be the time to computevpbL d1 . . . dn. This could for example bethe number of machine cycles to executemachine code for p on a concrete com-puter.Specialization is clearly advantageous

if in2 changes more frequently than in1.To exploit this, each time in1 changesone can construct a new specialized pin1faster than p, and then run it on variousin2 until in1 changes again. Partialevaluation can even be advantageous ina single run, since it often happens that

tmix~p, in1! 1 tpin1~in2! , tp~in1, in2!

An analogy is that compilation plus tar-get run time is often faster than inter-pretation in Lisp:

tcomp~src! 1 ttarg~d! , tinterp~src, d!

2. HOW CAN PARTIAL EVALUATION BEDONE?

We use the term “partial evaluation” forautomatic program specialization—nothand-directed program transformationor verification. Three main partial eval-uation techniques are well known fromprogram transformation [Burstall andDarlington 1977]: symbolic computa-tion, unfolding function calls, and pro-

2 Exactly the same idea applies to Prolog, exceptthat inputs are given by partially instantiatedqueries and answers are sequences of terms asvariable values. In this case in1 is the part of aquery known at stage one and in2 instantiatesthis query further.

Figure 2. Specialization of a program to compute xn.

482 • N. D. Jones

ACM Computing Surveys, Vol. 28, No. 3, September 1996

Page 4: AnIntroductiontoPartialEvaluationdevanbu/teaching/260/jones...Multiple language partial evaluation withdifferentinput,output,andimple-mentation languages (say S, L, T, respectively)isalsomeaningful.Anex-ampleisAMIX,apartialevaluatorwith

gram point specialization. The latter isa combination of definition creation andfolding, amounting to memoization.Figure 2 applied the first two tech-

niques; the third was unnecessary sincethe specialized program had no functioncalls. The idea of program point special-ization is that a single function or labelin program p may appear in the special-ized program pin1 in several specializedversions, each corresponding to data de-termined at partial evaluation time.More details may be found in Jones etal. [1993].

A representative example. Acker-mann’s function is useless for practicalcomputation but an excellent vehicle toillustrate program point specialization.An example is seen in Figure 3 (theunderlines should still be ignored). Notethat the specialized program uses lessthan half as many arithmetic operationsas the original.

2.1 Online and Offline Specialization

Figure 3 illustrates offline specializa-tion [Bondorf 1991; Consel 1993; Go-mard and Jones 1991a; 1991b]. Thismakes use of program annotations, hereindicated by underlines, e.g., n-1 . Thesecan be regarded as instructions to thespecializer. Offline specialization beginswith a so-called binding-time analysis,

whose task is to place appropriate anno-tations on the program before readingthe static input.Interpretation of the annotations by

the specializer is simple:

(1) evaluate all nonunderlined expres-sions;

(2) unfold at specialization time all non-underlined function calls;

(3) generate residual code for all under-lined expressions; and

(4) generate residual function calls forall underlined function calls.

An alternative, called online specializa-tion, computes program parts as earlyas possible and takes decisions “on thefly” using only (and all) available infor-mation [Berlin and Weise 1990; Sahlin1990; Weise et al. 1991].Figure 3 is a clear improvement over

the unspecialized program, but can ob-viously be improved even more by “on-the-fly” reductions to

a2 ~n! 5 if n 5 0 then 3

else a1 ~a2 ~n 2 1!!

a1 ~n! 5 if n 5 0 then 2

else a1 ~n 2 1! 1 1

These methods often work better thanoffline methods, in particular on struc-tured data that is partially static and

Figure 3. Specialization of a program for Ackermann’s function.

Introduction to Partial Evaluation • 483

ACM Computing Surveys, Vol. 28, No. 3, September 1996

Page 5: AnIntroductiontoPartialEvaluationdevanbu/teaching/260/jones...Multiple language partial evaluation withdifferentinput,output,andimple-mentation languages (say S, L, T, respectively)isalsomeaningful.Anex-ampleisAMIX,apartialevaluatorwith

partially dynamic. On the other hand,they introduce new problems and newtechniques concerning termination ofspecializers. Comparisons and evalua-tions of costs and benefits can be foundin Ruf [1993] and Jones [1993, Ch. 7].

2.2 Sketch of an Offline Partial Evaluator

Consider as given (1) a first-order func-tional program of form

f1(s, d) 5 expression1g(u, v, . . . ) 5 expression2. . .

h(r, s, . . . ) 5 expressionm

and (2) annotations that mark everyfunction parameter, operation, test, andfunction call as either eliminable: per-form or compute or unfold during spe-cialization, or residual: generate pro-gram code to appear in the specializedprogram.In particular, the parameters of any

definition of a function f can be parti-tioned into those which are static andthe rest, which are dynamic. For in-stance, m is static and n is dynamic inthe Ackermann example.The specialized program will have the

same form as the original, but it willconsist of definitions of specialized func-tions (program points) gStatvalues , eachcorresponding to a pair (g, Statval-ues ) where g is defined in the originalprogram and Statvalues is a tupleconsisting of some values for all thestatic parameters of g. The parametersof function gStatvalues in the specializerwill be the remaining parameters of g,all dynamic.Finally, we give the specialization al-

gorithm sketch, assuming the input pro-gram’s defining function is given byf1(s, d) 5 expression1 and that sis static and d is dynamic. In the follow-ing, variables Seenbefore and Pend-ing both range over sets of specializedfunctions gStatvalues . Specializer outputvariable Target will always be a list of(residual) function definitions.

1. Read Program and S.

2. Pending :5 {f1 s};Seenbefore :5{};

3. While Pending Þ {} do 4O6:4. Choose and remove a pair gStatvalues

from Pending , and add it to Seenbe-fore if not already there.

5. Find g’s definitiong(x1, x2, . . .) 5 g-expressionand let D1, . . . , Dmbe all its dynamicparameters.

6. Generate and append to Target thedefinition

gStatvalues (D1, . . . , Dm) 5Reduce(E);

where E is the result of substitutingstatic value Si from Statevaluesin place of each static g-parameterxi occurring ing-expression

Reduction of an expression E to its re-sidual equivalent RE5 Reduce(E) is de-fined by:

1. If E is constant or a dynamic param-eter of g, then RE 5 E.

2. If E is a static parameter of g thenRE5 its value, extracted from the listStatvalues .

3. If E is of formoperator(E1, . . . , En) thencompute the values v1, . . . , vn ofReduce(E1), . . . , Reduce(En).(These must be totally computablefrom g’s static parameter values, elsethe annotation is in error.)Then set RE5 the value of operatorapplied to v1, . . . , vn.

4. If E is operator(E1, . . . , En)then compute E19 5 Reduce(E1), . . . ,En9 5 Reduce(En).Then set RE5 the expression“operator(E1 9, . . . , En 9)” .

5. If E is if E0 then E1 else E2 thencompute Reduce(E0). This must beconstant, else the annotation is inerror. If Reduce(E0) equals true ,then RE 5 Reduce(E1), otherwiseRE5 Reduce(E2).

6. If E is if E0 then E1 else E2 thenRE 5 the expression “if E0 9 thenE19 else E2 9” where each Ei 9equals Reduce(Ei ).

484 • N. D. Jones

ACM Computing Surveys, Vol. 28, No. 3, September 1996

Page 6: AnIntroductiontoPartialEvaluationdevanbu/teaching/260/jones...Multiple language partial evaluation withdifferentinput,output,andimple-mentation languages (say S, L, T, respectively)isalsomeaningful.Anex-ampleisAMIX,apartialevaluatorwith

7. Suppose E is f(E1, E2, . . . ,En) and Program contains definitionf(x1 . . . xn) 5 f-expression

then RE5 Reduce(E9), where E9 is theresult of substituting Reduce(Ei ) inplace of each static f -parameter xioccurring in f-expression .

8. If E is f(E1, E2, . . . , En) ,then(a) Compute the tuple Statvalues 9

of the static parameters of f , bycalling Reduce on each. This willbe a tuple of constant values (ifnot, the annotation is incorrect).

(b) Compute the tuple Dynvalues ofthe dynamic parameters of f , bycalling Reduce; this will be a listof expressions.

(c) Then RE5 the callf Statvalues 9(Dynvalues)

(d) A side-effect: if f Statvalues 9 is nei-ther in Seenbefore nor in Pend-ing , then add it to Pending .

2.3 Congruence, Binding-Time Analysis,and Finiteness

Where do the annotations used by thealgorithm above come from? Their rootsource is knowledge of which inputs willbe known when the program is special-ized, for example m but not n in theAckermann example. There are two fur-ther requirements for the specializationalgorithm above to succeed.First, the internal parts of the pro-

gram must be properly annotated (wit-ness comments such as “if . . . the anno-tation is incorrect”). The bottom line isthat if any parameter or operation hasbeen marked as eliminable, then oneneeds a guarantee that it actually willbe so when specialization is carried out,for any possible static program inputs.For example, an if marked as eliminablemust have a test part that evaluates toa constant. This requirement (properlyformalized) is called the congruence con-dition.The second condition is termination:

regardless of what the values of thestatic inputs are, the specializer shouldattempt to produce neither infinitely

many residual functions nor any infi-nitely large residual expression.It is the task of binding-time analysis

to ensure that these conditions are sat-isfied. Given an unmarked program to-gether with a division of its inputs intostatic (will be known when specializa-tion begins) and dynamic, the binding-time analyzer proceeds to annotate thewhole program. Several techniques forthis are described in Jones et al. [1993].The current state of the art is that

congruence can definitely be achievedautomatically, whereas binding-timeanalyses that guarantee terminationare only beginning to be constructed.The problem is complex in that thebinding-time analysis must account forpossible consequences not one step intothe future, but two.

3. COMPILERS, INTERPRETERS

3.1 Computation in One Stage or More

Computational problems can be solvedeither by single-stage computations orby multistage solutions using programgeneration. To illuminate the problemsand payoffs involved we describe twofamiliar examples, at first informally:

(1) A compiler, which generates a tar-get program in some target lan-guage from a source program in asource language.

(2) A parser generator, which generatesa parser from a context-free gram-mar.

Compilers and parser generators firsttransform their input into an executableprogram and then run the generatedprogram on runtime inputs for a com-piler, or on a character string to beparsed. Efficiency is vital: the targetprogram should run as quickly as possi-ble, and the parser should use as littletime per input character as possible.Figure 4 compares two-step compila-

tive program execution with one-stepinterpretive execution. Similar dia-grams describe two-step parser genera-tion and one-step general parsing.

Introduction to Partial Evaluation • 485

ACM Computing Surveys, Vol. 28, No. 3, September 1996

Page 7: AnIntroductiontoPartialEvaluationdevanbu/teaching/260/jones...Multiple language partial evaluation withdifferentinput,output,andimple-mentation languages (say S, L, T, respectively)isalsomeaningful.Anex-ampleisAMIX,apartialevaluatorwith

Comparison. Interpreters are usuallysmaller and easier to write than compil-ers. One reason is that the implementerthinks only of one time: execution time,whereas a compiler must perform ac-tions to generate code to achieve a de-sired effect at run time. Another is thatthe implementer only thinks of one lan-guage (the source language), while acompiler writer also has to think of thetarget language.Further, an interpreter, if written in

a sufficiently abstract, concise and high-level language, can serve as a languagedefinition: an operational semantics forthe interpreted language.However, compilers are here to stay.

The overwhelming reason is efficiency:compiled target programs usually runan order of magnitude (and sometimestwo) faster than interpretating a sourceprogram.Another source of efficiency. A two-

phase program may in its first phaseestablish global properties of its firstinput and exploit them to construct agood second-stage program. Examples: acompiler can type-check its source pro-gram and, if type-correct, generate atarget program without run-timechecks. A parser generator may checkthat its input grammar is LALR(1), soallowing efficient stack-based parsing.

3.2 Interpreters

A source program can be run in one stepusing an interpreter; an L-program, callit int, that executes S-programs. Thishas as input the S-program to be exe-cuted, together with its run-time inputs.Symbolically

ou8tput 5 vsource bS [in 1, . . . , in n]

5 vint bL [source,in 1, . . . , in n]

By definition (assuming only one inputfor notational simplicity), program int isan interpreter for S written in L if for allsource, d [ D

vsource bS d 5 vint bL [source, d]

3.3 Compilers

A compiler generates a target programin target language T from a source pro-gram source in language S. The com-piler is itself a program, say compiler,written in implementation language L.The effect of running source on inputin 1, in 2, . . . , in n is realized byfirst compiling source into target form:

target 5 vcompiler bL source

and then running the result:

output 5 vsource bS [in 1, . . . , in n]

5 vtarget bT [in 1, . . . , in n]

Figure 4. Compilation in two steps, interpretation in one.

486 • N. D. Jones

ACM Computing Surveys, Vol. 28, No. 3, September 1996

Page 8: AnIntroductiontoPartialEvaluationdevanbu/teaching/260/jones...Multiple language partial evaluation withdifferentinput,output,andimple-mentation languages (say S, L, T, respectively)isalsomeaningful.Anex-ampleisAMIX,apartialevaluatorwith

Formally, compiler is an S-to-T-compilerwritten in L if for all source, d [ D,

vsource bS d 5

vvcompiler bL source bT d

4. COMPILING BY SPECIALIZATION

In general, the idea is to specialize theinterpreter to execute only one fixedsource program, yielding a target pro-gram in the partial evaluator’s outputlanguage so that

target 5 vmix b [int, source]

Program target can be expected to befaster than interpreting source sincemany interpreter actions depend onlyon source and so can be precomputed.Remark: this shows that mix together

with int can be used to compile. It doesnot show that mix is a compiler as de-fined earlier, since a compiler has onlyone input and mix has two.

4.1 Example of Compiling

We now consider a fairly trivial inter-preter written for an imperative lan-guage S in a simple functional languageL. A source program is an instructionsequence with the following syntax(only seven instructions!):

X: 5X11, X: 5X21,Y: 5Y11, Y: 5Y21,

(IFY 50GOTO label),(IFX 50GOTO label),

(GOTO label)

Figure 5. Functional interpreter for an imperative language.

Introduction to Partial Evaluation • 487

ACM Computing Surveys, Vol. 28, No. 3, September 1996

Page 9: AnIntroductiontoPartialEvaluationdevanbu/teaching/260/jones...Multiple language partial evaluation withdifferentinput,output,andimple-mentation languages (say S, L, T, respectively)isalsomeaningful.Anex-ampleisAMIX,apartialevaluatorwith

The middle box of Figure 5 contains aninterpreter interp for S written in L,using a syntax whose meaning, wehope, is obvious.How the interpreter works. the “in-

struction counter” is maintained by ar-gument pgmtail of Run. Its value isalways a suffix of source program pgm,and its first instruction is the next to beexecuted. Normal sequential executionjust removes this first instruction andcontains with the remainder, calledrest in Run. Control transfer is han-dled by function N-th which, given alabel ,, finds the ,-th instruction in pgmand returns the suffix of pgm beginningat that point. (This is the reason thatargument pgm is passed along through-out the interpreter.)Effect of specialization. Figure 5

shows in the uppermost box a sourceprogram src that doubles its input x bycounting y up by 2 each time it counts xdown by 1, stopping when x becomeszero. (Instructions are labeled 0, 1, . . . ,so 5 denotes the end of the program.)The lowermost box shows a functionaltarget program tgt equivalent to sourceprogram src . Our claim is that special-ization of interp with respect to srcyields tgt .The underline in the call in Execute

causes generation of the call to Run-1 .(This is function Run, specialized tosrc , src as its first two arguments.)Within function Run, all the “syntac-

tic dispatch” operations (the case, letand patterns) having to do with sourceprogram structure can be done stati-cally, and so do not appear at all in thetarget program. On the other hand, op-erations involving x and y cannot be soexecuted, so code is generated (residualtarget code x 2 1 and (y 1 1) 1 1) .As to function calls of Run to itself,

those which decrease argumentpgmtail (i.e., those reflecting normalsequential execution) may safely be un-folded, since pgmtail can only be de-creased finitely many times (pgmtail isa list, not an integer). The remainingcalls (to interpret tests and GOTOs)may not be safely unfolded—this could

cause infinite unfolding and thus non-terminating specialization in the case ofsource program loops. They are thusmarked (by underlining) as “not to beunfolded,” and thus account for the callto Run-1 nested inside Run-1 .In general, program target will be a

mixture of int and source , containingparts derived from both. A common pat-tern is that the target program’s controlstructure and computations resemblethose of the source program, while itsappearance resembles that of the inter-preter, both in its language and thenames of its specialized functions.

4.2 Partial Evaluation Versus TraditionalCompiling

Given a language definition in the formof an operational semantics, partialevaluation eliminates the first and larg-est order of magnitude: the interpreta-tion overhead. Further, the methodyields target programs which are al-ways correct with respect to the inter-preter (assuming, of course, that mix iscorrect). Thus the problem of compilercorrectness seems to have vanished.Clearly the approach is suitable for

prototype implementation of new lan-guages which are defined interpretively,as has been done in functional lan-guages since very early times [Mc-Carthy et al. 1962].The generated target code is in the

partial evaluator’s output language,typically the language in which the in-terpreter is written. Thus partial evalu-ation will not devise a target languagetailor-made to the source language, e.g.,P-code for Pascal.It won’t invent new runtime data

structures, either, so human creativityseems necessary to gain the full hand-written compiler efficiency. Recent workby Hannan and Miller [1990], however,suggests the possibility of deriving tar-get machine architectures from the textof an interpreter.Because partial evaluation is auto-

matic and general, its generated codemay not be as good as handwritten tar-

488 • N. D. Jones

ACM Computing Surveys, Vol. 28, No. 3, September 1996

Page 10: AnIntroductiontoPartialEvaluationdevanbu/teaching/260/jones...Multiple language partial evaluation withdifferentinput,output,andimple-mentation languages (say S, L, T, respectively)isalsomeaningful.Anex-ampleisAMIX,apartialevaluatorwith

get code. In particular, we have notmentioned classical optimization tech-niques such as common subexpressionelimination, exploiting available expres-sions, and register allocation. Some ofthese depend on specific machine mod-els or intermediate languages and soare hard to generalize; but there is noreason many well-known techniquescould not be incorporated into the nextgeneration of partial evaluators.

4.3 The Cost of Interpretation

A typical interpreter’s basic cycle is firstsyntax analysis; then evaluation of sub-expressions by recursive calls; and fi-nally, actions to perform the main oper-ator, e.g., to do arithmetic operations ora variable lookup. In general, runningtime of interpreter int on inputs p and dsatisfies

ap z tp(d) # tint(p, d )

for all d, where ap is a constant. (In thiscontext, “constant” means: ap is inde-pendent of d, but may depend on sourceprogram p). In experiments ap is oftenaround 10 for simple interpreters runon small source programs, and largerfor more sophisticated interpreters.Clever use of data structures such ashash tables or binary trees can make apgrow slowly as a function of p’s size.

Optimality of mix. The “best possible”mix should remove all computationaloverhead caused by interpretation. Thiscan be simply checked for a self-inter-preter sint—an interpreter for L whichis written in L (as was McCarthy’s firstLisp definition).As above, the running time of sint

will be around ap z tp(d); and ap will belarge enough to be worth reducing. Ide-ally mix should reduce ap to 1. For anyprogram p and input d

vpb d 5 vsint b @p, d #

5 vvmix b @sint, p #bd

so p9 5 vmix b[sint, p] is a programequivalent to p. If p9 is at least as effi-

cient as p, then all overhead caused bysint’s interpretation has been removed.

Definition mix is optimal provided tp9

(d) # tp(d) for all p, d [ D, where sint isa self-interpreter and p9 5 vmix b[sint,p] .

This criterion has been satisfied forseveral partial evaluators for variouslanguages, using natural self-interpret-ers [Jones et al., p. 174; Romanenko1988]. In each case p9 is identical to pup to variable renaming and reordering.The same property explains the

speedups resulting from self-applicationmentioned in the previous discussion.

4.4 Example with Larger Speedup

Several earlier articles exemplify compil-ing from interpreters for traditional pro-gramming languages [Andersen 1992;Bondorf 1991; Consel 1993; Gomord andJones 1991a; 1991b; Jones et al. 1989;Jørgensen 1992; Safra and Shapiro 1986].An example with a different flavor butthe same essence is seen in Figure 6—aregular expression recognizer rex , writ-ten in a Lisp-like functional language.“Compiling” a regular expression is a wayto obtain a lexical analyzer.The recognizer rex has as inputs a

regular expression r , e.g., (a 1 b) pabb , and a subject string s . The recog-nizer’s effect is to return #t (true) if s isgenerated by the regular expression,else #f . The code shown takes into ac-count the possibility that s is empty. Ifnot, its first symbol is checked againstthose r could begin with, using functionfirstcharacters . If successful, therest of s is checked against a new regu-lar expression obtained by next . Fur-ther explanations may be found in Bon-dorf’s thesis [1990].For example, suppose r 5 (a 1 b) p

abb . The results of some calls follow:

~accept-empty? r ! #f

~next r ’a ! bb 1 ~a 1 b!*abb

~next r ’b ! ~a 1 b!*abb

Introduction to Partial Evaluation • 489

ACM Computing Surveys, Vol. 28, No. 3, September 1996

Page 11: AnIntroductiontoPartialEvaluationdevanbu/teaching/260/jones...Multiple language partial evaluation withdifferentinput,output,andimple-mentation languages (say S, L, T, respectively)isalsomeaningful.Anex-ampleisAMIX,apartialevaluatorwith

An example target program. Figure 7shows that the result of specializing “in-terpreter” rex with respect to “sourceprogram” is (a 1 b) p abb .The “target” program is essentially a

program form of the deterministic fi-nite-state automaton derived from (a 1b) p abb by standard methods. Aninteresting observation is that mixknows nothing at all about finite autom-ata—just how to specialize programs.Experiments show that in general

vtarget b s runs about 200 times fasterthan interpretively computing vrex bregex s . This is much larger than formore traditional interpreters, wherespeedups of 10 are more common.

How the target program was obtained.The input to mix is the program rex ,

whose dynamic parts are annotated byunderlining as in Figure 6, and the reg-ular expression r . Variables r0, r1,r2, firstchars, frest and f de-pend only on known (static) input r ,even though at run time the value of swill determine just which values theyassume during the computation. Thepoint is that the set of all their possiblevalues is finite and so can be precom-puted by mix during specialization.In particular, functions next and

first-characters may be completelyevaluated at compile time for everyreachable argument combination. Fol-lowing these rules gives the target pro-gram of Figure 7.For this fixed rex and any r, compila-

tion of target 5 vmix b[rex, r] will

Figure 6. Regular expression recognizer.

490 • N. D. Jones

ACM Computing Surveys, Vol. 28, No. 3, September 1996

Page 12: AnIntroductiontoPartialEvaluationdevanbu/teaching/260/jones...Multiple language partial evaluation withdifferentinput,output,andimple-mentation languages (say S, L, T, respectively)isalsomeaningful.Anex-ampleisAMIX,apartialevaluatorwith

terminate. Proof depends on the factthat any regular expression has onlyfinitely many “derivatives” (not hardbut nontrivial to prove).

5. GENERATION OF PROGRAMGENERATORS

Why not take our own medicine andapply partial evaluation to producefaster generators of specialized pro-grams? A telling catch phrase is bind-ing-time engineering—making computa-tion faster by changing the times atwhich subcomputations are done.This can indeed be done, yielding a

generator of program generators as inFigure 8. Efficiency of such a procedureis desirable at three different times:

(1) The specialized program pin1 shouldbe fast. Analogy: a fast target pro-gram.

(2) The program specializer p-genshould quickly construct pin1 . Anal-ogy: a fast compiler.

(3) cogen should quickly construct p-gen from p. Analogy: fast compilergeneration.

Our goal is thus to construct an efficientprogram generator from a general pro-gram by completely automatic methods.On the whole the general program willbe simpler but less efficient than thespecialized versions the program gener-ator produces.

5.1 Generating Program Generators

In practice one rarely uses extremelygeneral programs, e.g., specification ex-ecuters, to run programs or to parsestrings—since experience shows themoften to be much slower than the spe-

Figure 7. Specialization of the recognizer to (a1b)*abb.

Introduction to Partial Evaluation • 491

ACM Computing Surveys, Vol. 28, No. 3, September 1996

Page 13: AnIntroductiontoPartialEvaluationdevanbu/teaching/260/jones...Multiple language partial evaluation withdifferentinput,output,andimple-mentation languages (say S, L, T, respectively)isalsomeaningful.Anex-ampleisAMIX,apartialevaluatorwith

cialized programs generated by a com-piler or parser generator.Wouldn’t it be nice to have the best of

both worlds—the simplicity and direct-ness of executable specifications, andthe efficiency of programs produced byprogram generators? This dream is il-lustrated in Figure 8:

—Program cogen accepts a two-inputprogram p as input and generates aprogram generator (p-gen in the dia-gram).

—The task of p-gen is to generate aspecialized program pin1 , givenknown value in1 for p’s first input.

—Program pin1 computes the same out-put when given p’s remaining inputin2 that p would compute if givenboth in1 and in2 .

Andrei Ershov gave the appealing name“generating extension” to p-gen [1982].We will see that partial evaluation canrealize this dream quite generally, bothin theory and in practice on the com-puter.First, we give an example to demys-

tify Figure 8 by showing a generatingextension for our very first example, theexponentiation program from Figure 2.This is seen in Figure 9. Since the pur-pose of p-gen is to generate program

code, we have used an informal stringnotation with quotes for output code.

Efficiency in program generator gener-ation. It would be wonderful to havesuch a tool, but it is far from clear howto construct one. Polya’s problem adviceon solving hard problems was to solve asimpler problem similar to the ultimategoal, and then to generalize. Followingthis approach, we can clump boxes co-gen and p-gen in Figure 8 together intoa single program with two inputs, theprogram p to be specialized and its firstargument in1 . This is just the mix ofFigure 1, so we already have a weakerversion of the multiphase cogen .We will see how cogen can be con-

structed from mix . This has been donein practice for several different pro-gramming languages, and efficiency cri-teria 1, 2 and 3 have all been met.Surprisingly, criteria 2 and 3 areachieved by self-application—applyingthe partial evaluator to itself as input.

5.2 Compiling by the First FutamuraProjection

This section shows the sometimes sur-prising capabilities of partial evaluationfor generating program generators.In Section 4 we saw examples of com-

Figure 8. A generator of program generators.

492 • N. D. Jones

ACM Computing Surveys, Vol. 28, No. 3, September 1996

Page 14: AnIntroductiontoPartialEvaluationdevanbu/teaching/260/jones...Multiple language partial evaluation withdifferentinput,output,andimple-mentation languages (say S, L, T, respectively)isalsomeaningful.Anex-ampleisAMIX,apartialevaluatorwith

piling by partial evaluation. This proce-dure always yields correct target pro-grams, verified as follows:

out 5 vsource bS input5 vint b [source, input]5 vvmix b [int, source] b input5 vtarget b input

The last three equalities follow respec-tively by the definitions of an inter-preter, mix , and target . The net effecthas thus been to translate from S to L.Equation

target 5 vmix b@int,source #

is often called the first Futamura projec-tion, first reported in Futamura [1971].The conclusion is that mix can com-

pile. The target program is always aspecialized form of the interpreter, andso is in mix ’s output language—usuallythe language in which the interpreter iswritten.

5.3 Compiler Generation the SecondFutamura Projection

We now show that mix can also gener-ate a stand-alone compiler:

compiler 5 vmix b @mix, int #

This is an L-program which, when ap-plied to source , yields target , and sois a compiler from S to L, written in L.Verification is straightforward from the

mix equation:

target 5 vmix b@int, source #

5 vvmix b@mix, int #b source

5 vcompiler b source

Equation compiler 5 vmix b[mix,int] is called the second Futamura pro-jection. The compiler generates special-ized versions of interpreter int , and sois in effect int-gen , as discussed inSection 5.1. A concrete example may beseen in Jones et al. [1993, Ch. 4].Operationally, constructing a com-

piler this way is hard to understandbecause it involves self-application—us-ing mix to specialize itself. But it givesgood results in practice, as we soonshall see.

Remark. This way of doing compilergeneration requires that mix be writtenin its own input language, e.g., that S 5L. This restricts the possibility of multi-ple language partial evaluation as dis-cussed in Section 1.1.

5.4 Compiler Generator Generation by theThird Futamura Projection

By precisely parallel reasoning, co-gen 5 vmix b[mix, mix] is a compilergenerator: a program that transformsinterpreters into compilers. The compil-ers it produces are versions of mix it-self, specialized to various interpreters.

Figure 9. Generating extension for a program to compute xn.

Introduction to Partial Evaluation • 493

ACM Computing Surveys, Vol. 28, No. 3, September 1996

Page 15: AnIntroductiontoPartialEvaluationdevanbu/teaching/260/jones...Multiple language partial evaluation withdifferentinput,output,andimple-mentation languages (say S, L, T, respectively)isalsomeaningful.Anex-ampleisAMIX,apartialevaluatorwith

This projection is even harder to under-stand intuitively than the second, butalso gives good results in practice. Veri-fication of Figure 8 is again straightfor-ward from the mix equation:

vpb @in1, in2 # 5

vvmix b @p, in1 #b in2 5

vvvmix b @mix, p #b in1 b in2 5

vvvvmix b @mix, mix #b pb in1 b in2 5

vvvcogen b pb in1 b in2

5.5 Speedups by Self-Application

A variety of partial evaluators satisfy-ing all the above equations have beenconstructed. Compilation, compiler gen-eration and compiler-generator genera-tion can each be done in two differentways:

target 5 vmix b @int, source #

5 vcompiler b source

compiler 5 vmix b @mix, int #

5 vcogen b int

cogen 5 vmix b @mix, mix #

5 vcogen b mixThe exact timings vary according to thedesign of mix and int , and with theimplementation language L. Nonethe-less, a number of researchers have ob-served that in each case the second wayis often about 10 times faster than thefirst [Consel 1993; Gomard and Jones1991b; Jones et al. 1993; Jones et al.1989; Romanenko 1988]. Moral: self-ap-plication can generate programs thatrun faster!

Parser and Compiler Generation. As-suming cogen exists, compiler genera-tion can be done by letting p be theinterpreter int and letting in1 besource . The result of specializing intto source is a program written in thespecializer’s output language, but withthe same input-output function as thesource program. In other words, thesource program has been compiled from

S into cogen ’s output language. Theeffect is that int-gen is a compiler.If we let p be program parser , with a

given grammar as its known input in1 ,by the description above parser-gen isa parser generator, meaning thatparser-gen transforms its inputgrammar into a specialized parser. Thisapplication has been realized in practice[Sperber and Thiemann, 1995] andyields essentially the well-known LR(k)parsers, in program form.

6. AUTOMATIC PROGRAM GENERATION

6.1 Changing Program Style

Partial evaluation provides a novel wayto construct program style transform-ers. Let program int be a self-inter-preter for L. A generated compiler 5vcogen bint is a translator from L to Lwritten in L. In other words, it is anL-program transformer.The transformer’s output is always a

specialized version of the self-inter-preter. Because the basic operationsused in most partial evaluators arequite simple, the output program will“inherit” many of this interpreter’scharacteristics. The following exampleshave all been implemented this way:

(1) Compiling L into a proper subset.(2) Automatic instrumentation, e.g.,

transforming a program into ver-sions including code for step count-ing, or printing traces, or other de-bug code.

(3) Translating direct style programsinto continuation-passing style. Thisis easy: just write the self-inter-preter itself in continuation-passingstyle [Bondorf 1991].

(4) Translating lazy programs intoequivalent eager programs [Jør-gensen 1992].

(5) Translating direct-style programsinto tail-recursive style suitable formachine code implementation. Inprinciple this can be done by “just”writing the self-interpreter itself intail-recursive style, but achieving

494 • N. D. Jones

ACM Computing Surveys, Vol. 28, No. 3, September 1996

Page 16: AnIntroductiontoPartialEvaluationdevanbu/teaching/260/jones...Multiple language partial evaluation withdifferentinput,output,andimple-mentation languages (say S, L, T, respectively)isalsomeaningful.Anex-ampleisAMIX,apartialevaluatorwith

the desired binding-time separationis a quite nontrivial task [Sperberand Thiemann 1996].

Example (2) was exploited by Shapiro[1983] to aid in debugging programs inFlat Concurrent Prolog.

6.2 Hierarchies of Metalanguages

A modern approach to solving a wide-spectrum problem is to devise a user-oriented language to express computa-tional requests, hence, the widespreadinterest in expert systems. A processor forsuch a language usually works interpre-tively, alternating between reading anddeciphering the user’s requests, consult-ing databases and doing problem-relatedcomputing—an obvious opportunity to op-timize by partial evaluation.Such systems are often constructed us-

ing a hierarchy of metalanguages, eachcontrolling the sequence and choice of op-erations at the next lower level [Safraand Shapiro 1986]. Here efficiency prob-lems are yet more serious since each in-terpretation layer can multiply computa-tion time by a significant factor.Assume L2 is executed by an inter-

preter written in language L1 , and thatL1 is itself executed by an interpreterwritten in implementation language L0 .The left side of Figure 10 depicts thetime blowup occurring when runningprograms in language L2 .

Metaprogramming without order-of-magnitude loss of efficiency. The rightside of Figure 10 illustrates graphically

that partial evaluation can substan-tially reduce the cost of multiple inter-pretation levels. The possibility of alle-viating these problems by partialevaluation has been described in severalplaces. A literal interpretation of Figure10 involves writing two partial evalua-tors, one for L1 and one for L0 . Fortu-nately, there is an alternative approachusing only a partial evaluator for L0 .Let p2 be an L2 -program and let in ,

out be representative input and outputdata, so

out 5 vint 01bL0[int 1

2, p2, in]One may construct an interpreter for L2written in L0 as follows:

int 02 : 5 vmix bL0[int 0

1, int 12]

Partial evaluation of int 02 can compile

L2 -programs into L0 -programs. Better,one may construct a compiler from L2into L0 by

comp02 : 5 vcogen b int 0

2

The net effect is that metaprogrammingmay be used without order-of-magni-tude loss of efficiency. Although concep-tually complex, the development abovehas been realized in practice more thanonce by partial evaluation (one exampleis Jørgensen [1992]), with significantspeedups.

6.3 Semantics-directed CompilerGeneration

By this we mean more than just a toolto help humans write compilers. Given

Figure 10. Overhead introduction and elimination.

Introduction to Partial Evaluation • 495

ACM Computing Surveys, Vol. 28, No. 3, September 1996

Page 17: AnIntroductiontoPartialEvaluationdevanbu/teaching/260/jones...Multiple language partial evaluation withdifferentinput,output,andimple-mentation languages (say S, L, T, respectively)isalsomeaningful.Anex-ampleisAMIX,apartialevaluatorwith

a specification of a programming lan-guage, for example, a formal semanticsor an interpreter, our goal is automati-cally and correctly to transform it into acompiler from the specified “source” lan-guage into another “target” language[Mosses 1979; Paulson 1984].Traditional compiler-writing tools

such as parser generators and attributegrammar evaluators are not semantics-directed, even though they can and doproduce compilers as output. These sys-tems are extremely useful in practice—but it is entirely up to their users toensure generation of correct target code.The motivation for automatic com-

piler generation is evident: thousands ofman-years have been spent constructingcompilers by hand, and many of theseare not correct with respect to the in-tended semantics of the language theycompile. Automatic transformation of asemantic specification into a compilerfaithful to that semantics eliminatessuch consistency errors.The three jobs of writing the language

specification, writing the compiler, andshowing the compiler to be correct (ordebugging it) are reduced to one: writ-ing the specification in a form suitablefor the compiler generator. There hasbeen rapid progress towards this re-search goal in the past few years, withmore and more sophisticated practicalsystems and mathematical theories forthe semantics-based manipulation ofprograms. One of the most promising ispartial evaluation.

6.4 Executable Specifications

A still broader goal is efficient imple-mentation of executable specifications.Examples include compiler generationand parser generation.One can naturally think of programs

int and parser above as specificationexecuters: the interpreter executes asource program on its inputs, and theparser applies a grammar to a characterstring. In each case the value of the firstinput determines how the remaining in-

puts are to be interpreted. Symbolicallywe can write:

vspec-exec bL [spec, in 1, . . . ,in n]5 output

The interpreter’s source program inputdetermines what is to be computed. Theinterpreter thus executes a specifica-tion, namely a source S-program that isto be run in language L. The first inputto a general parser is a grammar thatdefines the structure of a certain set ofcharacter strings. The specification in-put is thus a grammar defining a pars-ing task.A reservation is that one can of course

also commit errors (sometimes the mostserious ones!) when writing specifica-tions. Achieving our goal does not elim-inate all errors, but it again reduces theplaces at which they can occur to one,namely the specification. For example, asemantics-directed compiler generatorallows quick tests of a new languagedesign to see whether it is in accordancewith the designers’ intentions regardingprogram behavior, computational ef-fects, freedom from run-time type er-rors, stack usage, efficiency, etc.

7. BROADER PERSPECTIVES

Partial evaluation is no panacea. Pro-gram specialization, like highly optimiz-ing compilation, may not be worthwhilefor all applications. For one example,knowing the value of x will not signifi-cantly aid computing xn as in Figure 2.Further, the efficiency of mix-generatedtarget programs depend crucially onhow the interpreter is written. For an-other, if an interpreter uses dynamicvariable name binding, then generatedtarget programs will have run-timevariable name searches; and if it usesdynamic source code creation then gen-erated target programs will containrun-time source language text.Characteristics of a problem that

make it suitable for specialization in-clude: It is time-consuming. It must besolved repeatedly. It is often solved withsimilar parameters, for example: code

496 • N. D. Jones

ACM Computing Surveys, Vol. 28, No. 3, September 1996

Page 18: AnIntroductiontoPartialEvaluationdevanbu/teaching/260/jones...Multiple language partial evaluation withdifferentinput,output,andimple-mentation languages (say S, L, T, respectively)isalsomeaningful.Anex-ampleisAMIX,apartialevaluatorwith

keys in cryptography, a circuit to simu-late, a query to evaluate, or a networkcommunication pattern. It is solved bywell-structured and cleanly written soft-ware (programming tricks make it hard,not only for the human to maintain, butalso for the specializer). It implements ahigh-level applications-oriented lan-guage.

7.1 Efficiency Versus Generality andModularity?

One often has a class of similar prob-lems that all must be solved efficiently.One solution is to write many small andefficient programs, one for each. Twodisadvantages are that much program-ming is needed and maintenance is dif-ficult: a change in outside specificationscan require every program to be modi-fied.Alternatively, one may write a single

highly parametrized program able tosolve any problem in the class. This hasa different disadvantage: inefficiency. Ahighly parameterized program canspend most of its time testing and inter-preting parameters and relatively littlein carrying out the computations it isintended to do.Similar problems arise with highly mod-

ular programming. While excellent for doc-umentation, modification and human us-age, inordinately much computation timecan be spent passing data back and forthand converting among various internal rep-resentations at module interfaces.To get the best of both worlds: write

only one highly parameterized and per-haps inefficient program; and use a par-tial evaluator to specialize it to each inter-esting setting of the parameters,automatically obtaining as many custom-ized versions as desired. All are faithfulto the general program, and the custom-ized versions are often much more effi-cient. Similarly, partial evaluation canremove most or all the interface code frommodularly written programs.

7.2 Some More Dramatic Examples

Applications of program generation in-clude the following, all of which havebeen seen to give significant speedupson the computer. A common characteris-tic is that many involve general andrather “interpretive” algorithms. Moredetails may be found in Jones et al.[1993] or in the reports cited below.

Pattern recognition. An earlier exam-ple gave the result of specializing a gen-eral regular expression recognizer to aparticular expression, with dramaticspeedup. This theme has been carriedmuch further, for several classes of pat-terns, by several researchers [Conseland Danvy 1989; Danvy 1991].

Computer graphics. “Ray tracing” re-peatedly recomputes information aboutthe ways light rays traverse a givenscene from different origins and in dif-ferent directions. Specializing a generalray tracer to a fixed scene to transformthe scene into a specialized tracer, onlygood for tracing rays through that onescene, gives a much faster algorithm[Andersen 1994; Mogensen 1986].

Database queries. Partial evaluationcan compile a query into a special-pur-pose search program whose task is only toanswer the given query. The generatedprogram may be discarded afterwards.Here the input to the program generatoris a general query answerer and the out-put is a “compiler” from queries intosearch programs [Safra and Shapiro1986]. A more recent application is spe-cialized integrity checks through partialevaluation of meta-interpreters [Leuscheand De Shreye 1995].

Neural networks. Training a neuralnetwork typically uses much computertime, but can be improved by specializ-ing a general simulator to a fixed net-work topology [Jacobsen 1990].

Spreadsheets. Spreadsheets are usu-ally implemented interpretively, but theprogram generation approach has beenused to transform spreadsheet specifica-

Introduction to Partial Evaluation • 497

ACM Computing Surveys, Vol. 28, No. 3, September 1996

Page 19: AnIntroductiontoPartialEvaluationdevanbu/teaching/260/jones...Multiple language partial evaluation withdifferentinput,output,andimple-mentation languages (say S, L, T, respectively)isalsomeaningful.Anex-ampleisAMIX,apartialevaluatorwith

tions into faster specialized spreadsheetprograms [Appel 1988].

Scientific computing. General pro-grams for several diverse applicationsincluding orbit calculations (the n-bodyproblem) and computations for electri-cal circuits have been speeded up byspecialization to particular planetarysystems and circuits [Baier et al. 1994;Berlin and Weise 1990].

Parsing. Parsing can also be done byfirst generating a parser from an inputcontext-free grammar:

parser 5 vparse-gen bL grammar

and then applying the result to an inputcharacter string:

parse-tree 5 vparser bL char-string

On the other hand, there exist one-stepgeneral parsers, e.g., Earley’s parser.Similar tradeoffs arise—a generalparser is usually smaller and easier towrite than a parser generator, but aparser generated from a fixed context-free grammar runs much faster.

8. AUTOMATION AND PARTIALEVALUATION

Binding-time separation. The essence ofpartial evaluation is to recognize whichof a program’s computations can bedone at specialization time and whichshould be postponed to run time. This“binding-time separation” is becomingmuch better understood, resulting inmore reliable and more powerful sys-tems.In our experience it is usually fairly

easy to establish termination, whengiven a particular interpretive languagedefinition and when the separation intostatic and dynamic arguments havebeen accomplished by a binding-timeanalysis. Ensuring termination may,however, require small changes to theinterpreter. Binding-time analysis suffi-cient to give a congruent separation isnow well automated; but fully auto-matic binding-time analyses sufficientlyconservative to guarantee termination

of specialization, or to perform “binding-time improvement” program transfor-mations automatically, are still topics ofongoing research.

Critical assessment. Partial evalua-tors are still far from perfectly under-stood in either theory or practice. Sig-nificant problems remain, and weconclude this section with some of them.Partial evaluation has advanced rap-

idly since the first years. Early systemssometimes gave impressive results butwere only applicable to limited lan-guages, required great expertise on thepart of the practitioner, and sometimesgave wrong results. Often in order toget good specialization it was necessaryboth to give extensive user advice on thesubject program and to “tune” the par-tial evaluator itself to fit new programs.

Need for human understanding. Adeeper difficulty is that new problems,and programs that solve them, requireunderstanding, a program developmentaspect never likely to be fully auto-mated (regardless of progress in artifi-cial intelligence).While mechanical program under-

standing is unreasonable to expect,progress is occurring to automate muchof the program manipulation now doneby hand. Program transformations,adaptations, etc., are being developedthat respect the behavior of the pro-grams being manipulated. Formally,program behavior is semantics, and re-cent rapid progress in partial evalua-tion owes to advances in understandingthe operational aspects of semantics.

Greater automation and user conve-nience. The user should not need to giveadvice on unfolding or on generaliza-tion, that is to say where statically com-putable values should be regarded asdynamic. (Such advice is required insome current systems to avoid con-structing large or infinite output pro-grams.)The user should not be forced to un-

derstand the logic of a program result-ing from specialization. An analogy is

498 • N. D. Jones

ACM Computing Surveys, Vol. 28, No. 3, September 1996

Page 20: AnIntroductiontoPartialEvaluationdevanbu/teaching/260/jones...Multiple language partial evaluation withdifferentinput,output,andimple-mentation languages (say S, L, T, respectively)isalsomeaningful.Anex-ampleisAMIX,apartialevaluatorwith

that one almost never looks at a compil-er-generated target program or a Yacc-generated parser.Further, users shouldn’t need to un-

derstand how the partial evaluatorworks. If partial evaluation is to be usedby non-specialists in the field, it is es-sential that the user think as much aspossible about the problem he or she istrying to solve, and as little as possibleabout the tool being used to aid itssolution. A consequence is that systemsand debugging facilities that give feed-back about the subject program’s bind-ing-time separation are essential for useby nonspecialists.Quite significant advances have been

made, but the presence or absence ofsuch important characteristics is all toorarely mentioned in the literature.

Analogy with parser generation. Inseveral respects, using a partial evalua-tor is rather like using a parser genera-tor such as Yacc. First, if Yacc accepts agrammar, then one can be certain thatthe parser it generates assigns the rightparse tree to any syntactically correctinput string and detects any incorrectstring. Analogously, a correct partialevaluator always yields specialized pro-grams correct with respect to the inputprogram. For instance, a generatedcompiler is always faithful to the inter-preter from which it was derived.Second, when a user constructs a con-

text-free grammar, he or she is mainlyinterested in what strings it generates.But use of Yacc forces the user to thinkfrom a new perspective: possible left-to-right ambiguity. If Yacc rejects a gram-mar, the user may have to modify itseveral times, until it is free of left-to-right ambiguity.Analogously, a partial evaluator user

may have to think about his or herprogram from a new perspective: whatare its binding-time properties? If spe-cialized programs are too slow, it will benecessary to modify the program andretry until a better binding-time-stageseparation is achieved. In other words,does one need binding-time improve-

ments: transformations that do notchange the algorithm’s semantics, butmake it easier for the specializer toseparate binding-times?

Everchanging languages and systems.Unfortunately for many automation at-tempts, the ground is constantly shiftingunder one’s feet in both software and inhardware (e.g., new architectures andchanging preferences for imperative,logic, functional, and object-oriented pro-gramming). An ever-changing contextmakes systematization and automationquite hard; a well-known example is thatmethods good for yesterday’s optimizingcompilers are sometimes disastrous ontoday’s machines.Nonetheless, frequent change is in no

way a good excuse for neglecting theapplication of automation in our ownworkplaces (indeed, this is embarrass-ing, given the enormous benefits givenby computers in automating work donein other scientific and industrial fields!).

9. HISTORY

Jones et al. [1993] describe several ap-proaches to and systems for partialevaluation. For an extensive bibliogra-phy including references to papers inRussian, see Sestoft and Zamulin[1988]. It is still being updated and iselectronically available by anonymousftp from file pub/diku/dists/jones-book/partial-eval.bib.Z .Another source: http://www.

diku.dk/research-groups/topps/Bibliography.html .

Theory. The idea of obtaining a one-argument function by “freezing” an in-put to a two-argument function is clas-sical mathematics (“restriction,”“projection,” or “currying”). Specializingprograms rather than functions is alsofar from new, for instance Kleene’s s-m-n Theorem from 1936(!) is an impor-tant building block of recursive functiontheory. On the other hand, efficiencymatters were quite irrelevant toKleene’s investigations.

Introduction to Partial Evaluation • 499

ACM Computing Surveys, Vol. 28, No. 3, September 1996

Page 21: AnIntroductiontoPartialEvaluationdevanbu/teaching/260/jones...Multiple language partial evaluation withdifferentinput,output,andimple-mentation languages (say S, L, T, respectively)isalsomeaningful.Anex-ampleisAMIX,apartialevaluatorwith

Futamura saw around 1970 that com-piling may in principle be done by par-tial [Futamura 1971]. Turchin [1986],Ershov [1982] and Beckmann et al.[1976] realized the same independentlyin the mid-1970s and saw that even acompiler generator could be built by ap-plying a partial evaluator to itself.

Practice. Lombardi and Raphael’s[1964] papers on incremental computa-tion were pathbreaking. In the mid-1970s a large partial evaluator was de-veloped in Sweden for Lisp as used inpractice (including imperative featuresand property lists) [Beckman et al.1976] and a partial evaluator for Prolog[Komorowski 1982]. Trends to recognizepartial evaluation as an important toolappeared among dedicated builders ofcompiler generators [Mosses 1979; Paul-son 1984].A wide range of languages has been

covered in recent years, including first-order functional languages [Berlin andWeise 1990; Consel 1993; Jones et al.1989; Romanenko 1988], higher-orderlanguages including Scheme [Bondorf1991; Gomard and Jones 1991b; Weiseet al. 1991], typed languages [Launch-bury 1991], logic programming includ-ing Prolog [Komorowski 1982; Lloydand Shepherdson 1991; Safra and Sha-piro 1986; Leuschel and De Schreye,1995; Sahlin 1990] a term-rewritinglanguage [Bondorf 1989], and impera-tive languages [Andersen 1994; 1992;Gomard and Jones 1991] including asubset of C.

Self-application. A nontrivial self-ap-plicable partial evaluator that requiredhandmade unfolding annotations forfunction calls was first developed in late1984 and communicated in Jones et al.[1985]. Fully automatic self-applicablesystems among the above are discussedin Andersen [1992], Bondorf [1990],Consel [1993], Gomard and Jones[1991a, 1991b], Jones et al. [1989] andRomanenko [1988].

New applications. An early motiva-tion was optimization, so it is gratifying

to see recent applications to scientificcomputing such as that of Berlin andWeise [1990] and Baier et al. [1994].Applications to compiling and compilergeneration were envisioned long beforethey were realized in practice, but un-foreseen applications have arisen too,for example in real-time processing[Nirkhe and Pugh 1992], incrementalcomputation, debugging concurrent pro-grams [Shapiro 1983], and parallel andpipelined computation [Pingali and Rog-ers 1990; Vasell 1993].A potential use of fast specialization

is to have a specializer running concur-rently with the original program, andfrom time to time to switch to special-ized versions whenever input patternsrecur.

10. CONCLUSIONS

Partial evaluation and self-applicationhave many promising applications andwork well in practice for generating pro-gram generators, e.g., compilers andcompiler generators and other programtransformers, for example style chang-ers and instrumenters.

Some recurring problems in partialevaluation. Rapid progress has oc-curred, but there are often problemswith termination of the partial evalua-tor, and sometimes with semantic faith-fulness of the specialized program to theinput program (termination, backtrack-ing, correct answers, etc.). Further, itcan be hard to predict how much (if any)speedup will be achieved by specializa-tion, and hard to see how to modify theprogram to improve the speedup.An increasing understanding is evolv-

ing of how to construct partial evalua-tors for various languages, of how totame termination problems, and of themathematical foundations of partialevaluation. On the other hand, we needto be able to

—make it easier to use a partial evalu-ator,

—understand how much speedup is pos-sible,

500 • N. D. Jones

ACM Computing Surveys, Vol. 28, No. 3, September 1996

Page 22: AnIntroductiontoPartialEvaluationdevanbu/teaching/260/jones...Multiple language partial evaluation withdifferentinput,output,andimple-mentation languages (say S, L, T, respectively)isalsomeaningful.Anex-ampleisAMIX,apartialevaluatorwith

—predict the speedup and space usagefrom the program before specializa-tion,

—produce better results when specializ-ing typed languages,

—avoid code explosion (by automaticmeans), and

—generate machine architectures tai-lor-made to the source language de-fined by an interpreter

Deeper-going and more advanced criti-cal reviews may be found in Jones et al.[1993] and Ruf [1993].

ACKNOWLEDGMENTS

This article has benefited greatly from many peo-ple’s reading and constructive criticism. Specialthanks are due to Carsten Gomard, Peter Sestoftand others in the TOPPS group at Copenhagen,Jacques Cohen, Robert Gluck, John Launchbury,Patrick O’Keefe, Carolyn Talcott, Dan Weise, andthe referees.

REFERENCES

ACM. 1991. Partial Evaluation and Semantics-Based Program Manipulation, New Haven,Connecticut. (Sigplan Notices, 26, 9, Sept.),ACM Press.

ACM. 1992. Sigplan Workshop on Partial Eval-uation and Semantics-Based Program Manip-ulation, (San Francisco).

ACM. 1993. Sigplan Workshop on Partial Eval-uation and Semantics-Based Program Manip-ulation (Copenhagen). ACM Press.

ACM 1994. Sigplan Workshop on Partial Eval-uation and Semantics-Based Program Manip-ulation, (Orlando, Florida) Univ. of Mel-bourne report 94/9, 1994.

ACM. 1995. Sigplan Workshop on Partial Eval-uation and Semantics-Based Program Manip-ulation, (San Diego, Calif.) ACM Press.

AHO, A. V., SETHI, R., AND ULLMAN, J. D.1986. Compilers: Principles, Techniques, andTools. Addison-Wesley.

ANDERSEN, L. O. 1994. Program analysis andspecialization for the C programming lan-guage. DIKU, Dept. of Computer Science,Univ. of Copenhagen. DIKU Rep. No. 94/19.

ANDERSEN, L. O. 1992. C program specializa-tion. International Workshop on CompilerConstruction, (Paderborn, Germany), Spring-er-Verlag.

ANDERSEN, P. H. 1994. Partial evaluation ap-plied to ray tracing. Res. Rep. DIKU, Dept. ofComputer Science, Univ. of Copenhagen.

APPEL, A. 1988. Reopening closures. Unpub-lished report, Princeton Univ.

BAIER, R., GLUCK, R., AND ZOCHLING, R. 1994. Par-tial evaluation of numerical programs in For-tran. In Proceedings of ACM SIGPLAN Work-shop on Partial Evaluation and Semantics-Based Program Manipulation, Tech. Rep. 94/9,Univ. of Melbourne, Australia, 119–132.

BECKMAN, L., ET AL. 1976. A partial evaluator,and its use as a programming tool. Artif.Intell. 7, 4, 319–357.

BERLIN, A. AND WEISE, D. 1990. Compiling sci-entific code using partial evaluation. IEEEComput. 23, 12 (Dec.) 25–37.

BJØRNER, D., ERSHOV, A. P., AND JONES, N. D.EDS. 1987. Partial evaluation and mixedcomputation. In Proceedings of the IFIP TC2Workshop (Gammel Avernœs, Denmark, Oct.)North-Holland, 1988.

BONDORF, A. 1989. A self-applicable partialevaluator for term rewriting systems. In TAP-SOFT ’89 Proceedings of the InternationalConference Theory and Practice of SoftwareDevelopment, J. Diaz and F. Orejas, Eds.(Barcelona, Spain, Mar.) (Lecture Notes inComputer Science, 352), Springer-Verlag, 81–95.

BONDORF, A. 1990. Self-applicable partial eval-uation. PhD thesis, DIKU, Univ. of Copenha-gen. Revised version: DIKU Rep. 90/17.

BONDORF, A. 1991. Automatic autoprojection ofhigher order recursive equations. Sci. Com-put. Program. 17, 3–34.

BURSTALL, R. M. AND DARLINGTON, J. 1977. Atransformation system for developing recur-sive programs. J ACM, 24, 1 (Jan.) 44–67.

CONSEL, C. AND DANVY, O. 1989. Partial evalua-tion of pattern matching in strings. Inf. Pro-cess. Lett., 30 (Jan.) 79–86.

CONSEL, C. AND NOEL, F. 1992. A general ap-proach for run-time specialization and its ap-plication to C. In ACM Symposium on Princi-ples of Programming Languages, (Orlando,Florida, Jan.) ACM Press.

CONSEL, C. AND DANVY, O. 1993. Tutorial noteson partial evaluation. In ACM Symposium onPrinciples of Programming Languages. ACMPress.

CONSEL, C. 1993. A tour of Schism: a partialevaluation system for higher-order applica-tive languages. In ACM Symposium on Par-tial Evaluation and Semantics-Based Pro-gram Manipulation, 66–77.

DANVY, O. 1991. Semantics-directed compila-tion of non-linear patterns. Inf. Process. Lett.37, 315–322.

ERSHOV, A. P. 1982. Mixed computation: Poten-tial applications and problems for study.Theor. Comput. Sci., 18, 41–67.

ERSHOV, A. P., BJØRNER, D., FUTAMURA, Y., FU-RUKAWA, K., HARALDSON, A., AND SCHERLIS, W.

Introduction to Partial Evaluation • 501

ACM Computing Surveys, Vol. 28, No. 3, September 1996

Page 23: AnIntroductiontoPartialEvaluationdevanbu/teaching/260/jones...Multiple language partial evaluation withdifferentinput,output,andimple-mentation languages (say S, L, T, respectively)isalsomeaningful.Anex-ampleisAMIX,apartialevaluatorwith

EDS. 1988. In Special Issue: Selected Pa-pers from the Workshop on Partial Evaluationand Mixed Computation, 1987. New Gen-eration Comput., 6, 2,3. Ohmsha Ltd. andSpringer-Verlag.

FUTAMURA, Y. 1971. Partial evaluation of com-putation process—an approach to a compiler-compiler. Syst. Comput. Contr. 2, 5, 45–50.

GOMARD, C. K. AND JONES, N. D. 1991a. Compilergeneration by partial evaluation: a case study.Structured Program. 12, 123–144. Also asDIKU-report 88/24 and 90/16.

GOMARD, C. K. AND JONES, N. D. 1991b. A par-tial evaluator for the untyped lambda-calcu-lus. J. Funct. Program. 1 1 (Jan.) 21–69.

HANNAN, J. AND MILLER, D. 1990. From opera-tional semantics to abstract machines. In1990 ACM Conference on Lisp and FunctionalProgramming, (Nice, France), ACM Press,June, 323–332.

HOLST, N. C. K. 1988. Language triplets: TheAMIX approach. In Partial Evaluation andMixed Computation, D. Bjørner, A. P. Ershov,and N. D. Jones, Eds., North-Holland, 167–185.

JACOBSEN, H. F. 1990. Speeding up the back-propagation algorithm by partial evaluation.DIKU Student Project 90-10-13, 32 pages.DIKU, Univ. of Copenhagen. (In Danish).

JONES, N. D. 1988. Automatic program special-ization: A re-examination from basic princi-ples. In Partial Evaluation and Mixed Com-putation, D. Bjørner, A. P. Ershov, and N. D.Jones, Eds. North-Holland, 225–282.

JONES, N. D. 1995. MIX ten years later. In Pro-ceedings of PEPM’95, the ACM Sigplan Sym-posium on Partial Evaluation and Semantics-Based Program Manipulation, 24–38.

JONES, N. D., GOMARD, C., AND SESTOFT, P.1993. Partial Evaluation and AutomaticProgram Generation. Prentice Hall.

JONES, N. D., SESTOFT, P., AND SØNDERGAARD, H.1985. An experiment in partial evaluation:The generation of a compiler generator. InRewriting Techniques and Applications, J.-P.Jouannaud, Ed. (Dijon, France) Lecture NotesComputer Science, 202, Springer-Verlag, 124–140.

JONES, N. D., SESTOFT, P., AND SØNDERGAARD, H.1989. Mix: A self-applicable partial evalua-tor for experiments in compiler generation.Lisp Symbolic Comput., 2, 1, 9–50.

JØRGENSEN, J. 1992. Generating a compiler fora lazy language by partial evaluation. InNineteenth ACM Symposium on Principles ofProgramming Languages (Albuquerque, NewMexico, Jan.) ACM, 258–268.

JØRRING, U. AND SCHERLIS, W. L. 1986. Compilersand staging transformations. In ThirteenthACM Symposium on Principles of ProgrammingLanguages (St. Petersburg, Florida) 86–96.

KOMOROWSKI, H. J. 1982. Partial evaluation asa means for inferencing data structures in anapplicative language: A theory and implemen-tation in the case of Prolog. In Ninth ACMSymposium on Principles of ProgrammingLanguages, (Albuquerque, New Mexico) 255–267.

LAUNCHBURY, J. 1991. Projection factorisationsin partial evaluation. Distinguished Disserta-tions in Computer Science. Cambridge Univ.Press.

LEONE, M. AND LEE, P. 1994. Lightweight run-time code generation. In Proceedings ofPEPM’94, the ACM Sigplan Symposium onPartial Evaluation and Semantics-Based Pro-gram Manipulation. ACM Press.

LEUSCHEL, M. AND DE SCHREYE, D. 1995. Towardscreating specialised integrity checks throughpartial evaluation of meta-interpreters. In Pro-ceedings of PEPM’95, the ACM Sigplan Sympo-sium on Partial Evaluation and Semantics-Based Program Manipulation, (La Jolla,California, June) ACM Press, 253–263.

LLOYD, J. W. AND SHEPHERDSON, J. C. 1991. Par-tial evaluation in logic programming. J. LogicProgram., 11, 217–242.

LOMBARDI, L. A. AND RAPHAEL, B. 1964. Lisp asthe language for an incremental computer. InThe Programming Language Lisp: Its Opera-tion and Applications, E. C. Berkeley and D.G. Bobrow, Eds. MIT Press, Cambridge, Mas-sachusetts, 204–219.

MCCARTHY, J., ET AL. 1962. LISP 1.5 Program-mer’s Manual. MIT Computation Center andResearch Laboratory of Electronics.

MOGENSEN, T. 1986. The application of partialevaluation to ray-tracing. Master’s thesis,DIKU, Univ. of Copenhagen, Denmark.

MOSSES, P. 1979. SIS—semantics implementa-tion system, reference manual and user guide.DAIMI Rep. MD-30, DAIMI, Univ. of Aarhus,Denmark.

NIRKHE, V. AND PUGH, W. 1992. Partial evalua-tion and high-level imperative programminglanguages with applications in hard real-timesystems. In Nineteenth ACM Symposium onPrinciples of Programming Languages, (Albu-querque, New Mexico, Jan.) ACM, 269–280.

PAGAN, F. G. 1991. Partial Computation andthe Construction of Language Processors.Prentice-Hall, 166.

PAULSON, L. 1984. Compiler generation fromdenotational semantics. In Methods and Toolsfor Compiler Construction, B. Lorho, Ed.Cambridge University Press, 219–250.

PINGALI, K. AND ROGERS, A. 1990. Compiler par-allelization for a simple distributed memory-machine. In International Conference on Par-allel Programming, (St. Charles, Illinois).

PU, C., AUTREY, T., BLACK, A., CONSEL, C., COWAN,C., INOUYE, J., KETHANA, L., WALPOLE, J., AND

502 • N. D. Jones

ACM Computing Surveys, Vol. 28, No. 3, September 1996

Page 24: AnIntroductiontoPartialEvaluationdevanbu/teaching/260/jones...Multiple language partial evaluation withdifferentinput,output,andimple-mentation languages (say S, L, T, respectively)isalsomeaningful.Anex-ampleisAMIX,apartialevaluatorwith

ZHANG, K. 1995. Optimistic incrementalspecialization: streamlining a commercial op-erating system. In ACM Symposium on Oper-ating Systems Principles.

ROMANENKO, S. A. 1988. A compiler generatorproduced by a self-applicable specializer canhave a surprisingly natural and understand-able structure. In Partial Evaluation andMixed Computation, D. Bjørner, A. P. Ershov,and N. D. Jones, Eds. North-Holland, 445–463.

RUF, E. 1993. Topics in online partial evalua-tion, Ph.D. thesis, Stanford Univ., California,Published as Tech. Rep. CSL-TR-93-563.

SAFRA, S. AND SHAPIRO, E. 1986. Meta inter-preters for real. In Information Processing 86,H.-J. Kugler, Ed. North-Holland, 271–278.

SAHLIN, D. 1990. The Mixtus approach to auto-matic partial evaluation of full Prolog. InLogic Programming: Proceedings of the 1990North American Conference (Austin, Texas,Oct.), S. Debray and M. Hermenegildo, Eds.MIT Press, 377–398.

SESTOFT, P. AND ZAMULIN, A. V. 1988. Annotatedbibliography on partial evaluation and mixedcomputation. In Special Issue: Selected Papersfrom the Workshop on Partial Evaluation andMixed Computation. Ohmsha Ltd. andSpringer-Verlag, 309–354.

SHAPIRO, E. 1983. Algorithmic Program Debug-ging. MIT Press, 1983.

SØRENSEN, H., GLUCK, R., AND JONES, N. D.1994. Towards unifying partial evaluation,deforestation, supercompilation, and GPC. InEuropean Symposium on Programming (Glas-gow) J.-P. Jouannaud, Ed., (Lecture Notes inComputer Science). Springer-Verlag.

SPERBER, M. AND THIEMANN, P. 1996. Realisticcompilation by partial evaluation. In ACMSIGPLAN Conference on Programming Lan-guage Design and Implementation PLDI’96.

SPERBER, M. AND THIEMANN, P. 1995. The es-sence of LR parsing. In ACM SIGPLAN Con-ference on Partial Evaluation and Semantics-Based Program Manipulation (San Diego,California), ACM Press, 146–155.

TURCHIN, V. F. 1986. The concept of a super-compiler. ACM Trans. Program. Lang. Syst.,8, 3 (July) 292–325.

VASELL, J. 1993. A partial evaluator for dataflow graphs. In ACM SIGPLAN Conferenceon Partial Evaluation and Semantics-BasedProgram Manipulation. (Copenhagen) 206–215.

WEISE, D., CONYBEARE, R., RUF, E., AND SELIGMAN,S. 1991. Automatic online partial evalua-tion. In Functional Programming Languagesand Computer Architecture (Cambridge, Mas-sachusetts, Aug.) J. Hughes, Ed., (LectureNotes in Computer Science, 523), ACM,Springer-Verlag, 165–191.

Received February 1996; accepted June 1996

Introduction to Partial Evaluation • 503

ACM Computing Surveys, Vol. 28, No. 3, September 1996