[PRL] Type-directed partial evaluation
David Herman
dherman at ccs.neu.edu
Thu Jan 8 14:43:37 EST 2004
And now for the Scheme magic of the day, thanks to Danvy [1]. Assume a
mini-Scheme with curried unary functions, atoms and pairs. If you give
me a *compiled* mini-Scheme program and its type, I will *decompile* it
back to (alpha-beta-eta-equivalent) source, amazingly with only a few
dozen LOC. Here's a sample interaction:
> (define S (lambda (f)
(lambda (g)
(lambda (x)
((f x) (g x))))))
> (residualize S '((A -> B -> C) -> (A -> B) -> A -> C))
(lambda (x0) (lambda (x1) (lambda (x2) ((x0 x2) (x1 x2)))))
> (define I*K (cons (lambda (x) x)
(lambda (y) (lambda (z) y))))
> (residualize I*K '((A -> A) * (B -> C -> B)))
(cons (lambda (x0) x0) (lambda (x1) (lambda (x2) x1))
Decompiling a value of ground type or a pair is easy. The trick to
decompiling a function is eta-expansion: although you can't inspect a
function, you can always apply it. By applying it in the body of a new
function, you can generate a dynamic (i.e., uncompiled) function that
is eta-equivalent to the original (compiled) function. However, the new
variable in the eta-expanded function is dynamic, and the compiled
function is static. So the variable has to be converted to a static
value before it can be passed to the compiled function. For this we
need a complementary `reflect' operation which takes dynamic
expressions to static values.
;; reify : type static-value -> dynamic-expression
;; reifies a static value into a dynamic program based on the
specified type
(define (reify t v)
(match t
[`(,t1 * ,t2)
`(cons ,(reify t1 (car v))
,(reify t2 (cdr v)))]
[`(,t1 -> ,t2)
(let ([x1 (gensym!)])
`(lambda (,x1)
,(reify t2 (v (reflect t1 x1)))))]
[_ v]))
;; reflect : type dynamic-expression -> static-value
;; reflects a program into a static value based on the specified
type
(define (reflect t e)
(match t
[`(,t1 * ,t2)
(cons (reflect t1 `(car ,e))
(reflect t2 `(cdr ,e)))]
[`(,t1 -> ,t2)
(lambda (v1)
(reflect t2 `(,e ,(reify t1 v1))))]
[_ e]))
;; residualize : any type -> program
;; decompiles a program
(define (residualize v t)
(reset-gensym!)
(reify (parse-type t) v))
[The parse-type function curries a type expression (e.g., '(A -> B ->
C) becomes '(A -> (B -> C))).]
Cool, huh?
Dave
[1] Olivier Danvy: Type-directed partial evaluation. POPL '96.
More information about the PRL
mailing list