Made it ok to use rest-like stuff with keywords when allowing other keywords
(either explicitly or implicitly). svn: r2676
This commit is contained in:
parent
5552630953
commit
88341ddf0e
|
@ -188,7 +188,7 @@
|
|||
'()))]
|
||||
[opts (pop-formals #:optional)]
|
||||
[keys (pop-formals #:key)])
|
||||
;; now get all rest-like vars
|
||||
;; now get all rest-like vars and modes
|
||||
(let loop ([formals formals] [rests '()] [modes '()])
|
||||
(if (null? formals)
|
||||
(apply process-vars vars opts keys rests modes only-vars?)
|
||||
|
@ -197,12 +197,16 @@
|
|||
(cond [(memq k '(#:optional #:key))
|
||||
(serror k-stx "misplaced ~a" k)]
|
||||
[(memq k mode-keywords)
|
||||
(cond [(null? keys)
|
||||
(serror k-stx "cannot use without #:key arguments")]
|
||||
[(pair? (cdar formals))
|
||||
(serror (cadar formals)
|
||||
"identifier following mode keyword ~a" k)]
|
||||
[else (loop (cdr formals) rests (cons k modes))])]
|
||||
(cond
|
||||
#; ;(*)
|
||||
;; don't throw an error here, it still fine if used with
|
||||
;; #:allow-other-keys (explicit or implicit), also below
|
||||
[(null? keys)
|
||||
(serror k-stx "cannot use without #:key arguments")]
|
||||
[(pair? (cdar formals))
|
||||
(serror (cadar formals)
|
||||
"identifier following mode keyword ~a" k)]
|
||||
[else (loop (cdr formals) rests (cons k modes))])]
|
||||
[(not (memq k rest-like-kwds))
|
||||
(serror k-stx "unknown meta keyword")]
|
||||
[(assq k rests)
|
||||
|
@ -211,6 +215,9 @@
|
|||
(serror k-stx "missing variable name")]
|
||||
[(not (null? (cddar formals)))
|
||||
(serror k-stx "too many variable names")]
|
||||
#; ;(*)
|
||||
;; same as above: don't throw an error here, still fine if
|
||||
;; used with #:allow-other-keys (explicit or implicit)
|
||||
[(and (null? keys) (not (eq? #:rest k)))
|
||||
(serror k-stx "cannot use without #:key arguments")]
|
||||
[else (loop (cdr formals)
|
||||
|
@ -367,14 +374,24 @@
|
|||
(with-syntax ([body (make-rest-body expr)] [keys keys])
|
||||
#'(let* keys body)))
|
||||
;; ------------------------------------------------------------------------
|
||||
;; more sanity tests (see commented code above -- search for "(*)")
|
||||
(let ([r (or all-keys other-keys other-keys+body body rest)])
|
||||
(when (and (not allow-other-keys?) (null? keys))
|
||||
(when r (serror r "cannot use without #:key or #:allow-other-keys"))
|
||||
(when allow-duplicate-keys?
|
||||
(serror #f (string-append "cannot allow duplicate keys without"
|
||||
" #:key or #:allow-other-keys"))))
|
||||
(when (and allow-other-keys? (null? keys) (not r))
|
||||
(serror #f "cannout allow other keys without using them in some way")))
|
||||
;; ------------------------------------------------------------------------
|
||||
;; body generation starts here
|
||||
(cond
|
||||
;; no optionals or keys => plain lambda
|
||||
[(and (null? opts) (null? keys))
|
||||
;; no optionals or keys (or other-keys) => plain lambda
|
||||
[(and (null? opts) (null? keys) (not allow-other-keys?))
|
||||
(with-syntax ([vars (append! vars (or rest '()))] [expr expr])
|
||||
(syntax/loc stx (lambda vars expr)))]
|
||||
;; no keys => make a case-lambda for optionals
|
||||
[(null? keys)
|
||||
[(and (null? keys) (not allow-other-keys?))
|
||||
(let ([clauses (make-opt-clauses expr (or rest '()))])
|
||||
(with-syntax ([name name] [clauses clauses])
|
||||
(syntax/loc stx (letrec ([name (case-lambda . clauses)]) name))))]
|
||||
|
|
|
@ -375,9 +375,11 @@
|
|||
:st-err: <= (lambda/kw (x #:body x #:allow-other-keys) 1)
|
||||
:st-err: <= (lambda/kw (x #:optional ()) 1)
|
||||
:st-err: <= (lambda/kw (x #:optional (x y z)) 1)
|
||||
:st-err: <= (lambda/kw (x #:other-keys z) 1)
|
||||
:st-err: <= (lambda/kw (x #:other-keys+body z) 1)
|
||||
:st-err: <= (lambda/kw (x #:all-keys z) 1)
|
||||
;; :st-err: <= (lambda/kw (x #:other-keys z) 1) <-- these are all
|
||||
;; :st-err: <= (lambda/kw (x #:other-keys+body z) 1) <-- fine!
|
||||
;; :st-err: <= (lambda/kw (x #:all-keys z) 1) <-- (see below)
|
||||
:st-err: <= (lambda/kw (x #:other-keys z #:forbid-other-keys) 1)
|
||||
:st-err: <= (lambda/kw (x #:all-keys z #:forbid-other-keys) 1)
|
||||
:st-err: <= (lambda/kw (x #:key y #:allow-other-keys z) 1)
|
||||
:st-err: <= (lambda/kw (x #:key y #:forbid-body z) 1)
|
||||
:st-err: <= (lambda/kw (x #:key y #:allow-body #:rest r #:forbid-body) 1)
|
||||
|
@ -387,4 +389,12 @@
|
|||
:st-err: <= (lambda/kw (#:key a #:body r #:forbid-body) r)
|
||||
:st-err: <= (lambda/kw (#:key a #:other-keys r #:forbid-other-keys) r))
|
||||
|
||||
;; it is ok to have no keys, and still specify all-keys etc
|
||||
(let ([f (lambda/kw (x #:all-keys ak) (list x ak))])
|
||||
(t (f 1) => '(1 ())
|
||||
(f 1 #:a 2) => '(1 (#:a 2))
|
||||
(f 1 #:a 2 #:b 3) => '(1 (#:a 2 #:b 3))
|
||||
(f 1 #:a 2 #:a 3) => '(1 (#:a 2 #:a 3))
|
||||
(f 1 #:a 2 #:a 3) => '(1 (#:a 2 #:a 3))))
|
||||
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue
Block a user