From c92ae7385976f99bb5aa3d7a0ee29950d38a3d30 Mon Sep 17 00:00:00 2001 From: Vincent St-Amour Date: Fri, 28 May 2010 13:22:48 -0400 Subject: [PATCH] Wrote tests for the for: macros. --- collects/tests/typed-scheme/succeed/for.rkt | 115 ++++++++++++++++++ .../typed-scheme/xfail/for-inference.rkt | 55 +++++++++ .../typed-scheme/xfail/for-type-precision.rkt | 37 ++++++ 3 files changed, 207 insertions(+) create mode 100644 collects/tests/typed-scheme/succeed/for.rkt create mode 100644 collects/tests/typed-scheme/xfail/for-inference.rkt create mode 100644 collects/tests/typed-scheme/xfail/for-type-precision.rkt diff --git a/collects/tests/typed-scheme/succeed/for.rkt b/collects/tests/typed-scheme/succeed/for.rkt new file mode 100644 index 0000000000..cdd22c1c0a --- /dev/null +++ b/collects/tests/typed-scheme/succeed/for.rkt @@ -0,0 +1,115 @@ +#lang typed/scheme + +(: check (All (a) ((a a -> Boolean) a a -> Boolean))) +;; Simple check function as RackUnit doesn't work in Typed Scheme (yet) +(define (check f a b) + (if (f a b) + #t + (error (format "Check (~a ~a ~a) failed" f a b)))) + +(check string=? + (with-output-to-string + (lambda () + (for: : Void ([i : Integer (in-range 10)]) + (display i)))) + "0123456789") + +(check string=? + (with-output-to-string + (lambda () + (for: : Void + ((i : Exact-Positive-Integer '(1 2 3)) + (j : Char "abc") + #:when (odd? i) + (k : True #(#t #t)) + #:when k) + (display (list i j k))))) + "(1 a #t)(1 a #t)(3 c #t)(3 c #t)") + +(check equal? + (for/list: : (Listof Integer) ([i : Integer (in-range 10)]) i) + '(0 1 2 3 4 5 6 7 8 9)) + +(check equal? + (for/list: : (Listof Integer) + ((i : Exact-Positive-Integer '(1 2 3)) + (j : Exact-Positive-Integer '(10 20 30)) + #:when (odd? i)) + (+ i j 10)) + '(21 43)) + +(check equal? + (for/or: : Boolean + ((i : Exact-Positive-Integer '(1 2 3))) + (>= i 3)) + #t) + +(check equal? + (for/or: : Boolean + ((i : Exact-Positive-Integer '(1 2 3)) + (j : Exact-Positive-Integer '(2 1 3))) + (>= i j)) + #t) + +(check equal? + (let-values: ([([x : (Listof Integer)] [y : (Listof Integer)]) + (for/lists: : (values (Listof Integer) (Listof Integer)) + ((x : (Listof Integer)) + (y : (Listof Integer))) + ((i : Exact-Positive-Integer '(1 2 3)) + #:when #t + (j : Exact-Positive-Integer '(10 20 30)) + #:when (> j 12)) + (values i j))]) + (append x y)) + '(1 1 2 2 3 3 20 30 20 30 20 30)) + +(check = + (for/fold: : Integer + ((acc : Integer 0)) + ((i : Exact-Positive-Integer '(1 2 3)) + (j : Exact-Positive-Integer '(10 20 30))) + (+ acc i j)) + 66) + +(check = + (for/fold: : Integer + ((acc : Integer 0)) + ((i : Exact-Positive-Integer '(1 2 3)) + #:when (even? i) + (j : Exact-Positive-Integer '(10 20 30)) + #:when #t + (k : Exact-Positive-Integer '(100 200 300))) + (+ acc i j k)) + 1998) + +(check string=? + (with-output-to-string + (lambda () + (for*: : Void + ((i : Exact-Positive-Integer '(1 2 3)) + (j : Exact-Positive-Integer '(10 20 30))) + (display (list i j))))) + "(1 10)(1 20)(1 30)(2 10)(2 20)(2 30)(3 10)(3 20)(3 30)") + +(check equal? + (let-values: ([([x : (Listof Integer)] [y : (Listof Integer)]) + (for*/lists: : (values (Listof Integer) (Listof Integer)) + ((x : (Listof Integer)) + (y : (Listof Integer))) + ((i : Exact-Positive-Integer '(1 2 3)) + (j : Exact-Positive-Integer '(10 20 30)) + #:when (> j 12)) + (values i j))]) + (append x y)) + '(1 1 2 2 3 3 20 30 20 30 20 30)) + +(check = + (for*/fold: : Integer + ((acc : Integer 0)) + ((i : Exact-Positive-Integer '(1 2 3)) + #:when (even? i) + (j : Exact-Positive-Integer '(10 20 30)) + (k : Exact-Positive-Integer '(100 200 300))) + (+ acc i j k)) + 1998) diff --git a/collects/tests/typed-scheme/xfail/for-inference.rkt b/collects/tests/typed-scheme/xfail/for-inference.rkt new file mode 100644 index 0000000000..e120ee010c --- /dev/null +++ b/collects/tests/typed-scheme/xfail/for-inference.rkt @@ -0,0 +1,55 @@ +#lang typed/scheme + +;; Inference fails when #:when clauses are used, except when there's +;; only one, and it's the last clause. +;; for:, for*: are unaffected, since they currently expand their +;; #:when clauses manually, unlike for/list: and co, who punt it to +;; non-annotated versions of the macros, to avoid breaking semantics. +;; for/fold:, for*/fold:, for/lists: and for*/lists: are not affected +;; either. The inferencer can handle their expansion, apparently no +;; matter how many #:when clauses we throw at them. +;; Of course, for*/list: and co won't work, since they are equivalent +;; to for/list: and co with #:when clauses. +(for/list: : (Listof Integer) + ((i : Exact-Positive-Integer '(1 2 3)) + #:when (odd? i) + (j : Exact-Positive-Integer '(10 20 30))) + (+ i j 10)) + +(for/list: : (Listof Integer) + (#:when #t + (i : Exact-Positive-Integer '(1 2 3)) + (j : Exact-Positive-Integer '(10 20 30))) + (+ i j 10)) + +(for*/list: : (Listof (Listof Integer)) + ((i : Exact-Positive-Integer '(1 2 3)) + (j : Exact-Positive-Integer '(10 20 30))) + (list i j)) + +;; The right type for the return value would be (values (Listof Integer) (Listof Integer)). +;; The problem here is with the error message. Somehow, source location information is lost and the whole module is blamed. +(for/lists: : (Listof Integer) + ((x : (Listof Integer)) + (y : (Listof Integer))) + ((i : Exact-Positive-Integer '(1 2 3)) + (j : Exact-Positive-Integer '(10 20 30))) + (values i j)) + +;; This is a legitimate use of multi-valued seq-exprs, but it causes the typechecker to throw an internal error. +(for/list: : (Listof Integer) + ((([i : Exact-Positive-Integer] + [j : Exact-Positive-Integer]) + (list (values 1 10) (values 2 20) (values 2 30))) + #:when (odd? i)) + (+ i j 10)) + +;; Types can't be inferred for the expansion of for/first: at all. +(for/first: : Integer + ((i : Exact-Positive-Integer '(1 2 3))) + i) + +;; Same for for/last: +(for/last: : (Option Integer) + ((i : Exact-Positive-Integer '(1 2 3))) + i) diff --git a/collects/tests/typed-scheme/xfail/for-type-precision.rkt b/collects/tests/typed-scheme/xfail/for-type-precision.rkt new file mode 100644 index 0000000000..187907699f --- /dev/null +++ b/collects/tests/typed-scheme/xfail/for-type-precision.rkt @@ -0,0 +1,37 @@ +#lang typed/scheme + +;; I would have to be annotated with its most precise type (Exact-Positive-Integer) for this to work +(for: : Void ((i : Integer '(1 2 3))) + (display i)) + +;; same here, would need type (U (List 'a 't) (List 'c 'g)) +(for: : Void + ([from-to : (List Symbol Symbol) + '([a t] + [c g])]) + #t) + +;; wants (U False True), which should be the same as Boolean, but apparently isn't +(for: : Void + ((k : Boolean #(#t #f)) + #:when k) + (display k)) + +;; unlike the usual cases with #:when clauses (see for-inference.rkt), inference does something, but does it wrong +(for/list: : (Listof Integer) + (#:when #t + (i : Exact-Positive-Integer '(1 2 3)) + (j : Exact-Positive-Integer '(10 20 30))) + (+ i j 10)) + +;; that same bug makes for/hash:, for/hasheq: and for/hasheqv: unusable +;; this infers Nothing for the type of the elements of the HashTable +;; since they don't work, these functions are not currently documented +(for/hash: : (HashTable Integer Char) + ((i : Exact-Positive-Integer '(1 2 3)) + (j : Char "abc")) + (values i j)) +;; same thing for for/and: +(for/and: : Boolean + ((i : Exact-Positive-Integer '(1 2 3))) + (< i 3))