[racket-dev] Preserving source location in macro-generating macros, in collects

From: Robby Findler (robby at eecs.northwestern.edu)
Date: Fri Oct 7 12:24:52 EDT 2011

On Fri, Oct 7, 2011 at 11:15 AM, Neil Toronto <neil.toronto at gmail.com> wrote:
> On 10/07/2011 09:56 AM, Robby Findler wrote:
>> On Fri, Oct 7, 2011 at 10:35 AM, Neil Toronto<neil.toronto at gmail.com>
>>  wrote:
>>> Why I care: I wrote a macro that both defines a contracted function and
>>> defines a macro that expands to a Scribble 'defproc' with the same
>>> contract.
>>> With the source locations gone (recursively), Scribble can't format the
>>> contracts, and I end up with things like (real-in01) instead of (real-in
>>> 0
>>> 1).
>>> (I know about scribble/srcdoc, but dependencies keep me from using it.)
>> Can you say more about the dependencies issue?
> Sure! I have a module "parameters.rkt" that everything in the collection
> depends on. It has its own page in the docs as well. The best way to explain
> some of them - like plot-x-transform, which you can use to do log-scale axes
> - is to use an example. But I can't refer to 'plot' inside "parameters.rkt".
> I think.
> Here's the thing. When I first looked into it, I wasn't making a collection;
> 'plot' was just a directory on my hard drive. I tried using
> 'scribble/srcloc', and it kept not finding modules. So what I think is true
> about it are often assumptions and inferences.
> For example, I think that it wouldn't give me the freedom to present the API
> in the order/grouping I want it in, for the cases where the best
> order/grouping in the docs is different from the best order/grouping in the
> code.

I think there are hooks in there to make this pretty flexible. The
framework docs use them to slice up things and move things around. You
might take a look at how it is set up and see if something like that
would work.

>>> Suppose I have a "location reporter" macro, which is generated by a
>>> macro:
>>> #lang racket
>>> (require (for-syntax syntax/srcloc))
>>> (provide location-reporter)
>>> (define-syntax (make-location-reporter stx)
>>>  (syntax-case stx ()
>>>    [(_ name)  #'(define-syntax (name inner-stx)
>>>                   (syntax-case inner-stx ()
>>>                     [(_)  #`#,(source-location->string #'name)]))]))
>>> (make-location-reporter location-reporter)
>>> If I compile this in DrRacket, require it from another module, and do
>>>    (location-reporter)
>>> it expands to
>>>    "<collects>/plot/location-reporter.rkt:13.24"
>>> as I expect. But if I compile it as part of "raco setup", it expands to
>>>    "<collects>/plot/location-reporter.rkt"
>>> I understand that stripping source locations is an optimization. But is
>>> there a way to turn it off, or preserve them, recursively, another way?
>>> Also, exactly how is the location information disappearing? Does it
>>> happen
>>> when 'name' above is double-syntax-quoted?
>> When a syntax object is compiled and written to a .zo file, all that
>> information is stripped. You have to write use another function at
>> compile time that walks over the syntax objects and records the source
>> locations and then saves them in some way that is not a syntax object
>> literal. Then restore them.
> I was afraid of that. Probably not too hard, but not a cakewalk, either.

There may be some library that I don't know about that helps with this.


Posted on the dev mailing list.