Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Jones N.D.Partial evaluation and automatic program generation.1999

.pdf
Скачиваний:
9
Добавлен:
23.08.2013
Размер:
1.75 Mб
Скачать

The components of the Scheme0 specializer 381

)))))))))))

(define (desug* es sub) (map (lambda (e) (desug e sub)) es)) (define (desugardef def)

(list 'define (cons (name def) (var def)) (desug (body def) ()))) (map desugardef program)

)

; Define Scheme functions corresponding to abbreviations (define (sugartoscheme abbrevtriple)

(let ((abbrev

(car

abbrevtriple))

(var

(cadr

abbrevtriple))

(term

(caddr

abbrevtriple)))

(list 'define (list abbrev var)

(if (and (pair? term) (equal? (car term) 'op)) (cdr term) term)

)))

; Convert plain Scheme0 programs to Scheme, possibly renaming functions

(define (scheme program) (define (rename fn)

(define (variant f)

(let ((original (car (car f))) (btvariant (cdr f))) (foldl string-append ""

(map symbol->string (cons original (cons '* btvariant)))))) (define (gi f vs defs)

(if defs

(let ((fvs (name (car defs)))) (if (equal? f (car fvs))

(if (equal? vs (cdr fvs)) 1

(+ 1 (gi f vs (cdr defs)))) (gi f vs (cdr defs))))

(error 'rename "Unknown function: ~s" (cons f vs)))) (if (atom? fn)

fn

(let ((f (car fn)) (vs (cdr fn))) (string->symbol

(string-append (variant f) "-"

(number->string (gi f vs program)))))))

(define (schdef def) (list 'define

(cons (rename (name def)) (var def)) (schexp (body def))))

(define (schexp e)

(if (null? e)

e

(if (number? e) e

(if (atom? e)

e

(if (equal? (tag e) 'quote) e (if (equal? (tag e) 'if)

(list 'if (schexp (e1 e)) (schexp (e2 e)) (schexp (e3 e))) (if (equal? (tag e) 'call)

(cons (rename (funname e)) (map schexp (callargs e))) (if (equal? (tag e) 'op)

(cons (funname e) (map schexp (callargs e)))

(error 'scheme "Illegal Scheme0 expression: ~s" e))))))))) (map schdef program)

)

(define (reorder parameters sdpattern) (if parameters

(let ((pspd (reorder (cdr parameters) (cdr sdpattern)))) (if (equal? (car sdpattern) 'S)

(cons (cons (car parameters) (car pspd)) (cdr pspd)) (cons (car pspd) (cons (car parameters) (cdr pspd)))))

(cons () ())

382 The Self-Applicable Scheme0 Specializer

))

; General auxiliary functions

(define (foldl f a bs) (if bs (foldl f (f a (car bs)) (cdr bs)) a)) (define (foldr f a bs) (if bs (f (car bs) (foldr f a (cdr bs))) a)) (define (all bs) (if bs (and (car bs) (all (cdr bs))) 't))

(define (s0sort leq? xs) (define (insert x xs)

(if xs

(if (leq? x (car xs)) (cons x xs)

(cons (car xs) (insert x (cdr xs)))) (list x)))

(foldr insert () xs)

)

(define (number->string n) ; Works only for strictly positive n (define (num->str n digits)

(if (equal? n 0) digits

(num->str (quotient n 10)

(cons (integer->char (+ 48 (remainder n 10))) digits)))) (list->string (num->str n ()))

)

;*** Eval is not standard Scheme. Redefine to suit your Scheme version ***

;For Chez Scheme, xscheme, TI PC Scheme, and elk:

(define (s0eval schemeexpression) (eval schemeexpression))

;For Yale T Scheme:

;(define (s0eval schemeexpression) (eval schemeexpression scheme-env))

;Main variables and functions for experiments

(define onlineunfolding 't)

(define (create)

(map s0eval (map sugartoscheme sugars)) (load "spec.ss")

(make 'spec specializer) (load "annotate.ss") (load "analyse.ss") (load "subject.ss")

)

(define (polytate program sdpat) (annotate program (polydiv program sdpat))) (define (monotate program sdpat) (annotate program (monodiv program sdpat))) (define (polype program sdpat vs0) (specialize (polytate program sdpat) vs0)) (define (monope program sdpat vs0) (specialize (monotate program sdpat) vs0))

(define (make nam residual)

(let ((schemeprogram (scheme residual))) (let ((f (name (car schemeprogram))))

(s0eval (cons 'define

(cons (cons nam 'args)

(append schemeprogram (list (list 'apply f 'args)))

))))))

The le analyse.ss de nes the binding time analysis functions, and functions for handling divisions and sdpatterns.

The components of the Scheme0 specializer 383

;File "analyse.ss" -- Binding time analysis of Scheme0 programs

;Partial evaluator for first order functional language

;General (monovariant or polyvariant) binding time analysis

(define (finddivision program sdpattern update) (define (bv e vn vt division)

(if (null? e)

division

(if (number? e) division

(if (atom? e)

division

(if (equal? (tag e) 'quote) division (if (equal? (tag e) 'if)

(bv (e1 e) vn vt (bv (e2 e) vn vt (bv (e3 e) vn vt division))) (if (equal? (tag e) 'call)

(let ((argsdpat (map (lambda (e) (be e vn vt)) (callargs e)))) (foldl (lambda (d e) (bv e vn vt d))

(update (funname e) argsdpat division bv) (callargs e)))

(if (equal? (tag e) 'op)

(foldl (lambda (d e) (bv e vn vt d)) division (callargs e)) (error 'bv '"Illegal Scheme0 expression: ~s" e)

))))))))

(let ((def (car program)))

(let ((division0 (list (cons (name def) (list sdpattern))))) (bv (body def) (var def) sdpattern division0)

)))

; Monovariant binding time analysis

(define (monodiv program sdpattern) (define (monoupdate f sdpat div0 bv)

(define (monoupd div0) (if div0

(let ((d1 (car div0))) (if (equal? f (car d1))

(let ((oldsdpattern (car (cdr d1))))

(cons (cons f (list (lub* sdpat oldsdpattern))) (cdr div0)))

(cons d1 (monoupd (cdr div0))))) (list (cons f (list sdpat)))))

(let ((div1 (monoupd div0))) (if (equal? div0 div1)

div0

(let ((def (lookupfun f program)))

(bv (body def) (var def) (car (getsdpatterns f div1)) div1)

))))

(finddivision program sdpattern monoupdate)

)

; Polyvariant binding time analysis

(define (polydiv program sdpattern) (define (polyupdate f sdpat div0 bv)

(define (polyupd div0) (if div0

(let ((d1 (car div0))) (if (equal? f (car d1))

(let ((oldsdpatterns (cdr d1)))

(if (member sdpat oldsdpatterns) div0

(cons (cons f (append oldsdpatterns (list sdpat))) (cdr div0))))

(cons d1 (polyupd (cdr div0))))) (list (cons f (list sdpat)))))

384 The Self-Applicable Scheme0 Specializer

(let ((div1 (polyupd div0))) (if (equal? div0 div1)

div0

(let ((def (lookupfun f program))) (bv (body def) (var def) sdpat div1)

))))

(sortdivision (finddivision program sdpattern polyupdate))

)

;Returns S if e is static, D if e is dynamic.

;vn = variable names, vt = variable binding times

(define (be e vn vt) (if (null? e) 'S (if (number? e) 'S

(if (atom? e) (lookupbt e vn vt) (if (equal? (tag e) 'quote) 'S (if (equal? (tag e) 'if)

(lub (be (e1 e) vn vt)

(lub (be (e2 e) vn vt) (be (e3 e) vn vt))) (if (equal? (tag e) 'call)

(foldl lub 'S (map (lambda (e) (be e vn vt)) (callargs e))) (if (equal? (tag e) 'op)

(foldl lub 'S (map (lambda (e) (be e vn vt)) (callargs e))) (error 'be '"Illegal Scheme0 expression: ~s" e)

))))))))

(define (lub t1 t2) (if (equal? t1 'D) 'D t2))

(define (lub* t1s t2s) (if t1s

(cons (lub (car t1s) (car t2s)) (lub* (cdr t1s) (cdr t2s)))

()

))

(define (sdpattern-leq sdpat1 sdpat2) (equal? sdpat2 (lub* sdpat1 sdpat2)))

(define (sortdivision division) (map (lambda (fun-sdpats)

(cons (car fun-sdpats) (s0sort sdpattern-leq (cdr fun-sdpats)))) division

))

(define (getsdpatterns f division) (let ((binding (assoc f division)))

(if binding (cdr binding) ())

))

(define (lookupbt x xs vs) (if xs

(if (equal? x (car xs)) (car vs)

(lookupbt x (cdr xs) (cdr vs)))

(error 'lookupbt '"Unknown variable: ~s" x)

))

The le annotate.ss de nes the annotation functions and occurrence counting functions.

; File "annotate.ss" -- Annotation (monoor polyvariant) of Scheme0 programs

The components of the Scheme0 specializer 385

;Partial evaluator for first order functional language

;Takes a Scheme0 program and a (possibly polyvariant) division; returns

;an annotated Scheme0 program or reports non-congruence of the division.

(define (annotate program division) (foldl append ()

(map (lambda (def) (anndef def program division)) program)

))

(define (anndef def program division) (define (anndefversion sdpattern)

(let ((xsxd (reorder (var def) sdpattern))) (list 'define

(list (cons (cons (name def)

(dynoccs (name def) sdpattern program)) sdpattern)

(car xsxd) (cdr xsxd))

((if (cdr xsxd) lift exp)

(annexp (body def) (var def) sdpattern onlineunfolding))))) (define (annexp e vn vt unf)

(if (null? e) (cons e 'S) (if (number? e) (cons e 'S)

(if (atom? e) (cons e (lookupbt e vn vt)) (if (equal? (tag e) 'quote) (cons e 'S) (if (equal? (tag e) 'if)

(let ((ae1 (annexp (e1 e) vn vt unf)))

(let ((ae2 (annexp (e2 e) vn vt (and unf (static ae1)))) (ae3 (annexp (e3 e) vn vt (and unf (static ae1)))))

(if (static ae1)

(if (and (static ae2) (static ae3))

(cons (list 'ifs (exp ae1) (exp ae2) (exp ae3)) 'S) (cons (list 'ifs (exp ae1) (lift ae2) (lift ae3)) 'D))

(cons (list 'ifd (exp ae1) (lift ae2) (lift ae3)) 'D)))) (if (equal? (tag e) 'call)

(let ((aes (map (lambda (e) (annexp e vn vt unf)) (callargs e))) (f (funname e)))

(let ((argsdpat (map cdr aes)))

(let ((sdpattern (getleast argsdpat (getsdpatterns f division) f))) (let ((esed (reorder aes sdpattern))

(dynvaroccs (dynoccs f sdpattern program))) (let ((es (car esed)) (ed (cdr esed)))

(let ((staticcall (or (null? ed)

(and unf (nodup dynvaroccs (map exp ed)))))) (cons (list (if staticcall 'calls 'calld)

(cons (cons f dynvaroccs) sdpattern) (map exp es)

(map lift ed))

(if (null? ed) 'S 'D)))))))) (if (equal? (tag e) 'op)

(let ((aes (map (lambda (e) (annexp e vn vt unf)) (callargs e)))) (if (all (map static aes))

(cons (cons 'ops (cons (funname e) (map exp aes))) 'S) (cons (cons 'opd (cons (funname e) (map lift aes))) 'D)))

(error 'annotate "Illegal Scheme0 expression: ~s" e)

))))))))

(map anndefversion (getsdpatterns (name def) division))

)

(define (dynoccs f sdpattern program) (let ((def (lookupfun f program))) (let ((vn (var def)))

(let ((occs (count (body def) vn sdpattern (map (lambda (v) 0) vn)))) (cdr (reorder occs sdpattern))

386 The Self-Applicable Scheme0 Specializer

))))

;Count occurrences of all variables vn in e, giving a list of 0, 1, or 2,

;(meaning 0, 1, or >= 2) occurrences of the corresponding variable in vn.

(define (count e vn vt occurrences) (if (null? e) occurrences

(if (number? e) occurrences

(if (atom? e) (incvar e vn occurrences) (if (equal? (tag e) 'quote) occurrences (if (equal? (tag e) 'if)

(if (equal? (be (e1 e) vn vt) 'S)

(count (e1 e) vn vt (maxoccs (count (e2 e) vn vt occurrences) (count (e3 e) vn vt occurrences)))

(count (e1 e) vn vt (count (e2 e) vn vt

(count (e3 e) vn vt occurrences)))) (if (or (equal? (tag e) 'call) (equal? (tag e) 'op))

(foldl (lambda (occs e)(count e vn vt occs)) occurrences (callargs e)) (error 'count "Illegal Scheme0 expression: ~s" e)

)))))))

(define (incvar x vn occurrences) (if vn

(if (equal? x (car vn))

(cons (if (equal? (car occurrences) 0) 1 2) (cdr occurrences))

(cons (car occurrences) (incvar x (cdr vn) (cdr occurrences)))) (error 'incvar "Unknown variable: ~s" x)

))

(define (maxoccs occs1 occs2)

(if occs1 (cons (max (car occs1) (car occs2)) (maxoccs (cdr occs1) (cdr occs2)))

()

))

(define (static ae) (equal? (cdr ae) 'S))

(define (exp ae) (car ae))

(define (lift ae) (if (static ae) (list 'lift (car ae)) (car ae)))

; Find least sdpattern in sdpatterns which is compatible with sdpat

(define (getleast sdpat sdpatterns f) (if sdpatterns

(if (sdpattern-leq sdpat (car sdpatterns)) (car sdpatterns)

(getleast sdpat (cdr sdpatterns) f))

(error 'annotate "Incongruent division ~s at function ~s" sdpat f)

))

The le specialize.ss de nes the specializer itself and its auxiliary functions (successors, diff, lookupfun, . . . ).

;File "spec.ss" -- The specializer written in Scheme0

;Partial evaluator for first order functional language

;The specializer itself, written in Scheme0. Inputs: annotated Scheme0

;program and values of the static parameters. Output: a Scheme0 program.

The components of the Scheme0 specializer 387

(define specializer (desugar '(

(define (specialize program vs0)

(call complete (list (:: (name (hd program)) vs0)) () program)

)

(define (complete pending marked program) (if pending

(call generate (hd pending) program pending marked program) ()

))

(define (generate fvs defs pending marked program) (if defs

(slet (def (hd defs))

(if (op equal? (name def) (hd fvs))

(slet (evs (call reduce (body def) (svar def) (tl fvs) (dvar def) (dvar def) program))

(slet (newmarked (:: fvs marked))

(call gen1 def evs fvs pending newmarked program))) (call generate fvs (tl defs) pending marked program)))

(op error 'generate '"Undefined function: ~s" (hd fvs))

))

(define (gen1 def evs fvs pending newmarked program)

(slet (newpending (op diff (op successors evs pending) newmarked))

(slet (newdef

(list 'define (:: fvs (dvar def)) evs))

(:: newdef (call complete newpending newmarked program))

)))

 

 

(define (reduce e xs vs xd vd p)

(if (op null? e)

 

e

(if (op number? e)

e

(if (op atom? e)

 

(call lookupvar e xs vs xd vd)

(if (op equal? (tag

e) 'quote) (e1 e)

(if (op equal? (tag

e) 'ifs)

(if (call reduce (e1 e) xs vs xd vd p) (call reduce (e2 e) xs vs xd vd p) (call reduce (e3 e) xs vs xd vd p))

(if (op equal? (tag e) 'ifd)

(list 'if (call reduce (e1 e) xs vs xd vd p) (call reduce (e2 e) xs vs xd vd p) (call reduce (e3 e) xs vs xd vd p))

(if (op equal? (tag e) 'calls)

(call docalls (op lookupfun (funname e) p) p (call reduce* (sfunargs e) xs vs xd vd p) (call reduce* (dfunargs e) xs vs xd vd p))

(if (op equal? (tag e) 'calld) (:: 'call

(:: (:: (funname e) (call reduce* (sfunargs e) xs vs xd vd p)) (call reduce* (dfunargs e) xs vs xd vd p)))

(if (op equal? (tag e) 'ops)

(op evalbase (funname e) (call reduce* (callargs e) xs vs xd vd p)) (if (op equal? (tag e) 'opd)

(:: 'op (:: (funname e) (call reduce* (callargs e) xs vs xd vd p))) (if (op equal? (tag e) 'lift)

(list 'quote (call reduce (e1 e) xs vs xd vd p))

(op error 'reduce '"Illegal annotated Scheme0 expression: ~s" e)

))))))))))))

(define (reduce* es xs vs xd vd p) (if es

(:: (call reduce (hd es) xs vs xd vd p) (call reduce* (tl es) xs vs xd vd p))

'()

388 The Self-Applicable Scheme0 Specializer

))

(define (docalls def p args argd)

(if (op nodup (tl (hd (name def))) argd)

(call reduce (body def) (svar def) args (dvar def) argd p) (:: 'call (:: (:: (name def) args) argd))

))

(define (lookupvar x xs vs xd vd) (if xs

(if (op equal? x (hd xs)) (hd vs)

(call lookupvar x (tl xs) (tl vs) xd vd)) (call lookupvar x xd vd 'slam 'slam)

))

)))

; Auxiliary base functions for the specializer

(define (successors e s)

(if (null? e)

s

(if (number? e)

s

(if (atom? e)

s

(if (equal? (tag e) 'quote) s

(if (equal? (tag e) 'if)

(successors

(e1 e) (successors (e2 e) (successors (e3 e) s)))

(if (equal? (tag e) 'call)

(successors* (callargs e) (cons (funname e) s)) (if (equal? (tag e) 'op)

(successors* (callargs e) s)

(error 'successors '"Illegal Scheme0 expression: ~s" e)

))))))))

(define (successors* es s) (foldl (lambda (s e) (successors e s)) s es))

(define (diff set1 set2) (if set1

(if (member (car set1) set2) (diff (cdr set1) set2)

(cons (car set1) (diff (cdr set1) set2)))

()

))

(define (nodup occs exps) (if occs

(and (or (atom? (car exps)) (< (car occs) 2)) (nodup (cdr occs) (cdr exps)))

't

))

(define (lookupfun f program) (if program

(if (equal? f (name (car program))) (car program)

(lookupfun f (cdr program)))

(error 'lookupfun '"Undefined function: ~s" f)

))

(define (evalbase f args) (apply (s0eval f) args))

Bibliography

[1]ACM, Partial Evaluation and Semantics-Based Program Manipulation, New Haven, Connecticut (Sigplan Notices, vol. 26, no. 9, September 1991), New York: ACM, 1991.

[2]ACM, Partial Evaluation and Semantics-Based Program Manipulation, San Francisco, California, June 1992 (Technical Report YALEU/DCS/RR-909), New Haven, CT: Yale University, 1992.

[3]A.V. Aho and S.C. Johnson, `LR parsing', Computing Surveys, 6(2):99{124, 1974.

[4]A.V. Aho, R. Sethi, and J.D. Ullman, Compilers: Principles, Techniques, and Tools, Reading, MA: Addison-Wesley, 1986.

[5]M. Ajtai, J. Komlos, and E. Szemeredi, `Sorting in c log n parallel steps', Combinatorica, 3:1{19, 1983.

[6]L.O. Andersen, `C program specialization', Master's thesis, DIKU, University of Copenhagen, Denmark, December 1991. Student Project 91-12-17.

[7]L.O. Andersen, C Program Specialization, Technical Report 92/14, DIKU, University of Copenhagen, Denmark, May 1992.

[8]L.O. Andersen, `Partial evaluation of C and automatic compiler generation (extended abstract)', in U. Kastens and P. Pfahler (eds.), Compiler Construction, Paderborn, Germany, October 1992 (Lecture Notes in Computer Science, vol. 641), pp. 251{257, Berlin: Springer-Verlag, 1992.

[9]L.O. Andersen, `Self-applicable C program specialization', in Partial Evaluation and Semantics-Based Program Manipulation, San Francisco, California, June 1992 (Technical Report YALEU/DCS/RR-909), pp. 54{61, New Haven, CT: Yale University, June 1992.

[10]L.O. Andersen, `Binding-time analysis and the taming of C pointers', in Partial Evaluation and Semantics-Based Program Manipulation, Copenhagen, Denmark, June 1993, New York: ACM, 1993. To appear.

[11]L.O. Andersen and C.K. Gomard, `Speedup analysis in partial evaluation (preliminary results)', in Partial Evaluation and Semantics-Based Program Manipulation, San Francisco, California, June 1992 (Technical Report YALEU/DCS/RR-909), pp. 1{7, New Haven, CT: Yale University, 1992.

[12]L.O. Andersen and C. Mossin, `Binding time analysis via type inference'. Student Project 90-10-12, DIKU, University of Copenhagen, Denmark, October 1990.

389

390Bibliography

[13]A. Appel, `Reopening closures'. Personal communication, January 1988.

[14]W.-Y. Au, D. Weise, and S. Seligman, `Generating compiled simulations using partial evaluation', in 28th Design Automation Conference, pp. 205{210, New York: IEEE, June 1991.

[15]L. Augustsson, `Compiling pattern matching', in J.-P. Jouannaud (ed.), Functional Programming Languages and Computer Architecture, Nancy, France, 1985 (Lecture Notes in Computer Science, vol. 201), pp. 368{381, Berlin: Springer-Verlag, 1985.

[16]H.P. Barendregt, The Lambda Calculus: Its Syntax and Semantics, Amsterdam: NorthHolland, second edition, 1984.

[17]K.E. Batcher, `Sorting networks and their applications', in Proceedings AFIPS Spring Joint Computer Conference, pp. 307{314, American Federation of Information Processing Societies, 1968.

[18]D. Bechet, `Partial evaluation of interaction nets', in M. Billaud et al. (eds.), WSA '92, Static Analysis, Bordeaux, France, September 1992. Bigre vols 81{82, 1992, pp. 331{338, Rennes: IRISA, 1992.

[19]L. Beckman et al., `A partial evaluator, and its use as a programming tool', Arti cial Intelligence, 7(4):319{357, 1976.

[20] K. Benkerimi and J.W. Lloyd, `A partial evaluation procedure for logic programs', in

S.Debray and M. Hermenegildo (eds.), Logic Programming: Proceedings of the 1990 North American Conference, Austin, Texas, October 1990, pp. 343{358, Cambridge, MA: MIT Press, 1990.

[21]A. Berlin and D. Weise, `Compiling scienti c code using partial evaluation', IEEE Computer, 23(12):25{37, December 1990.

[22]A.A. Berlin, `Partial evaluation applied to numerical computation', in 1990 ACM Conference on Lisp and Functional Programming, Nice, France, pp. 139{150, New York: ACM, 1990.

[23]R.S. Bird, `Improving programs by the introduction of recursion', Communications of the ACM, 20(11):856{863, 1977.

[24]D. Bj rner, A.P. Ershov, and N.D. Jones (eds.), Partial Evaluation and Mixed Computation. Proceedings of the IFIP TC2 Workshop, Gammel Avern s, Denmark, October 1987, Amsterdam: North-Holland, 1988.

[25]D. Bj rner and C.B. Jones, Formal Speci cation and Software Development, Englewood Cli s, NJ: Prentice Hall, 1982.

[26]A. Bondorf, `Towards a self-applicable partial evaluator for term rewriting systems', in

D.Bj rner, A.P. Ershov, and N.D. Jones (eds.), Partial Evaluation and Mixed Computation, pp. 27{50, Amsterdam: North-Holland, 1988.

[27]A. Bondorf, `Self-applicable partial evaluation', Ph.D. thesis, DIKU, University of Copenhagen, Denmark, 1990. Revised version: DIKU Report 90/17.

[28]A. Bondorf, `Automatic autoprojection of higher order recursive equations', Science of Computer Programming, 17:3{34, 1991.

[29]A. Bondorf, Similix Manual, System Version 3.0, Technical Report 91/9, DIKU, University of Copenhagen, Denmark, 1991.

[30]A. Bondorf, Similix Manual, System Version 4.0, technical report, DIKU, University of Copenhagen, Denmark, 1991.