~ chicken-core (chicken-5) cfe84ac3fbf1f6143ea32db6405770b2084462cd
commit cfe84ac3fbf1f6143ea32db6405770b2084462cd Author: felix <felix@call-with-current-continuation.org> AuthorDate: Fri May 13 09:18:02 2011 +0200 Commit: felix <felix@call-with-current-continuation.org> CommitDate: Fri May 13 09:18:02 2011 +0200 special-handling of noreturn results in conditional branches; reversed diffing order for scrutiny test diff --git a/scrutinizer.scm b/scrutinizer.scm index 61fc0e1a..8c7116f7 100755 --- a/scrutinizer.scm +++ b/scrutinizer.scm @@ -94,6 +94,7 @@ (define (scrutinize node db complain specialize) (let ((blist '()) (aliased '()) + (noreturn #f) (safe-calls 0)) (define (constant-result lit) @@ -496,6 +497,14 @@ (sprintf "~aexpected argument #~a of type `~a', but was given an argument of type `~a'" (pname) i (car atypes) (car args))))) + (when (and (pair? ptype) ;XXX move this into helper procedure + (eq? 'procedure (car ptype)) + (list? ptype) + (eq? 'noreturn + (if (symbol? (second ptype)) + (fourth ptype) + (third ptype)))) + (set! noreturn #t)) (let ((r (procedure-result-types ptype values-rest (cdr args)))) ;;XXX we should check whether this is a standard- or extended binding (let* ((pn (procedure-name ptype)) @@ -596,20 +605,33 @@ (c (second subs)) (a (third subs))) (always-true rt loc n) - (let ((r1 (walk c e loc dest tail (cons (car tags) flow) #f)) - (r2 (walk a e loc dest tail (cons (cdr tags) flow) #f))) - (cond ((and (not (eq? '* r1)) (not (eq? '* r2))) - (when (and (not (any noreturn-type? r1)) - (not (any noreturn-type? r2)) - (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 '*))))) + (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 '*))))))) ((let) ;; before CPS-conversion, `let'-nodes may have multiple bindings (let loop ((vars params) (body subs) (e2 '())) diff --git a/tests/runtests.sh b/tests/runtests.sh index 901164d7..d62ef769 100644 --- a/tests/runtests.sh +++ b/tests/runtests.sh @@ -77,7 +77,7 @@ if test \! -f scrutiny.expected; then cp scrutiny.out scrutiny.expected fi -diff -bu scrutiny.out scrutiny.expected +diff -bu scrutiny.expected scrutiny.out $compile scrutiny-tests-2.scm -scrutinize -analyze-only -ignore-repository -types ../types.db ./a.outTrap