Using syntax/loc with ellipsis

You cannot use syntax/loc like that, since you need unsyntax (#,) to use syntax/loc, and unsyntax does not cooperate with ellipses.

One important note about syntax/loc: it only places the location on the outermost syntactic structure (pair, usually), and only if that structure originated from the syntax template. If the syntax template is just a pattern variable, then syntax/loc does not change the location of the syntax that the variable refers to.

One solution is to use a helper macro that takes the original syntax as an argument:

(define-syntax (example stx)
  (syntax-parse stx
    [(_ val:expr ...)
     #`(begin
         (process/loc val #,stx)
         ...)]))

(define-syntax (process/loc stx)
  (syntax-parse stx
    [(_ val:expr orig-stx)
     (syntax/loc #'orig-stx
       (process val))]))

A similar solution is to use a template metafunction, but keep in mind that the metafunction is only useful for applying syntax/loc if it is responsible for creating the syntactic structure that gets the location. For example:

(define-syntax (example stx)
  (define-template-metafunction (~process/loc mstx)
    (syntax-parse mstx
      [(_ arg:expr)
       (syntax/loc stx ;; not mstx
         (process arg))]))
  (syntax-parse stx
    [(_ val:expr ...)
     #`(begin (~process/loc val) ...)]))

The following variant would not set the source location as you want it:

(define-syntax (example stx)
  (define-template-metafunction (~loc mstx)
    (syntax-parse mstx
      [(_ arg:expr)
       (syntax/loc stx ;; NO EFFECT!
         arg)]))
  (syntax-parse stx
    [(_ val:expr ...)
     #`(begin (~loc (process val)) ...)]))
1 Like