1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-04-30 03:40:34 +02:00

Fix order-of-side-effects bug in (eq? x y z) expansion

* module/language/tree-il/primitives.scm (bind-lexicals): New helper.
(expand-eq, expand-chained-comparisons): Ensure all arguments are
eagerly evaluated.  Previously an intermediate #f result would shortcut
the evaluation.
* test-suite/tests/compiler.test ("size effects in multi-arg eq / <"):
Add test.
This commit is contained in:
Andy Wingo 2022-12-01 12:56:51 +01:00
parent c7fa78fc75
commit d184d09346
2 changed files with 45 additions and 12 deletions

View file

@ -1,6 +1,6 @@
;;; open-coding primitive procedures ;;; open-coding primitive procedures
;; Copyright (C) 2009-2015, 2017-2021 Free Software Foundation, Inc. ;; Copyright (C) 2009-2015, 2017-2022 Free Software Foundation, Inc.
;;;; This library is free software; you can redistribute it and/or ;;;; This library is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU Lesser General Public ;;;; modify it under the terms of the GNU Lesser General Public
@ -568,17 +568,32 @@
(define-primitive-expander f64vector-set! (vec i x) (define-primitive-expander f64vector-set! (vec i x)
(bytevector-ieee-double-native-set! vec (* i 8) x)) (bytevector-ieee-double-native-set! vec (* i 8) x))
(define (bind-lexicals src exps k)
(match exps
(() (k '()))
((exp . exps)
(with-lexicals src (exp)
(bind-lexicals src exps (lambda (exps) (k (cons exp exps))))))))
(define (expand-eq prim) (define (expand-eq prim)
(case-lambda (case-lambda
((src) (make-const src #t)) ((src) (make-const src #t))
((src a) (make-const src #t)) ((src a) (make-const src #t))
((src a b) #f) ((src a b) #f)
((src a b . rest) ((src . args)
(with-lexicals src (b) (bind-lexicals
(make-conditional src (make-primcall src prim (list a b)) src args
(make-primcall src prim (cons b rest)) (lambda (args)
(make-const src #f)))) (match args
(else #f))) ((a . args)
(let lp ((args args))
(match args
((b)
(make-primcall src prim (list a b)))
((b . args)
(make-conditional src (make-primcall src prim (list a b))
(lp args)
(make-const src #f))))))))))))
(define-primitive-expander! 'eq? (expand-eq 'eq?)) (define-primitive-expander! 'eq? (expand-eq 'eq?))
(define-primitive-expander! 'eqv? (expand-eq 'eqv?)) (define-primitive-expander! 'eqv? (expand-eq 'eqv?))
@ -594,11 +609,18 @@
(make-primcall src prim (list a (make-const src 0))) (make-primcall src prim (list a (make-const src 0)))
(make-const src #t))) (make-const src #t)))
((src a b) #f) ((src a b) #f)
((src a b . rest) ((src . args)
(with-lexicals src (b) (bind-lexicals
(make-conditional src (make-primcall src prim (list a b)) src args
(make-primcall src prim (cons b rest)) (lambda (args)
(make-const src #f)))) (let lp ((args args))
(match args
((a b)
(make-primcall src prim (list a b)))
((a b . args)
(make-conditional src (make-primcall src prim (list a b))
(lp (cons b args))
(make-const src #f))))))))
(else #f))) (else #f)))
(for-each (lambda (prim) (for-each (lambda (prim)

View file

@ -401,6 +401,17 @@
(pass-if-equal "foo bar" 'qux (test-proc 'foo 'bar)) (pass-if-equal "foo bar" 'qux (test-proc 'foo 'bar))
(pass-if-equal "foo two" 'foo (test-proc 'foo 'two))) (pass-if-equal "foo two" 'foo (test-proc 'foo 'two)))
(with-test-prefix "size effects in multi-arg eq / <"
(pass-if-equal "eq?" 42
(compile '(catch 'foo
(lambda () (= 0 1 (throw 'foo)))
(lambda (k) 42))))
(pass-if-equal "<" 42
(compile '(catch 'foo
(lambda () (< 0 -1 (throw 'foo)))
(lambda (k) 42)))))
(with-test-prefix "read-and-compile tree-il" (with-test-prefix "read-and-compile tree-il"
(let ((code (let ((code
"\ "\