; ; test.scm - simple test suite ; Total Procedures in Scheme, May 2006, Chris Pressey ; For license information, see the file LICENSE in this directory. ; (load "std.scm") (load "boot1.scm") (load "util.scm") (load "env.scm") (load "canon.scm") (load "crit.scm") (load "total.scm") ; ; Definitions (as S-expressions) of procedures that we will test. ; (define simple-proc '(lambda (a b) (if (> a b) (* 2 a) (* 3 b))) ) (define unsafe-fac-proc '(lambda (n) (cond ((zero? n) 1) (else (* n (fac (- n 1)))))) ) (define fac-proc '(lambda (n) (if (>= n 0) (cond ((zero? n) 1) (else (* n (fac (- n 1))))) 0)) ) (define unsafe-anbncn-proc '(lambda (l k) (cond ((null? l) (eq? k 0)) ((eq? (car l) 'a) (anbncn (cdr l) (+ k 1))) ((eq? (car l) 'b) (anbncn (cdr l) (+ k 1))) ((eq? (car l) 'c) (anbncn (cdr l) (- k 2))) (else (anbncn (cdr l) k)))) ) (define anbncn-proc '(lambda (l k) (if (acyclic? l) (cond ((null? l) (eq? k 0)) ((eq? (car l) 'a) (anbncn (cdr l) (+ k 1))) ((eq? (car l) 'b) (anbncn (cdr l) (+ k 1))) ((eq? (car l) 'c) (anbncn (cdr l) (- k 2))) (else (anbncn (cdr l) k))))) ) (define ack-proc '(lambda (x y) (if (and (>= x 0) (>= y 0)) (cond ((zero? x) (+ y 1)) ((zero? y) (ack (- x 1) 1)) (else (ack (- x 1) (ack x (- y 1))))))) ) (define ever1-proc '(lambda (x) (cond ((eq? x 10000) x) (else (ever1 (+ x 1))))) ) ; ; The tests proper. ; ;; Tests for acyclicity. (test acyclic-1 (acyclic? '(1 2 3 4 5)) #t ) (test acyclic-2 (acyclic? '(1 2 (a b c) 3 4 5)) #t ) (test acyclic-3 (let* ((tail '(5 . TBA)) (lst (append '(1 2 3 4) tail))) (set-cdr! tail lst) (acyclic? lst)) #f ) (test acyclic-4 (let* ((tail '(5 . TBA)) (inner-lst (append '(1 2 3 4) tail)) (outer-lst (list 'a 'b inner-lst 'c 'd))) (set-cdr! tail inner-lst) (acyclic? outer-lst)) #f ) ;; Tests for canonicalization. (test canonicalize-simple (canonicalize simple-proc '()) '(lambda (a b) (if (> a b) (* 2 a) (* 3 b))) ) (test canonicalize-fac (canonicalize fac-proc '()) '(lambda (n) (if (>= n 0) (if (zero? n) 1 (let ((z (let ((z (- n 1))) (fac z)) )) (* n z))) 0)) ) (test canonicalize-ack (canonicalize ack-proc '()) '(lambda (x y) (if (let ((z (>= x 0)) (zz (>= y 0))) (and z zz)) (if (zero? x) (+ y 1) (if (zero? y) (let ((z (- x 1))) (ack z 1)) (let ((z (- x 1)) (zz (let ((zz (- y 1))) (ack x zz)))) (ack z zz)))) 'undefined)) ) (test canonicalize-let* (canonicalize '(lambda (x y) (let* ((p (+ x y)) (q (* p p))) (display q))) '()) '(lambda (x y) (let ((p (+ x y))) (let ((q (* p p))) (display q)))) ) ;; Tests for finding critical arguments. (test crit-args-simple (find-crit (canonicalize simple-proc '()) '(simple)) '() ) (test crit-args-fac (find-crit (canonicalize fac-proc '()) '(fac)) '((n . crit-nat)) ) (test crit-args-unsafe-fac (find-crit (canonicalize unsafe-fac-proc '()) '(fac)) '() ) (test crit-args-anbncn (find-crit (canonicalize anbncn-proc '()) '(anbncn)) '((l . crit-list)) ) (test crit-args-ack (find-crit (canonicalize ack-proc '()) '(ack)) '() ) (test crit-args-ever1 (find-crit (canonicalize ever1-proc '()) '(ever1)) '() ) ;; Tests for determining totality. (test proc-total-simple (proc-total? 'simple (canonicalize simple-proc '()) known-total-env) #t ) (test proc-total-fac (proc-total? 'fac (canonicalize fac-proc '()) known-total-env) #t ) (test proc-total-unsafe-fac (proc-total? 'fac (canonicalize unsafe-fac-proc '()) known-total-env) #f ) (test proc-total-anbncn (proc-total? 'anbncn (canonicalize anbncn-proc '()) known-total-env) #t ) (test proc-total-ack (proc-total? 'ack (canonicalize ack-proc '()) known-total-env) #f ) (test proc-total-ever1 (proc-total? 'ever1 (canonicalize ever1-proc '()) known-total-env) #f ) ;; Tests for determining totality of mutually-recursive procedures. (test mutrec-total-even (procs-total? '(even odd) (list (canonicalize '(lambda (x) (if (>= x 0) (cond ((zero? x) 1) (else (odd (- x 1)))))) '()) (canonicalize '(lambda (x) (if (>= x 0) (cond ((zero? x) 0) (else (odd (- x 1)))))) '())) known-total-env) #t ) (test mutrec-total-bad (procs-total? '(foo bar) (list (canonicalize '(lambda (x y) (if (acyclic? x) (cond ((null? x) (bar '(1 2 3 4 5) y)) (else (foo (cdr x) (+ y 1)))))) '()) (canonicalize '(lambda (x y) (if (acyclic? x) (cond ((null? x) (foo '(1 2 3 4 5) y)) (else (bar (cdr x) (+ y 1)))))) '())) known-total-env) #f )