Skip to content

Commit dc81ca0

Browse files
committed
[for] Support #:do and #:splice
1 parent 317226c commit dc81ca0

File tree

4 files changed

+57
-15
lines changed

4 files changed

+57
-15
lines changed

typed-racket-doc/typed-racket/scribblings/reference/special-forms.scrbl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,9 +225,15 @@ To see how to declare a type for @racket[add-map], see the
225225
[for-clause [id : t seq-expr]
226226
[(binding ...) seq-expr]
227227
[id seq-expr]
228-
@code:line[#:when guard]]
228+
@code:line[#:when guard]
229+
@code:line[#:unless guard]
230+
@code:line[#:do [do-body ...]]
231+
break-clause
232+
@code:line[#:splice (splicing-id . form)]]
229233
[binding id
230-
[id : t]])]{
234+
[id : t]]
235+
[break-clause @code:line[#:break guard]
236+
@code:line[#:final guard]])]{
231237
Like @|for-id| from @racketmodname[racket/base], but each @racket[id] has the associated type
232238
@racket[t]. The latter @racket[_ann-maybe] will be used first, and then the previous one.
233239
Since the return type is always @racket[Void],

typed-racket-lib/typed-racket/base-env/for-clauses.rkt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@
2525
#:with (expand* ...) (list (quasisyntax/loc #'c
2626
((v.ann-name ...) seq-expr.e))
2727
#'#:when #''#t))
28-
(pattern (~seq (~and kw (~or #:when #:unless #:break #:final)) guard:expr)
29-
#:with (expand ...) (list #'kw #'guard)
28+
(pattern (~seq (~and kw (~or #:when #:unless #:break #:final #:do #:splice)) expr:expr)
29+
#:with (expand ...) (list #'kw #'expr)
3030
#:with (expand* ...) #'(expand ...)))
3131

3232
(define-syntax-class for-clauses

typed-racket-lib/typed-racket/base-env/prims.rkt

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -308,16 +308,29 @@ the typed racket language.
308308
(pattern (~seq (~and kw (~or #:break #:final)) guard-expr:expr)
309309
#:with (expand ...) #'(kw guard-expr)))
310310
(define-syntax-class for-kw
311+
(pattern #:when)
312+
(pattern #:unless)
313+
(pattern #:do)
314+
(pattern #:splice))
315+
(define-syntax-class for-when
311316
(pattern #:when
312317
#:with replace-with #'when)
313318
(pattern #:unless
314319
#:with replace-with #'unless))
315320
(syntax-parse clauses
316-
[(head:for-clause next:for-clause ... kw:for-kw guard b:break-clause ... rest ...)
321+
[(when:for-when guard) ; we end on a keyword clause
322+
(quasisyntax/loc stx
323+
(when.replace-with guard
324+
#,@body))]
325+
[(when:for-when guard rest ...)
326+
(quasisyntax/loc stx
327+
(when.replace-with guard
328+
#,(loop #'(rest ...))))]
329+
[(head:for-clause ... kw:for-kw expr b:break-clause ... rest ...)
317330
(add-ann
318331
(quasisyntax/loc stx
319332
(for
320-
(head.expand ... next.expand ... ... kw guard b.expand ... ...)
333+
(head.expand ... ... kw expr b.expand ... ...)
321334
#,(loop #'(rest ...))))
322335
#'Void)]
323336
[(head:for-clause ...) ; we reached the end
@@ -326,15 +339,7 @@ the typed racket language.
326339
(for
327340
(head.expand ... ...)
328341
#,@body))
329-
#'Void)]
330-
[(kw:for-kw guard) ; we end on a keyword clause
331-
(quasisyntax/loc stx
332-
(kw.replace-with guard
333-
#,@body))]
334-
[(kw:for-kw guard rest ...)
335-
(quasisyntax/loc stx
336-
(kw.replace-with guard
337-
#,(loop #'(rest ...))))])))]))
342+
#'Void)])))]))
338343

339344
(begin-for-syntax
340345
(define-splicing-syntax-class optional-standalone-annotation*

typed-racket-test/succeed/for.rkt

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#lang typed/scheme
22

3+
(require (for-syntax racket/base))
4+
35
(: check (All (a) ((a a -> Boolean) a a -> Boolean)))
46
;; Simple check function as RackUnit doesn't work in Typed Scheme (yet)
57
(define (check f a b)
@@ -50,6 +52,35 @@
5052
(display (list i j k)))))
5153
"(1 a #t)(1 a #t)(3 c #t)(3 c #t)")
5254

55+
(check string=?
56+
(with-output-to-string
57+
(lambda ()
58+
(for: : Void (#:do [(display #"0123456789")])
59+
(void))))
60+
"0123456789")
61+
(check string=?
62+
(with-output-to-string
63+
(lambda ()
64+
(for: : Void
65+
([i '(1 2 3)]
66+
#:do [(define neg-i (- i))]
67+
[j (in-list (list neg-i 0 i))])
68+
(display j))))
69+
"-101-202-303")
70+
71+
(check string=?
72+
(with-output-to-string
73+
(lambda ()
74+
(define-splicing-for-clause-syntax cross3
75+
(lambda (stx)
76+
(syntax-case stx ()
77+
[(_ n m) #'([n (in-range 3)]
78+
#:when #t
79+
[m (in-range 3)])])))
80+
(for: : Void (#:splice (cross3 m n))
81+
(display (+ m n)))))
82+
"012123234")
83+
5384
(check equal?
5485
(for/list: : (Listof Integer) ([i : Integer (in-range 10)]) i)
5586
'(0 1 2 3 4 5 6 7 8 9))

0 commit comments

Comments
 (0)