diff --git a/racket/collects/syntax/contract.rkt b/racket/collects/syntax/contract.rkt index 1d285a7599..9f595a1399 100644 --- a/racket/collects/syntax/contract.rkt +++ b/racket/collects/syntax/contract.rkt @@ -19,6 +19,27 @@ #:context (or/c syntax? #f)) syntax?)]) +(module macro-arg/c racket/base + (require racket/contract/base + racket/contract/combinator) + + (provide macro-arg/c) + + (define (macro-arg/c macro-name ctc) + (let ([ctc-project (get/build-late-neg-projection (coerce-contract 'wrap-expr/c ctc))]) + ((cond [(flat-contract? ctc) make-flat-contract] + [(chaperone-contract? ctc) make-chaperone-contract] + [else make-contract]) + #:name (contract-name ctc) + #:first-order (contract-first-order ctc) + #:late-neg-projection + (λ (blame) + (let ([blame* (if macro-name (blame-add-context blame #f #:important macro-name) blame)]) + (ctc-project (blame-swap blame*)))) + #:list-contract? (list-contract? ctc))))) + +(require (for-template 'macro-arg/c)) + (define (wrap-expr/c ctc-expr expr #:positive [pos-source 'use-site] #:negative [neg-source 'from-macro] @@ -31,42 +52,47 @@ [neg-source-expr (get-source-expr neg-source (if (identifier? macro-name) macro-name ctx))] + [expr-name + (if (identifier? expr-name) + (syntax-e expr-name) + expr-name)] [macro-name (cond [(identifier? macro-name) (syntax-e macro-name)] [(or (string? macro-name) (symbol? macro-name)) macro-name] [(syntax? ctx) (syntax-case ctx () [(x . _) (identifier? #'x) (syntax-e #'x)] - [x (identifier? #'#'x)] + [x (identifier? #'x) (syntax-e #'x)] [_ #f])] [else #f])]) - (base-wrap-expr/c expr ctc-expr - #:positive #'(quote-module-name) + (base-wrap-expr/c expr #`(macro-arg/c '#,macro-name #,ctc-expr) + #:positive pos-source-expr #:negative neg-source-expr - #:expr-name (cond [(and expr-name macro-name) - (format "~a of ~a" expr-name macro-name)] - [expr-name expr-name] - [else #f]) + #:expr-name (cond [(and macro-name expr-name) + (format "~a of ~a" expr-name macro-name)] + [(or macro-name expr-name) + => (λ (name) (format "~a" name))] + [else #f]) #:source #`(quote-syntax #,expr)))) (define (base-wrap-expr/c expr ctc-expr #:positive positive #:negative negative - #:expr-name [expr-name #f] - #:source [source #f]) + #:expr-name expr-name + #:source source) (let ([expr-name (or expr-name #'#f)] [source (or source #'#f)]) (quasisyntax/loc expr (contract #,ctc-expr #,expr - #,positive #,negative + #,positive #,expr-name #,source)))) (define (get-source-expr source ctx) (cond [(eq? source 'use-site) - #'(quote-module-name)] + #'(quote-module-path)] [(eq? source 'unknown) #'(quote "unknown")] [(eq? source 'from-macro)