mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-21 12:10:26 +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:
parent
b34b66b346
commit
e6450062a1
2 changed files with 29 additions and 4 deletions
|
@ -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)))))
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue