Clean up handling of (let) and (%bind), plus misc. cleanup.

With this change, any (%bind) returned from (simplify-let) or (simplify-form)
can be assumed to be flat, with unique bound symbols. Before, this was only
true of (%lambda) forms and the output of (compile).
This commit is contained in:
Jesse D. McDonald 2010-04-15 12:23:09 -05:00
parent 6b51229c48
commit 0b0b352dd6
1 changed files with 103 additions and 99 deletions

View File

@ -14,7 +14,7 @@
[(letrec) (simplify-letrec form)] [(letrec) (simplify-letrec form)]
[(if) (simplify-if form)] [(if) (simplify-if form)]
[(lambda) (simplify-lambda form)] [(lambda) (simplify-lambda form)]
[(begin) `(%bind () ,@(map simplify-form (cdr form)))] [(begin) (simplify-form `(let () ,@(cdr form)))]
[(set!) (simplify-set! form)] [(set!) (simplify-set! form)]
[(car cdr cons) (simplify-primitive (case (first form) [(car cdr cons) (simplify-primitive (case (first form)
[(car) '%car] [(car) '%car]
@ -28,18 +28,19 @@
(define (simplify-set! form) (define (simplify-set! form)
(let ([value-form (simplify-form (third form))]) (let ([value-form (simplify-form (third form))])
(if (and (pair? value-form) (eq? (first value-form) '%bind)) (if (and (pair? value-form) (eq? (first value-form) '%bind))
`(%bind ,(second value-form) (simplify-form
`(let ,(second value-form)
,@(foldr (lambda (subform after) ,@(foldr (lambda (subform after)
(if (pair? after) (cond
(cons subform after) [(pair? after) (cons subform after)]
(if (or (not (pair? subform)) [(or (not (pair? subform))
(memq (first subform) '(%apply %car %cdr %cons %bind %if))) (memq (first subform) '(%apply %car %cdr %cons %bind %if)))
(list (simplify-set! `(set! ,(second form) ,subform))) `((set! ,(second form) ,subform))]
(if (and (pair? subform) (eq? (first subform) '%tail-call)) [(and (pair? subform) (eq? (first subform) '%tail-call))
(list subform) ; The %set! wouldn't be executed anyway. `(,subform)] ; The %set! wouldn't be executed anyway.
(error "set! used with non-value form:" subform))))) [else (error "set! used with non-value form:" subform)]))
'() '()
(cddr value-form))) (cddr value-form))))
`(%set! ,(second form) ,value-form)))) `(%set! ,(second form) ,value-form))))
(define (simplify-primitive new-id value-forms) (define (simplify-primitive new-id value-forms)
@ -50,10 +51,10 @@
value-forms)) value-forms))
(define temp-bindings (filter (lambda (x) (not (eq? (first x) (second x)))) (define temp-bindings (filter (lambda (x) (not (eq? (first x) (second x))))
bindings)) bindings))
(simplify-form
`(%bind ,(map first temp-bindings) `(let ,(map first temp-bindings)
,@(map (lambda (x) (simplify-set! `(set! ,(first x) ,(second x)))) temp-bindings) ,@(map (lambda (x) `(set! ,(first x) ,(second x))) temp-bindings)
(,new-id ,@(map first bindings)))) (,new-id ,@(map first bindings)))))
; (let ([var expr]...) bodyexpr...) ; first eval exprs, then assign bindings in parallel ; (let ([var expr]...) bodyexpr...) ; first eval exprs, then assign bindings in parallel
; => (%bind (tmp...) ; => (%bind (tmp...)
@ -65,29 +66,34 @@
(define (simplify-let form) (define (simplify-let form)
(define bindings (second form)) (define bindings (second form))
(define bodyexprs (cdr (cdr form))) (define bodyexprs (cdr (cdr form)))
(define vars (map (lambda (x) (if (pair? x) (first x) x)) bindings)) (flatten-binds
(define temp-bindings (cond
(append-map [(not (pair? bindings))
(lambda (x) (if (pair? x) `(%bind () ,@(map simplify-form bodyexprs))]
[(not (pair? (cdr bindings)))
(let ([binding (first bindings)])
(make-bindings-unique
`(%bind (,(if (pair? binding) (first binding) binding))
,@(if (pair? binding) `(,(simplify-set! `(set! ,(first binding)
,(second binding))))
'())
,@(map simplify-form bodyexprs))))]
[else
(let ([vars (map (lambda (x) (if (pair? x) (first x) x)) bindings)]
[temp-bindings (append-map (lambda (x)
(if (pair? x)
(let ([tmp (gensym)]) (let ([tmp (gensym)])
`((,tmp `((,tmp
,(simplify-form `(set! ,tmp ,(second x))) ,(simplify-form `(set! ,tmp ,(second x)))
(%set! ,(first x) ,tmp)))) (%set! ,(first x) ,tmp))))
'())) '()))
bindings)) bindings)])
(if (pair? bindings)
(if (pair? (cdr bindings))
`(%bind ,(map first temp-bindings) `(%bind ,(map first temp-bindings)
,@(map second temp-bindings) ,@(map second temp-bindings)
(%bind ,vars ,(make-bindings-unique
`(%bind ,vars
,@(map third temp-bindings) ,@(map third temp-bindings)
,@(map simplify-form bodyexprs))) ,@(map simplify-form bodyexprs)))))])))
`(%bind (,(first vars))
,@(if (pair? (first bindings))
`(,(simplify-form `(set! ,(first vars) ,(second (first bindings)))))
'())
,@(map simplify-form bodyexprs)))
`(%bind () ,@(map simplify-form bodyexprs))))
; (let* ...) ; eval exprs & bind variables serially ; (let* ...) ; eval exprs & bind variables serially
; => (let ([var-0 expr-0]) ; => (let ([var-0 expr-0])
@ -110,14 +116,15 @@
(define (simplify-letrec form) (define (simplify-letrec form)
(define bindings (second form)) (define bindings (second form))
(define bodyexprs (cdr (cdr form))) (define bodyexprs (cdr (cdr form)))
`(%bind (,@(map (lambda (x) (if (pair? x) (first x) x)) bindings)) (simplify-form
`(let (,@(map (lambda (x) (if (pair? x) (first x) x)) bindings))
,@(append-map ,@(append-map
(lambda (x) (lambda (x)
(if (pair? x) (if (pair? x)
`(,(simplify-form `(set! ,(first x) ,(simplify-form (second x))))) `((set! ,(first x) ,(second x)))
'())) '()))
bindings) bindings)
,@(map simplify-form bodyexprs))) ,@bodyexprs)))
(define (simplify-if form) (define (simplify-if form)
(define cond-val (gensym)) (define cond-val (gensym))
@ -175,32 +182,34 @@
(define (add-tail-call k rval form) (define (add-tail-call k rval form)
`(%bind ,(second form) `(%bind ,(second form)
,@(foldr (lambda (subform after) ,@(foldr (lambda (subform after)
(if (pair? after) (cond
(cons subform after) [(pair? after)
(if (and (pair? subform) (cons subform after)]
[(and (pair? subform)
(eq? (first subform) '%set!) (eq? (first subform) '%set!)
(eq? (second subform) rval) (eq? (second subform) rval)
(pair? (third subform)) (pair? (third subform))
(eq? (first (third subform)) '%apply)) (eq? (first (third subform)) '%apply))
(let ([fn (second (third subform))] (let ([fn (second (third subform))]
[argv (third (third subform))]) [argv (third (third subform))])
`((%tail-call ,fn ,argv ,k))) `((%tail-call ,fn ,argv ,k)))]
(if (and (pair? subform) [(and (pair? subform)
(eq? (first subform) '%tail-call)) (eq? (first subform) '%tail-call))
(list subform) `(,subform)]
(if (and (pair? subform) [(and (pair? subform)
(eq? (first subform) '%apply)) (eq? (first subform) '%apply))
`((%tail-call ,(second subform) `((%tail-call ,(second subform)
,(third subform) ,(third subform)
,k)) ,k))]
(if (and (pair? subform) [(and (pair? subform)
(eq? (first subform) '%set!) (eq? (first subform) '%set!)
(eq? (second subform) rval)) (eq? (second subform) rval))
`(,subform `(,subform
(%set! ,rval (%cons ,rval %nil)) (%set! ,rval (%cons ,rval %nil))
(%tail-call ,k ,rval #f)) (%tail-call ,k ,rval #f))]
[else
`(,subform `(,subform
(%tail-call ,k %nil #f)))))))) (%tail-call ,k %nil #f))]))
'() '()
(cddr form)))) (cddr form))))
@ -231,14 +240,13 @@
(flatten-binds (flatten-binds
`(%bind (,rval ,k) `(%bind (,rval ,k)
(%set! ,k %k) (%set! ,k %k)
,(make-bindings-unique ,(simplify-form
(simplify-form
`(set! ,rval (let ([,argv-temp %argv]) `(set! ,rval (let ([,argv-temp %argv])
,(foldr add-req ,(foldr add-req
(foldr add-opt (foldr add-opt
rest+bodyexprs rest+bodyexprs
optionals) optionals)
requireds))))))))))) requireds))))))))))
; <= (%bind (var...) ; <= (%bind (var...)
; @before ; @before
; (%apply x y) ; (%apply x y)
@ -306,12 +314,13 @@
(define fn-var (gensym)) (define fn-var (gensym))
(define arg-vars (map (lambda (x) (gensym)) arg-exprs)) (define arg-vars (map (lambda (x) (gensym)) arg-exprs))
(define argv (gensym)) (define argv (gensym))
`(%bind (,fn-var ,@arg-vars ,argv) (simplify-form
,(simplify-form `(set! ,fn-var ,fn-expr)) `(let (,fn-var ,@arg-vars ,argv)
,@(map (lambda (x y) (simplify-form `(set! ,x ,y))) arg-vars arg-exprs) (set! ,fn-var ,fn-expr)
,@(map (lambda (x y) `(set! ,x ,y)) arg-vars arg-exprs)
(%set! ,argv %nil) (%set! ,argv %nil)
,@(reverse (map (lambda (x) `(%set! ,argv (%cons ,x ,argv))) arg-vars)) ,@(reverse (map (lambda (x) `(%set! ,argv (%cons ,x ,argv))) arg-vars))
(%apply ,fn-var ,argv))) (%apply ,fn-var ,argv))))
(define (subst-var old-var new-var form) (define (subst-var old-var new-var form)
(define (recurse form) (define (recurse form)
@ -340,7 +349,7 @@
(subst-var (car pair) (subst-var (car pair)
(cdr pair) (cdr pair)
s)) s))
(make-bindings-unique frm) frm
(map cons (second form) new-vars))) (map cons (second form) new-vars)))
(cddr form))))] (cddr form))))]
[(%if %tail-call %apply %lambda %set! %cons %car %cdr) form] [(%if %tail-call %apply %lambda %set! %cons %car %cdr) form]
@ -365,13 +374,8 @@
[else (error "Unsimplified form:" form)]) [else (error "Unsimplified form:" form)])
form)) form))
(define (compile-lambda lambda-form)
(flatten-binds
(make-bindings-unique
(simplify-form lambda-form))))
(define (compile form) (define (compile form)
(compile-lambda `(lambda () ,form))) (simplify-form `(lambda () ,form)))
(define (free-variables form [input? #t] [output? #t]) (define (free-variables form [input? #t] [output? #t])
(define (recurse form) (free-variables form input? output?)) (define (recurse form) (free-variables form input? output?))
@ -439,8 +443,8 @@
(reduce-set! (reduce-set!
form))) form)))
;(void (trace optimize (trace compile-lambda (trace simplify-form `(lambda () ,(read))))))
;(pretty-print (compile (read)))
(pretty-print (optimize (compile (read)))) (pretty-print (optimize (compile (read))))
;(pretty-print (compile (read)))
;(pretty-print (optimize (trace compile (read))))
; vim:set sw=2 expandtab: ; vim:set sw=2 expandtab: