allow internal definitions in when',
unless', cond,
case', `match'
This commit is contained in:
parent
5e162d94e2
commit
99df8e1267
|
@ -58,7 +58,7 @@
|
|||
(let ([mk (lambda (unm rhs)
|
||||
(make-Row (for/list ([p (syntax->list pats)])
|
||||
(parse/cert p cert))
|
||||
#`(begin . #,rhs) unm null))])
|
||||
#`(let-values () . #,rhs) unm null))])
|
||||
(syntax-case* rhs (=>)
|
||||
(lambda (x y) (eq? (syntax-e x) (syntax-e y)))
|
||||
[((=> unm) . rhs) (mk #'unm #'rhs)]
|
||||
|
|
|
@ -67,18 +67,14 @@
|
|||
(serror
|
||||
"missing expressions in `else' clause"
|
||||
line)
|
||||
(if first?
|
||||
;; first => be careful not to introduce a splicable begin...
|
||||
`(,(quote-syntax if) #t ,(cons (quote-syntax begin) value) (void))
|
||||
;; we're in an `if' branch already...
|
||||
(cons (quote-syntax begin) value)))
|
||||
(list* (quote-syntax let-values) (quote-syntax ()) value))
|
||||
(if (stx-null? value)
|
||||
(let ([gen (gen-temp-id 'c)])
|
||||
`(,(quote-syntax let-values) ([(,gen) ,test])
|
||||
(,(quote-syntax if) ,gen ,gen ,(loop rest #f))))
|
||||
(list
|
||||
(quote-syntax if) test
|
||||
(cons (quote-syntax begin) value)
|
||||
(list* (quote-syntax let-values) (quote-syntax ()) value)
|
||||
(loop rest #f))))))))))))
|
||||
in-form)))])
|
||||
(values
|
||||
|
|
|
@ -41,7 +41,8 @@
|
|||
(list (quote-syntax if)
|
||||
(stx-car (stx-cdr x))
|
||||
(list*
|
||||
(quote-syntax begin)
|
||||
(quote-syntax let-values)
|
||||
(quote-syntax ())
|
||||
(stx-cdr (stx-cdr x)))
|
||||
(quote-syntax (void)))
|
||||
x)
|
||||
|
@ -61,7 +62,8 @@
|
|||
(cadr l)
|
||||
(quote-syntax (void))
|
||||
(list*
|
||||
(quote-syntax begin)
|
||||
(quote-syntax let-values)
|
||||
(quote-syntax ())
|
||||
(cddr l)))
|
||||
x)
|
||||
(raise-syntax-error
|
||||
|
|
|
@ -27,13 +27,13 @@
|
|||
((_ v)
|
||||
(syntax (#%expression (begin v (void)))))
|
||||
((_ v (else e1 e2 ...))
|
||||
(syntax/loc x (#%expression (begin v e1 e2 ...))))
|
||||
(syntax/loc x (#%expression (begin v (let-values () e1 e2 ...)))))
|
||||
((_ v ((k ...) e1 e2 ...))
|
||||
(syntax/loc x (if (case-test v (k ...)) (begin e1 e2 ...) (void))))
|
||||
(syntax/loc x (if (case-test v (k ...)) (let-values () e1 e2 ...) (void))))
|
||||
((self v ((k ...) e1 e2 ...) c1 c2 ...)
|
||||
(syntax/loc x (let ((x v))
|
||||
(if (case-test x (k ...))
|
||||
(begin e1 e2 ...)
|
||||
(let-values () e1 e2 ...)
|
||||
(self x c1 c2 ...)))))
|
||||
((_ v (bad e1 e2 ...) . rest)
|
||||
(raise-syntax-error
|
||||
|
@ -74,20 +74,11 @@
|
|||
orig-x))))
|
||||
(syntax->list (syntax (var ...)))
|
||||
(syntax->list (syntax (step ...))))))
|
||||
(syntax-case (syntax (e1 ...)) ()
|
||||
(() (syntax/loc
|
||||
orig-x
|
||||
(let doloop ((var init) ...)
|
||||
(if e0
|
||||
(void)
|
||||
(begin c ... (doloop step ...))))))
|
||||
((e1 e2 ...)
|
||||
(syntax/loc
|
||||
orig-x
|
||||
(let doloop ((var init) ...)
|
||||
(if e0
|
||||
(begin e1 e2 ...)
|
||||
(begin c ... (doloop step ...))))))))))))
|
||||
(syntax/loc orig-x
|
||||
(let doloop ((var init) ...)
|
||||
(if e0
|
||||
(begin (void) e1 ...)
|
||||
(begin c ... (doloop step ...))))))))))
|
||||
|
||||
(define-syntax parameterize
|
||||
(lambda (stx)
|
||||
|
|
|
@ -339,7 +339,7 @@ parallel iterations.}
|
|||
|
||||
@defform/subs[(do ([id init-expr step-expr-maybe] ...)
|
||||
(stop?-expr finish-expr ...)
|
||||
expr ...+)
|
||||
expr ...)
|
||||
([step-expr-maybe code:blank
|
||||
step-expr])]{
|
||||
|
||||
|
|
|
@ -17,12 +17,12 @@ on regular-expression matching on strings, bytes, and streams.
|
|||
@note-lib[racket/match #:use-sources (racket/match)]
|
||||
|
||||
@defform/subs[(match val-expr clause ...)
|
||||
([clause [pat expr ...+]
|
||||
[pat (=> id) expr ...+]])]{
|
||||
([clause [pat body ...+]
|
||||
[pat (=> id) body ...+]])]{
|
||||
|
||||
Finds the first @racket[pat] that matches the result of
|
||||
@racket[val-expr], and evaluates the corresponding @racket[expr]s with
|
||||
bindings introduced by @racket[pat] (if any). The last @racket[expr]
|
||||
@racket[val-expr], and evaluates the corresponding @racket[body]s with
|
||||
bindings introduced by @racket[pat] (if any). The last @racket[body]
|
||||
in the matching clause is evaluated in tail position with respect to
|
||||
the @racket[match] expression.
|
||||
|
||||
|
@ -30,10 +30,10 @@ The @racket[clause]s are tried in order to find a match. If no
|
|||
@racket[clause] matches, then the @exnraise[exn:misc:match?].
|
||||
|
||||
An optional @racket[(=> id)] between a @racket[pat] and the
|
||||
@racket[expr]s is bound to a @defterm{failure procedure} of zero
|
||||
@racket[body]s is bound to a @defterm{failure procedure} of zero
|
||||
arguments. If this procedure is invoked, it escapes back to the
|
||||
pattern matching expression, and resumes the matching process as if
|
||||
the pattern had failed to match. The @racket[expr]s must not mutate
|
||||
the pattern had failed to match. The @racket[body]s must not mutate
|
||||
the object being matched before calling the failure procedure,
|
||||
otherwise the behavior of matching is unpredictable.
|
||||
|
||||
|
@ -358,8 +358,8 @@ In more detail, patterns match as follows:
|
|||
@section{Additional Matching Forms}
|
||||
|
||||
@defform/subs[(match* (val-expr ...+) clause* ...)
|
||||
([clause* [(pat ...+) expr ...+]
|
||||
[(pat ...+) (=> id) expr ...+]])]{
|
||||
([clause* [(pat ...+) body ...+]
|
||||
[(pat ...+) (=> id) body ...+]])]{
|
||||
Matches a sequence of values against each clause in order, matching
|
||||
only when all patterns in a clause match. Each clause must have the
|
||||
same number of patterns as the number of @racket[val-expr]s.
|
||||
|
|
|
@ -1738,8 +1738,8 @@ position with respect to the @racket[if] form.
|
|||
|
||||
@defform/subs[#:literals (else =>)
|
||||
(cond cond-clause ...)
|
||||
([cond-clause [test-expr then-expr ...+]
|
||||
[else then-expr ...+]
|
||||
([cond-clause [test-expr then-body ...+]
|
||||
[else then-body ...+]
|
||||
[test-expr => proc-expr]
|
||||
[test-expr]])]{
|
||||
|
||||
|
@ -1750,10 +1750,10 @@ A @racket[cond-clause] that starts with @racket[else] must be the last
|
|||
|
||||
If no @racket[cond-clause]s are present, the result is @|void-const|.
|
||||
|
||||
If only a @racket[[else then-expr ...+]] is present, then the
|
||||
@racket[then-expr]s are evaluated. The results from all but the last
|
||||
@racket[then-expr] are ignored. The results of the last
|
||||
@racket[then-expr], which is in tail position with respect to the
|
||||
If only a @racket[[else then-body ...+]] is present, then the
|
||||
@racket[then-body]s are evaluated. The results from all but the last
|
||||
@racket[then-body] are ignored. The results of the last
|
||||
@racket[then-body], which is in tail position with respect to the
|
||||
@racket[cond] form, are the results for the whole @racket[cond]
|
||||
form.
|
||||
|
||||
|
@ -1763,10 +1763,10 @@ the remaining @racket[cond-clause]s, in tail position with respect to
|
|||
the original @racket[cond] form. Otherwise, evaluation depends on the
|
||||
form of the @racket[cond-clause]:
|
||||
|
||||
@specsubform[[test-expr then-expr ...+]]{The @racket[then-expr]s are
|
||||
@specsubform[[test-expr then-body ...+]]{The @racket[then-body]s are
|
||||
evaluated in order, and the results from all but the last
|
||||
@racket[then-expr] are ignored. The results of the last
|
||||
@racket[then-expr], which is in tail position with respect to the
|
||||
@racket[then-body] are ignored. The results of the last
|
||||
@racket[then-body], which is in tail position with respect to the
|
||||
@racket[cond] form, provides the result for the whole @racket[cond]
|
||||
form.}
|
||||
|
||||
|
@ -1860,8 +1860,8 @@ position with respect to the original @racket[or] form.
|
|||
|
||||
@defform/subs[#:literals (else)
|
||||
(case val-expr case-clause ...)
|
||||
([case-clause [(datum ...) then-expr ...+]
|
||||
[else then-expr ...+]])]{
|
||||
([case-clause [(datum ...) then-body ...+]
|
||||
[else then-body ...+]])]{
|
||||
|
||||
Evaluates @racket[val-expr] and uses the result to select a
|
||||
@racket[case-clause]. The selected clause is the first one with a
|
||||
|
@ -1872,7 +1872,7 @@ result of @racket[val-expr]. If no such @racket[datum] is present, the
|
|||
@racket[case] form is @|void-const|.
|
||||
|
||||
For the selected @racket[case-clause], the results of the last
|
||||
@racket[then-expr], which is in tail position with respect to the
|
||||
@racket[then-body], which is in tail position with respect to the
|
||||
@racket[case] form, are the results for the whole @racket[case] form.
|
||||
|
||||
A @racket[case-clause] that starts with @racket[else] must be the last
|
||||
|
@ -2202,12 +2202,12 @@ classifications:
|
|||
|
||||
@guideintro["when+unless"]{@racket[when] and @racket[unless]}
|
||||
|
||||
@defform[(when test-expr expr ...)]{
|
||||
@defform[(when test-expr body ...+)]{
|
||||
|
||||
Evaluates @racket[test-expr]. If the result is @racket[#f], then
|
||||
the result of the @racket[when] expression is
|
||||
@|void-const|. Otherwise, the @racket[expr]s are evaluated, and the
|
||||
last @racket[expr] is in tail position with respect to the
|
||||
@|void-const|. Otherwise, the @racket[body]s are evaluated, and the
|
||||
last @racket[body] is in tail position with respect to the
|
||||
@racket[when] form.
|
||||
|
||||
@mz-examples[
|
||||
|
@ -2218,9 +2218,9 @@ last @racket[expr] is in tail position with respect to the
|
|||
(display " there"))
|
||||
]}
|
||||
|
||||
@defform[(unless test-expr expr ...)]{
|
||||
@defform[(unless test-expr body ...+)]{
|
||||
|
||||
Equivalent to @racket[(when (not test-expr) expr ...)].
|
||||
Equivalent to @racket[(when (not test-expr) body ...+)].
|
||||
|
||||
@mz-examples[
|
||||
(unless (positive? 5)
|
||||
|
|
|
@ -526,12 +526,12 @@
|
|||
(with-handlers () ,@body)))
|
||||
(teval `(test ,val 'with-handlers-begin
|
||||
(with-handlers ([void void]) ,@body)))
|
||||
(syntax-test (datum->syntax #f `(when (positive? 1) ,@body) #f))
|
||||
(syntax-test (datum->syntax #f `(unless (positive? -1) ,@body) #f))
|
||||
(syntax-test (datum->syntax #f `(cond [(positive? 1) ,@body][else #f]) #f))
|
||||
(syntax-test (datum->syntax #f `(cond [(positive? -1) 0][else ,@body]) #f))
|
||||
(syntax-test (datum->syntax #f `(case (positive? 1) [(#t) ,@body][else -12]) #f))
|
||||
(syntax-test (datum->syntax #f `(cond [#t ,@body]) #f))
|
||||
(teval `(test ,val 'when-begin (when (positive? 1) ,@body)))
|
||||
(teval `(test ,val 'unless-begin (unless (positive? -1) ,@body)))
|
||||
(teval `(test ,val 'cons-begin (cond [(positive? 1) ,@body][else #f])))
|
||||
(teval `(test ,val 'cons-else-begin (cond [(positive? -1) 0][else ,@body])))
|
||||
(teval `(test ,val 'case-begin (case (positive? 1) [(#t) ,@body][else -12])))
|
||||
(teval `(test ,val 'cond-only-begin (cond [#t ,@body])))
|
||||
(syntax-test (datum->syntax #f `(do ((x 1)) (#t ,@body) ,@body) #f))
|
||||
(syntax-test (datum->syntax #f `(begin0 12 ,@body) #f)))])
|
||||
(wrap 5 '((begin (define x 5)) x))
|
||||
|
@ -791,7 +791,6 @@
|
|||
(syntax-test #'(lambda () (void (define x 2)) 1))
|
||||
(syntax-test #'(cond [(< 2 3) (define x 2)] [else 5]))
|
||||
(syntax-test #'(cond [else (define x 2)]))
|
||||
(syntax-test #'(cond [else (define x 2) 0]))
|
||||
|
||||
;; No good way to test in mzc:
|
||||
(error-test #'(define x (values)) exn:application:arity?)
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
Version 5.0.1.8
|
||||
Changed body of `when', `unless', `cond' clauses, `case'
|
||||
clauses, and `match' clauses to be internal-definition contexts
|
||||
Added #true and #false, and changed #t/#T and #f/#F to
|
||||
require a delimiter afterward
|
||||
Added print-boolean-long-form
|
||||
|
|
Loading…
Reference in New Issue
Block a user