~ chicken-core (chicken-5) 69776d0cceab5bf39ccdad51fc21089676b522bc
commit 69776d0cceab5bf39ccdad51fc21089676b522bc Author: felix <felix@call-with-current-continuation.org> AuthorDate: Mon May 16 11:09:18 2011 +0200 Commit: felix <felix@call-with-current-continuation.org> CommitDate: Mon May 16 11:09:18 2011 +0200 FA-fixes for noreturn and result-count checks in conditionals diff --git a/chicken-install.scm b/chicken-install.scm index ba6ec1c9..3988ee3b 100644 --- a/chicken-install.scm +++ b/chicken-install.scm @@ -275,8 +275,6 @@ (shellpath (make-pathname *program-path* C_CSI_PROGRAM))) (define (try-extension name version trans locn) - ;;XXX this gives a warning in the scrutinizer (different number - ;; of results) (condition-case (retrieve-extension name trans locn diff --git a/scrutinizer.scm b/scrutinizer.scm index 2ee0d94c..169e530d 100755 --- a/scrutinizer.scm +++ b/scrutinizer.scm @@ -86,7 +86,7 @@ (define-constant +fragment-max-length+ 5) -(define-constant +fragment-max-depth+ 3) +(define-constant +fragment-max-depth+ 4) (define specialization-statistics '()) @@ -268,6 +268,7 @@ (cond ((and (pair? t) (eq? 'or (car t))) (cdr t)) ((eq? t 'undefined) (return 'undefined)) + ((eq? t 'noreturn) '()) (else (list t))))) (cdr t))) (ts2 (let loop ((ts ts) (done '())) @@ -324,6 +325,8 @@ (cond ((null? ts1) ts2) ((null? ts2) ts1) ((or (atom? ts1) (atom? ts2)) '*) + ((eq? 'noreturn (car ts1)) ts2) + ((eq? 'noreturn (car ts2)) ts1) (else (cons (simplify `(or ,(car ts1) ,(car ts2))) (merge-result-types (cdr ts1) (cdr ts2)))))) @@ -509,8 +512,6 @@ (variable-mark pn '##compiler#predicate)) => (lambda (pt) (cond ((match-specialization (list pt) (cdr args) #t) - ;;XXX incorrect: (or ... T ...) will return #t - ;; but arg(s) must match pt exactly (report loc (sprintf @@ -600,35 +601,46 @@ (let* ((tags (cons (tag) (tag))) (rt (single "in conditional" (walk (first subs) e loc #f #f flow tags) loc)) (c (second subs)) - (a (third subs))) + (a (third subs)) + (nor0 noreturn)) (always-true rt loc n) - (fluid-let ((noreturn #f)) - (let* ((r1 (walk c e loc dest tail (cons (car tags) flow) #f)) - (nor1 noreturn)) - (set! noreturn #f) - (let ((r2 (walk a e loc dest tail (cons (cdr tags) flow) #f))) - ;; when only one branch is noreturn, add blist entries for - ;; all in other branch: - (unless (eq? nor1 noreturn) - (let ((yestag (if nor1 (cdr tags) (car tags)))) - (for-each - (lambda (ble) - (when (eq? (cdar ble) yestag) - (d "adding blist entry ~a for returning conditional branch" - ble) - (add-to-blist (caar ble) (car flow) (cdr ble)))) - blist))) - (cond ((and (not (eq? '* r1)) (not (eq? '* r2))) - (when (and (not nor1) (not noreturn) - (not (= (length r1) (length r2)))) - (report - loc - (sprintf - "branches in conditional expression differ in the number of results:~%~%~a" - (pp-fragment n)))) - (map (lambda (t1 t2) (simplify `(or ,t1 ,t2))) - r1 r2)) - (else '*))))))) + (set! noreturn #f) + (let* ((r1 (walk c e loc dest tail (cons (car tags) flow) #f)) + (nor1 noreturn)) + (set! noreturn #f) + (let* ((r2 (walk a e loc dest tail (cons (cdr tags) flow) #f)) + (nor2 noreturn)) + (set! noreturn + (if nor1 + (if nor2 + (if nor0 #t 'some) + 'some) + (if nor2 + 'some + nor0))) + ;; when only one branch is noreturn, add blist entries for + ;; all in other branch: + (when (or (and (eq? #t nor1) (not nor2)) + (and (eq? #t nor2) (not nor1))) + (let ((yestag (if nor1 (cdr tags) (car tags)))) + (for-each + (lambda (ble) + (when (eq? (cdar ble) yestag) + (d "adding blist entry ~a for single returning conditional branch" + ble) + (add-to-blist (caar ble) (car flow) (cdr ble)))) + blist))) + (cond ((and (not (eq? '* r1)) (not (eq? '* r2))) + (when (and (not nor1) (not nor2) + (not (= (length r1) (length r2)))) + (report + loc + (sprintf + "branches in conditional expression differ in the number of results:~%~%~a" + (pp-fragment n)))) + (map (lambda (t1 t2) (simplify `(or ,t1 ,t2))) + r1 r2)) + (else '*)))))) ((let) ;; before CPS-conversion, `let'-nodes may have multiple bindings (let loop ((vars params) (body subs) (e2 '())) @@ -989,7 +1001,7 @@ ((eq? st 'number) (match '(or fixnum float) t)) ((pair? t) (case (car t) - ((or) (and (not exact) (any (cut match st <>) (cdr t)))) + ((or) ((if exact every any) (cut match st <>) (cdr t))) ((and) (every (cut match st <>) (cdr t))) ((procedure) (match st 'procedure)) ;; (not ...) should not occur diff --git a/tests/scrutiny-tests.scm b/tests/scrutiny-tests.scm index 4363b701..c4fd9ea8 100644 --- a/tests/scrutiny-tests.scm +++ b/tests/scrutiny-tests.scm @@ -38,6 +38,13 @@ (values 42 43) (fail))) +; same case, but nested +(define (test-values2 x y) + (define (fail) (error "failed")) + (if x + (values 42 43) + (if y (values 99 100) (fail)))) + (define (foo) (define (bar) (if foo 1)) ; should not warn (local) (for-each void '(1 2 3)) ; should not warn (self-call) @@ -73,4 +80,3 @@ (let ((y x)) (string-append x "abc") (+ x 3))) ;XXX (+ y 3) does not work yet -Trap