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

peval: Truncate multiple values when extending the environment.

Reported by Cédric Cellier <rixed@happyleptic.org>.

* module/language/tree-il/peval.scm (truncate-values): New procedure.
  (make-operand): Call `truncate-values' SOURCE.

* test-suite/tests/tree-il.test ("partial evaluation"): New tests for
  multiple value truncation.
This commit is contained in:
Ludovic Courtès 2011-12-06 21:36:49 +01:00
parent 679eea4f0e
commit bcec8858a8
2 changed files with 61 additions and 1 deletions

View file

@ -99,6 +99,47 @@
(or (proc (vlist-ref vlist i)) (or (proc (vlist-ref vlist i))
(lp (1+ i))))))) (lp (1+ i)))))))
(define (truncate-values x)
"Discard all but the first value of X."
(let loop ((x x))
(match x
(($ <const>) x)
(($ <lexical-ref>) x)
(($ <void>) x)
(($ <lexical-ref>) x)
(($ <primitive-ref>) x)
(($ <module-ref>) x)
(($ <toplevel-ref>) x)
(($ <conditional> src condition subsequent alternate)
(make-conditional src condition (loop subsequent) (loop alternate)))
(($ <application> _ ($ <primitive-ref> _ 'values) (first _ ...))
first)
(($ <application> _ ($ <primitive-ref> _ 'values) (val))
val)
(($ <application> src
(and prim ($ <primitive-ref> _ (? singly-valued-primitive?)))
args)
(make-application src prim (map loop args)))
(($ <application> src proc args)
(make-application src proc (map loop args)))
(($ <sequence> src (exps ... last))
(make-sequence src (append exps (list (loop last)))))
(($ <lambda>) x)
(($ <dynlet> src fluids vals body)
(make-dynlet src fluids vals (loop body)))
(($ <let> src names gensyms vals body)
(make-let src names gensyms vals (loop body)))
(($ <letrec> src in-order? names gensyms vals body)
(make-letrec src in-order? names gensyms vals (loop body)))
(($ <fix> src names gensyms vals body)
(make-fix src names gensyms vals body))
(($ <let-values> src exp body)
(make-let-values src exp (loop body)))
(else
(make-application (tree-il-src x)
(make-primitive-ref #f 'values)
(list x))))))
;; Peval will do a one-pass analysis on the source program to determine ;; Peval will do a one-pass analysis on the source program to determine
;; the set of assigned lexicals, and to identify unreferenced and ;; the set of assigned lexicals, and to identify unreferenced and
;; singly-referenced lexicals. ;; singly-referenced lexicals.
@ -278,8 +319,10 @@
(constant-value operand-constant-value set-operand-constant-value!)) (constant-value operand-constant-value set-operand-constant-value!))
(define* (make-operand var sym #:optional source visit) (define* (make-operand var sym #:optional source visit)
;; Bind SYM to VAR, with value SOURCE.
;; Bound operands are considered copyable until we prove otherwise. ;; Bound operands are considered copyable until we prove otherwise.
(%make-operand var sym visit source 0 #f (and source #t) #f #f)) (let ((source (if source (truncate-values source) source)))
(%make-operand var sym visit source 0 #f (and source #t) #f #f)))
(define (make-bound-operands vars syms sources visit) (define (make-bound-operands vars syms sources visit)
(map (lambda (x y z) (make-operand x y z visit)) vars syms sources)) (map (lambda (x y z) (make-operand x y z visit)) vars syms sources))

View file

@ -664,6 +664,23 @@
(+ a b)))) (+ a b))))
(const 3)) (const 3))
(pass-if-peval resolve-primitives
;; First order, multiple values.
(let ((x 1) (y 2))
(values x y))
(apply (primitive values) (const 1) (const 2)))
(pass-if-peval resolve-primitives
;; First order, multiple values truncated.
(let ((x (values 1 'a)) (y 2))
(values x y))
(apply (primitive values) (const 1) (const 2)))
(pass-if-peval resolve-primitives
;; First order, multiple values truncated.
(or (values 1 2) 3)
(const 1))
(pass-if-peval (pass-if-peval
;; First order, coalesced, mutability preserved. ;; First order, coalesced, mutability preserved.
(cons 0 (cons 1 (cons 2 (list 3 4 5)))) (cons 0 (cons 1 (cons 2 (list 3 4 5))))