This causes an error with the pattern variable not catching that I am using an ellipsis. I've tried using with-syntax and template-metafunctions to no avail, does anyone know of a specific way in which I could use syntax/loc with the ellipsis?
It can be tricky to know "the shape" of these kinds of forms, but it is helpful to remember that syntax/loc is like syntax, i.e. #', but with the source-location data from the stx in the first argument.
I think technically what you want to do, is related to quasisyntax/loc, which is again, like quasisyntax, i.e. #, but with source-location information from the relevant syntax.
Ag, and then I go and talk nonsense. quasisyntax is supposed to be related to "#`". The idea is there, I apologize for being a moron.
Other more experienced Racketeers will be able to give a more definitive answer, because I can only see the "shape" mismatch, but not necessarily the clear rationale for how this should be done.
I will try this approach out when I get back to my desktop, but unfortunately I suspect it probably wouldn't work for what I'm attempting to do. I think I may have oversimplified in attempt to get a minimal breaking example, my bad.
I'm trying to highlight specific values in the ellipsis because I'm using code to manipulate the values in the ellipsis that could cause an error if the macro is used incorrectly. Here is I think a closer albeit more abstract idea of what the problem I'm trying to solve is:
I think I am not oversimplifying it this time (I hope), but it seems to me I actually need the syntax/loc to be repeated by the ellipsis. I would be very happy to be wrong though, because I imagine it would make implementing proper syntax highlighting for my macro much easier
As @soegaard's answer shows, the problem isn't specific to syntax/loc: the fundamental issue is that ... can't handle any template term that uses unsyntax (a.k.a. #,), because ... doesn't know how to map the expression over (potentially nested) lists of pattern variables.
FWIW, if you are using syntax-parse, I would use #:with instead of with-syntax.
#lang racket/base
(require (for-syntax racket/base
syntax/parse))
(define-syntax (example stx)
(syntax-parse stx
[(_ (id val) ...)
#:with (rhs ...) (for/list ([val-expr (syntax->list #'(val ...))])
;; do work here ...
(quasisyntax/loc val-expr #,val-expr))
#`(let ([id rhs] ...)
(list id ...))]))
(example [a 1] [b 2]) ; -> '(1 2)
Just to check, are you manipulating the “values” at compile time or at run time?
At compile time, you only have the syntax of the sub-expression (or, more generally, the sub-form): it isn't evaluated until runtime. So you might have #'(+ 1 2) instead of #'3. The best way to detect and report compile-time errors in macro subterms is to use syntax/parse's syntax classes.
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:
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:
I am, however I am working with a colleague who has already created contracts which I would have to essentially decompose and reapply to the various arguments (its easier to just redirect the syntax highlighting in this particular case). I tried this since it seems to be one proper way to achieve the granular highlighting I'm looking for, but I appear to still be running into similar issues I've had previously in regard to syntax highlighting.
I did get this to work when using "stx" as the location expression, but as expected it highlights the entire expression rather than the specific subexpression. I was hopeful that using the values of the ellipsis as the location expression would work, however when using them as the location expression I seemed to be causing some inordinate amount of work somewhere (I've never waited longer than 30 seconds to a minute before killing the program, so maybe it will terminate but it's still excessive).
The final thing I've tried since is using with-handlers to re-raise the exception with a srcloc. This appears like it would work if I could differentiate which contract raised the exception with the predicate. I haven't looked too deeply into this yet, so maybe I'm just not aware of how to differentiate them.
For the time being I think I'll use the helper macro suggested by @ryanc but I am still looking for a way to highlight specific expressions. If I can't figure out a way to differentiate which contract raised the exception I'll probably attempt to combine expr/c with with-handlers next? Not the most elegant solutions unfortunately...
By the way, thank you all for your help in trying to figure this out, its very appreciated