[PRL] Type-directed partial evaluation

Matthias Felleisen matthias at ccs.neu.edu
Thu Jan 8 17:02:55 EST 2004


Take PCF instead of Scheme. Take good(tm) domains instead of 
target-machine code (and read some of Mitch's old papers from the early 
80s). Then I can create source text for all infinite computable
"compiled codes" using call/cc. Though I have to admit that the 
algorithm is burried in two papers
and I only know the one for finite computable "codes" reasonable well 
to do it on the spot.

-- Matthias


On Thursday, January 8, 2004, at 02:43 PM, David Herman wrote:

> 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.
>
> _______________________________________________
> PRL mailing list
> PRL at lists.ccs.neu.edu
> https://lists.ccs.neu.edu/bin/listinfo/prl



More information about the PRL mailing list