;;
(define store (build-var-table exp))
+ (define (record-new-temporary! name sym refcount)
+ (set! store (vhash-consq sym (make-var name sym refcount #f) store)))
+
(define (lookup-var sym)
(let ((v (vhash-assq sym store)))
(if v (cdr v) (error "unbound var" sym (vlist->list store)))))
(for-tail (make-const src head)))
(('cdr ($ <const> src (head . tail)))
(for-tail (make-const src tail)))
+ (((or 'memq 'memv) k ($ <const> _ (elts ...)))
+ ;; FIXME: factor
+ (case ctx
+ ((effect)
+ (for-tail
+ (make-sequence src (list k (make-void #f)))))
+ ((test)
+ (cond
+ ((const? k)
+ ;; A shortcut. The `else' case would handle it, but
+ ;; this way is faster.
+ (let ((member (case name ((memq) memq) ((memv) memv))))
+ (make-const #f (and (member (const-exp k) elts) #t))))
+ ((null? elts)
+ (for-tail
+ (make-sequence src (list k (make-const #f #f)))))
+ (else
+ (let ((t (gensym "t "))
+ (eq (if (eq? name 'memq) 'eq? 'eqv?)))
+ (record-new-temporary! 't t (length elts))
+ (for-tail
+ (make-let
+ src (list 't) (list t) (list k)
+ (let lp ((elts elts))
+ (define test
+ (make-application
+ #f (make-primitive-ref #f eq)
+ (list (make-lexical-ref #f 't t)
+ (make-const #f (car elts)))))
+ (if (null? (cdr elts))
+ test
+ (make-conditional src test
+ (make-const #f #t)
+ (lp (cdr elts)))))))))))
+ (else
+ (cond
+ ((const? k)
+ (let ((member (case name ((memq) memq) ((memv) memv))))
+ (make-const #f (member (const-exp k) elts))))
+ ((null? elts)
+ (for-tail (make-sequence src (list k (make-const #f #f)))))
+ (else
+ (make-application src proc (list k (make-const #f elts))))))))
((_ . args)
(make-application src proc args))))
(($ <primitive-ref> _ (? effect-free-primitive? name))
(and (even? 4) (odd? 7)))
(const #t))
+ (pass-if-peval
+ ;; Memv with constants.
+ (memv 1 '(3 2 1))
+ (const '(1)))
+
+ (pass-if-peval
+ ;; Memv with non-constant list. It could fold but doesn't
+ ;; currently.
+ (memv 1 (list 3 2 1))
+ (apply (primitive memv)
+ (const 1)
+ (apply (primitive list) (const 3) (const 2) (const 1))))
+
+ (pass-if-peval
+ ;; Memv with non-constant key, constant list, test context
+ (case foo
+ ((3 2 1) 'a)
+ (else 'b))
+ (if (let (t) (_) ((toplevel foo))
+ (if (apply (primitive eqv?) (lexical t _) (const 3))
+ (const #t)
+ (if (apply (primitive eqv?) (lexical t _) (const 2))
+ (const #t)
+ (apply (primitive eqv?) (lexical t _) (const 1)))))
+ (const a)
+ (const b)))
+
+ (pass-if-peval
+ ;; Memv with non-constant key, empty list, test context. Currently
+ ;; doesn't fold entirely.
+ (case foo
+ (() 'a)
+ (else 'b))
+ (if (begin (toplevel foo) (const #f))
+ (const a)
+ (const b)))
+
;;
;; Below are cases where constant propagation should bail out.
;;