1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-21 20:20:24 +02:00

Reduce call-with-values to let for singly-valued producers

* module/language/tree-il/peval.scm (singly-valued-expression?): Add
  support for conditionals.  In the future we should add more
  expressions here.
  (peval): Don't inline values into the body of a dynwind, as that could
  cause the consumer to run in the wrong dynamic context.
  If the producer is singly-valued and the consumer just has a rest arg,
  reduce to "let" and cons up a list in the consumer.  This may reduce
  further.

* test-suite/tests/peval.test ("partial evaluation"): Add a test.
This commit is contained in:
Andy Wingo 2013-06-16 15:02:34 +02:00
parent b34b66b346
commit e6450062a1
2 changed files with 29 additions and 4 deletions

View file

@ -101,6 +101,9 @@
(($ <primcall> _ (? singly-valued-primitive?)) #t)
(($ <primcall> _ 'values (val)) #t)
(($ <lambda>) #t)
(($ <conditional> _ test consequent alternate)
(and (singly-valued-expression? consequent)
(singly-valued-expression? alternate)))
(else #f)))
(define (truncate-values x)
@ -538,6 +541,10 @@ top-level bindings from ENV and return the resulting expression."
(($ <prompt>) #f)
(($ <abort>) #f)
;; Bail on dynwinds, as that would cause the consumer to run in
;; the wrong dynamic context.
(($ <dynwind>) #f)
;; Propagate to tail positions.
(($ <let> src names gensyms vals body)
(let ((body (loop body)))
@ -558,10 +565,6 @@ top-level bindings from ENV and return the resulting expression."
(make-let-values src exp
(make-lambda-case src2 req opt rest kw
inits gensyms body #f)))))
(($ <dynwind> src winder pre body post unwinder)
(let ((body (loop body)))
(and body
(make-dynwind src winder pre body post unwinder))))
(($ <dynlet> src fluids vals body)
(let ((body (loop body)))
(and body
@ -975,6 +978,19 @@ top-level bindings from ENV and return the resulting expression."
(for-tail
(make-let src (list req-name) (list req-sym) (list producer)
body)))
((and ($ <lambda-case> src () #f rest #f () (rest-sym) body #f)
(? (lambda _ (singly-valued-expression? producer))))
(let ((tmp (gensym "tmp ")))
(record-new-temporary! 'tmp tmp 1)
(for-tail
(make-let
src (list 'tmp) (list tmp) (list producer)
(make-let
src (list rest) (list rest-sym)
(list
(make-primcall #f 'list
(list (make-lexical-ref #f 'tmp tmp))))
body)))))
(($ <lambda-case> src req opt rest #f inits gensyms body #f)
(let* ((nmin (length req))
(nmax (and (not rest) (+ nmin (if opt (length opt) 0)))))

View file

@ -983,6 +983,15 @@
(apply list args)))
(primcall list (const 1) (const 2)))
(pass-if-peval
;; When we can't inline let-values but can prove that the producer
;; has just one value, reduce to "let" (which can then fold
;; further).
(call-with-values (lambda () (if foo 1 2))
(lambda args
(apply values args)))
(if (toplevel foo) (const 1) (const 2)))
(pass-if-peval
;; Constant folding: cons of #nil does not make list
(cons 1 #nil)