Hi everyone, I'm writing a macro-generating macro where the generated macro uses `syntax-parse`, and I can't figure out how to work with attributes using the dot syntax where the base identifier is generated by the outer macro.
For example, consider the following macro: (define-syntax example-macro (syntax-parser [(_ (~alt (~optional (~seq #:a (~var a (expr/c #'symbol?))) #:defaults ([a.c #''default-a])) (~optional (~seq #:b (~var b (expr/c #'string?))) #:defaults ([b.c #'"default-b"]))) ...) #`(list a.c b.c)])) I have a macro like `example-macro`, but more complicated and with many, many more potential keyword arguments, so I wanted to write a macro that would let me define `example-macro` with a more declarative syntax, like this: (define-example-macro/working generated-example-macro [#:a 'default-a symbol?] [#:b "default-b" string?]) My initial attempt looked something like this: (define-syntax (define-example-macro/buggy stx) (define-syntax-class arg-clause (pattern [kw:keyword default:expr contract:expr])) (syntax-parse stx [(_ name clause:arg-clause ...+) ;#:with (arg ...) (generate-temporaries #'(clause.kw ...)) ;#:with (arg.c ...) (generate-temporaries #'(clause.kw ...)) #`(define-syntax name (syntax-parser [(_ (~alt (~optional (~seq clause.kw (~var arg (expr/c #'clause.contract))) #:defaults ([arg.c #'clause.default])) ...) (... ...)) #`(list arg.c ...)]))])) which raises a syntax error "syntax: no pattern variables before ellipsis in template". The problem seems to be that `arg.c` is not recognized as a pattern variable derived from `arg`. I tried several variants on this, none of which allowed me to refer to `arg.c`. For example, if I uncomment the two `#:with` lines, I get the error "~optional: attribute bound in defaults but not in pattern". I eventually figured out a tricky way to avoid using dotted attributes altogether (see below), but it's rather less elegant than the non-working way. I am hoping there is a way to generate the right identifier for `arg.c` somehow. Thanks, Philip (define-syntax (define-example-macro/working stx) (define-syntax-class arg-clause (pattern [kw:keyword default:expr contract:expr] #:with arg (generate-temporary #'kw) )) (syntax-parse stx [(_ name clause:arg-clause ...+) #:with add-contract (generate-temporary 'add-contract) #:with (unsyntax-arg.c ...) #`(#,@(for/list ([arg-stx (in-list (syntax-e #'(clause.arg ...)))] [contract-stx (in-list (syntax-e #'(clause.contract ...)))]) (with-syntax ([arg arg-stx] [contract contract-stx]) #'#,(add-contract #'arg #'contract)))) #`(define-syntax (name inner-stx) (define (add-contract arg-stx contract-stx [err-name "name goes here"]) (syntax-parse arg-stx [the-arg #:declare the-arg (expr/c contract-stx #:name err-name #:macro #'name) #'the-arg.c])) (syntax-parse inner-stx [(_ (~alt (~optional (~seq clause.kw clause.arg) #:defaults ([clause.arg #'clause.default])) ...) (... ...)) #`(list unsyntax-arg.c ...)]))])) -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.