diff --git a/typed-racket-doc/typed-racket/scribblings/reference/special-forms.scrbl b/typed-racket-doc/typed-racket/scribblings/reference/special-forms.scrbl index 27129151d..af51fd16d 100644 --- a/typed-racket-doc/typed-racket/scribblings/reference/special-forms.scrbl +++ b/typed-racket-doc/typed-racket/scribblings/reference/special-forms.scrbl @@ -225,9 +225,15 @@ To see how to declare a type for @racket[add-map], see the [for-clause [id : t seq-expr] [(binding ...) seq-expr] [id seq-expr] - @code:line[#:when guard]] + @code:line[#:when guard] + @code:line[#:unless guard] + @code:line[#:do [do-body ...]] + break-clause + @code:line[#:splice (splicing-id . form)]] [binding id - [id : t]])]{ + [id : t]] + [break-clause @code:line[#:break guard] + @code:line[#:final guard]])]{ Like @|for-id| from @racketmodname[racket/base], but each @racket[id] has the associated type @racket[t]. The latter @racket[_ann-maybe] will be used first, and then the previous one. Since the return type is always @racket[Void], diff --git a/typed-racket-lib/typed-racket/base-env/for-clauses.rkt b/typed-racket-lib/typed-racket/base-env/for-clauses.rkt index 70ca31276..b7160090e 100644 --- a/typed-racket-lib/typed-racket/base-env/for-clauses.rkt +++ b/typed-racket-lib/typed-racket/base-env/for-clauses.rkt @@ -25,8 +25,8 @@ #:with (expand* ...) (list (quasisyntax/loc #'c ((v.ann-name ...) seq-expr.e)) #'#:when #''#t)) - (pattern (~seq (~and kw (~or #:when #:unless #:break #:final)) guard:expr) - #:with (expand ...) (list #'kw #'guard) + (pattern (~seq (~and kw (~or #:when #:unless #:break #:final #:do #:splice)) expr:expr) + #:with (expand ...) (list #'kw #'expr) #:with (expand* ...) #'(expand ...))) (define-syntax-class for-clauses diff --git a/typed-racket-lib/typed-racket/base-env/prims.rkt b/typed-racket-lib/typed-racket/base-env/prims.rkt index 2a26ad6c4..e039520e6 100644 --- a/typed-racket-lib/typed-racket/base-env/prims.rkt +++ b/typed-racket-lib/typed-racket/base-env/prims.rkt @@ -308,16 +308,29 @@ the typed racket language. (pattern (~seq (~and kw (~or #:break #:final)) guard-expr:expr) #:with (expand ...) #'(kw guard-expr))) (define-syntax-class for-kw + (pattern #:when) + (pattern #:unless) + (pattern #:do) + (pattern #:splice)) + (define-syntax-class for-when (pattern #:when #:with replace-with #'when) (pattern #:unless #:with replace-with #'unless)) (syntax-parse clauses - [(head:for-clause next:for-clause ... kw:for-kw guard b:break-clause ... rest ...) + [(when:for-when guard) ; we end on a keyword clause + (quasisyntax/loc stx + (when.replace-with guard + #,@body))] + [(when:for-when guard rest ...) + (quasisyntax/loc stx + (when.replace-with guard + #,(loop #'(rest ...))))] + [(head:for-clause ... kw:for-kw expr b:break-clause ... rest ...) (add-ann (quasisyntax/loc stx (for - (head.expand ... next.expand ... ... kw guard b.expand ... ...) + (head.expand ... ... kw expr b.expand ... ...) #,(loop #'(rest ...)))) #'Void)] [(head:for-clause ...) ; we reached the end @@ -326,15 +339,7 @@ the typed racket language. (for (head.expand ... ...) #,@body)) - #'Void)] - [(kw:for-kw guard) ; we end on a keyword clause - (quasisyntax/loc stx - (kw.replace-with guard - #,@body))] - [(kw:for-kw guard rest ...) - (quasisyntax/loc stx - (kw.replace-with guard - #,(loop #'(rest ...))))])))])) + #'Void)])))])) (begin-for-syntax (define-splicing-syntax-class optional-standalone-annotation* diff --git a/typed-racket-test/succeed/for.rkt b/typed-racket-test/succeed/for.rkt index 45decacc2..f6e819a8c 100644 --- a/typed-racket-test/succeed/for.rkt +++ b/typed-racket-test/succeed/for.rkt @@ -1,5 +1,7 @@ #lang typed/scheme +(require (for-syntax racket/base)) + (: 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) @@ -50,6 +52,35 @@ (display (list i j k))))) "(1 a #t)(1 a #t)(3 c #t)(3 c #t)") +(check string=? + (with-output-to-string + (lambda () + (for: : Void (#:do [(display #"0123456789")]) + (void)))) + "0123456789") +(check string=? + (with-output-to-string + (lambda () + (for: : Void + ([i '(1 2 3)] + #:do [(define neg-i (- i))] + [j (in-list (list neg-i 0 i))]) + (display j)))) + "-101-202-303") + +(check string=? + (with-output-to-string + (lambda () + (define-splicing-for-clause-syntax cross3 + (lambda (stx) + (syntax-case stx () + [(_ n m) #'([n (in-range 3)] + #:when #t + [m (in-range 3)])]))) + (for: : Void (#:splice (cross3 m n)) + (display (+ m n))))) + "012123234") + (check equal? (for/list: : (Listof Integer) ([i : Integer (in-range 10)]) i) '(0 1 2 3 4 5 6 7 8 9))