diff --git a/collects/racket/private/kw.rkt b/collects/racket/private/kw.rkt index 088e89b490..e0976864cb 100644 --- a/collects/racket/private/kw.rkt +++ b/collects/racket/private/kw.rkt @@ -357,185 +357,228 @@ #f "bad argument sequence" stx (syntax args))])))) ;; The new `lambda' form: + (define-for-syntax (parse-lambda stx non-kw-k kw-k) + (syntax-case stx () + [(_ args body1 body ...) + (if (simple-args? #'args) + ;; Use plain old `lambda': + (non-kw-k + (syntax-protect + (syntax/loc stx + (lambda args body1 body ...)))) + ;; Handle keyword or optional arguments: + (with-syntax ([((plain-id ...) + (opt-id ...) + ([id opt-expr kind] ...) + ([kw kw-id kw-req] ...) + need-kw + rest) + (parse-formals stx #'args)]) + (let ([dup-id (check-duplicate-identifier (syntax->list #'(id ... . rest)))]) + (when dup-id + (raise-syntax-error + #f + "duplicate argument identifier" + stx + dup-id))) + (let* ([kws (syntax->list #'(kw ...))] + [opts (syntax->list #'(opt-id ...))] + [ids (syntax->list #'(id ...))] + [plain-ids (syntax->list #'(plain-id ...))] + [kw-reqs (syntax->list #'(kw-req ...))] + [kw-args (generate-temporaries kws)] ; to hold supplied value + [kw-arg?s (generate-temporaries kws)] ; to indicated whether it was supplied + [opt-args (generate-temporaries opts)] ; supplied value + [opt-arg?s (generate-temporaries opts)] ; whether supplied + [needed-kws (sort (syntax->list #'need-kw) + (lambda (a b) (keywordlist #'(id ... . rest)))]) - (when dup-id - (raise-syntax-error - #f - "duplicate argument identifier" - stx - dup-id))) - (let* ([kws (syntax->list #'(kw ...))] - [opts (syntax->list #'(opt-id ...))] - [ids (syntax->list #'(id ...))] - [plain-ids (syntax->list #'(plain-id ...))] - [kw-reqs (syntax->list #'(kw-req ...))] - [kw-args (generate-temporaries kws)] ; to hold supplied value - [kw-arg?s (generate-temporaries kws)] ; to indicated whether it was supplied - [opt-args (generate-temporaries opts)] ; supplied value - [opt-arg?s (generate-temporaries opts)] ; whether supplied - [needed-kws (sort (syntax->list #'need-kw) - (lambda (a b) (keywordlist stx)]) (if (not (and l (pair? (cdr l)) @@ -762,8 +830,13 @@ #f "missing procedure expression; probably originally (), which is an illegal empty application" stx) - (quasisyntax/loc stx - (#%app . #,(cdr (syntax-e stx)))))) + (begin + (check-arity (- (length l) 2)) + (let ([args (cdr (syntax-e stx))]) + (syntax-protect + (or (generate-direct (cdr (if (pair? args) args (syntax-e args))) null) + (quasisyntax/loc stx + (#%app . #,args)))))))) ;; keyword app (maybe) (let ([exprs (let ([kw-ht (make-hasheq)]) @@ -812,17 +885,20 @@ (keywordsyntax stx '#%app)) + (parse-app (datum->syntax #f (cons #'new-app stx) stx) + (lambda (n) + (when (or (n . < . n-req) + (and (not rest?) + (n . > . (+ n-req n-opt)))) + (printf "~s\n" (list n n-req n-opt)) + (warning "wrong number of by-position arguments"))) + (lambda (args kw-args) + (let* ([args (syntax->list (datum->syntax #f args))] + [n (length args)]) + (and (not (or (n . < . n-req) + (and (not rest?) + (n . > . (+ n-req n-opt))))) + (let loop ([kw-args kw-args] [req-kws req-kws] [all-kws all-kws]) + (cond + [(null? kw-args) + (or (null? req-kws) + (and + (warning + (format "missing required keyword ~a" (car req-kws))) + #f))] + [else (let* ([kw (syntax-e (caar kw-args))] + [all-kws (let loop ([all-kws all-kws]) + (cond + [(null? all-kws) null] + [(keywordsyntax stx (cons wrap-id #'(arg ...)) stx stx)))] + [_ wrap-id]))) ;; Checks given kws against expected. Result is ;; (values missing-kw extra-kw), where both are #f if