<div dir="ltr">Alright, here is one solution to the trace of libraries.<div><br></div><div>The following is macro definition for a type of model provide statement that allows toggling on and off trace for the provided routines. Instead of using (provide x y z) you use (provide-with-trace "my-lib" x y z). Then the functions (my-lib-trace) will turn on tracing for x y and z, and (my-lib-untrace) turns them off. Use provide-with-trace only once per module.</div><div><br></div><div>(provide-with-trace ...) must be at the bottom of the module because the interface routines must be defined before trace can be turned on for them. Note the provide statement must be at module top level scope - not the top of the file, not the same thing of course, and the macro handles this.<br><br>Matthias would probably tell you to use a case match instead of pulling the args out of stx directly, while the docs tell you to use syntax-parse instead, so that the args can be put into syntax classes; however grabbing the args was the least of my worries here .. perhaps when I'm better at this ..</div><div><br></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><div><font face="monospace, monospace">;;--------------------------------------------------------------------------------</font></div></div><div><div><font face="monospace, monospace">;; defines a trace-able module interface</font></div></div><div><div><font face="monospace, monospace">;;</font></div></div><div><div><font face="monospace, monospace">;; (interface "lib-name" provide-functions ...)</font></div></div><div><div><font face="monospace, monospace">;;</font></div></div><div><div><font face="monospace, monospace">;; lib-name-trace to turn on tracing</font></div></div><div><div><font face="monospace, monospace">;; lib-name-untrace to turn off tracing</font></div></div><div><div><font face="monospace, monospace">;;</font></div></div><div><div><font face="monospace, monospace"> (define-syntax (provide-with-trace stx)</font></div></div><div><div><font face="monospace, monospace"> (let(</font></div></div><div><div><font face="monospace, monospace"> [datum (syntax->datum stx)]</font></div></div><div><div><font face="monospace, monospace"> )</font></div></div><div><div><font face="monospace, monospace"> (let(</font></div></div><div><div><font face="monospace, monospace"> [prefix (cadr datum)]</font></div></div><div><div><font face="monospace, monospace"> [interface-functions (cddr datum)] </font></div></div><div><div><font face="monospace, monospace"> )</font></div></div><div><div><font face="monospace, monospace"> (let(</font></div></div><div><div><font face="monospace, monospace"> [name-trace-fun (string->symbol (string-append prefix "-trace"))]</font></div></div><div><div><font face="monospace, monospace"> [name-untrace-fun (string->symbol (string-append prefix "-untrace"))]</font></div></div><div><div><font face="monospace, monospace"> )</font></div></div><div><font face="monospace, monospace"> #|</font></div><div><div><font face="monospace, monospace"> (displayln name-trace-fun)</font></div></div><div><div><font face="monospace, monospace"> (displayln name-untrace-fun)</font></div></div><div><font face="monospace, monospace"> |#</font></div><div><div><font face="monospace, monospace"> (let(</font></div></div><div><div><font face="monospace, monospace"> [code-block `(begin)]</font></div></div><div><div><font face="monospace, monospace"> [trace-require '(require racket/trace)]</font></div></div><div><div><font face="monospace, monospace"> [trace-fun</font></div></div><div><div><font face="monospace, monospace"> (append</font></div></div><div><div><font face="monospace, monospace"> '(define)</font></div></div><div><div><font face="monospace, monospace"> (list (list name-trace-fun))</font></div></div><div><div><font face="monospace, monospace"> (map (λ(e)`(trace ,e)) interface-functions)</font></div></div><div><div><font face="monospace, monospace"> )</font></div></div><div><div><font face="monospace, monospace"> ]</font></div></div><div><div><font face="monospace, monospace"> [untrace-fun</font></div></div><div><div><font face="monospace, monospace"> (append</font></div></div><div><div><font face="monospace, monospace"> '(define)</font></div></div><div><div><font face="monospace, monospace"> (list (list name-untrace-fun))</font></div></div><div><div><font face="monospace, monospace"> (map (λ(e)`(untrace ,e)) interface-functions)</font></div></div><div><div><font face="monospace, monospace"> )</font></div></div><div><div><font face="monospace, monospace"> ]</font></div></div><div><div><font face="monospace, monospace"> [provide-calls (map (λ(e)`(provide ,e)) interface-functions)]</font></div></div><div><div><font face="monospace, monospace"> )</font></div></div><div><div><font face="monospace, monospace"> #|</font></div></div><div><div><font face="monospace, monospace"> (displayln code-block)</font></div></div><div><div><font face="monospace, monospace"> (displayln trace-require)</font></div></div><div><div><font face="monospace, monospace"> (displayln trace-fun)</font></div></div><div><div><font face="monospace, monospace"> (displayln untrace-fun)</font></div></div><div><div><font face="monospace, monospace"> (displayln provide-calls)</font></div></div><div><div><font face="monospace, monospace"> |#</font></div></div><div><div><font face="monospace, monospace"> (let*(</font></div></div><div><div><font face="monospace, monospace"> [program </font></div></div><div><div><font face="monospace, monospace"> (append</font></div></div><div><div><font face="monospace, monospace"> code-block</font></div></div><div><div><font face="monospace, monospace"> (list trace-require)</font></div></div><div><div><font face="monospace, monospace"> (list trace-fun)</font></div></div><div><div><font face="monospace, monospace"> (list untrace-fun)</font></div></div><div><div><font face="monospace, monospace"> provide-calls</font></div></div><div><div><font face="monospace, monospace"> )</font></div></div><div><div><font face="monospace, monospace"> ]</font></div></div><div><div><font face="monospace, monospace"> )</font></div></div><div><div><font face="monospace, monospace"> ;;(displayln program)</font></div></div><div><div><font face="monospace, monospace"> (datum->syntax stx program)</font></div></div><div><div><font face="monospace, monospace"> ))))))</font></div></div></blockquote><div><div><br></div><br>As an example for using this, we have removed all of the (provide f) statements from the top of our db-lib module (which is a variation of the standard one) and now instead at the bottom of the file we have:<br><br></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div><font face="monospace, monospace">;;--------------------------------------------------------------------------------</font></div></div><div><div><font face="monospace, monospace">;; module interface</font></div></div><div><div><font face="monospace, monospace">;;</font></div></div><div><div><font face="monospace, monospace"> (provide-with-trace "db-lib"</font></div></div><div><div><font face="monospace, monospace"> db-init</font></div></div><div><div><font face="monospace, monospace"> db-exec</font></div></div><div><div><font face="monospace, monospace"> db-exec*</font></div></div><div><div><font face="monospace, monospace"> db-value</font></div></div><div><div><font face="monospace, monospace"> db-value*</font></div></div><div><div><font face="monospace, monospace"> db-maybe-value</font></div></div><div><div><font face="monospace, monospace"> db-maybe-value*</font></div></div><div><div><font face="monospace, monospace"> db-row</font></div></div><div><div><font face="monospace, monospace"> db-row*</font></div></div><div><div><font face="monospace, monospace"> db-rows</font></div></div><div><div><font face="monospace, monospace"> db-rows*</font></div></div><div><div><font face="monospace, monospace"> db-list</font></div></div><div><div><font face="monospace, monospace"> db-list*</font></div></div><div><div><font face="monospace, monospace"> db-lib-trace</font></div></div><div><div><font face="monospace, monospace"> db-lib-untrace</font></div></div><div><div><font face="monospace, monospace"> )</font></div></div></blockquote><div><div><br></div><div>Now when debugging, we type (db-lib-trace) to turn on tracing of calls to the db-lib interface. We call (db-lib-untrace) to turn the tracing off.<br><br>We plan to use this approach for all modules.<br><br></div><div>Seems to be working. Hope someone finds this useful.<br><br>-Thomas</div><br><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Jan 19, 2015 at 11:31 PM, Thomas Lynch <span dir="ltr"><<a href="mailto:thomas.lynch@reasoningtechnology.com" target="_blank">thomas.lynch@reasoningtechnology.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">please note, the simple example here is to facilitate discussion. trace is being used very broadly for an entire development cycle. This isn't a one time fix issue in general.<br><br>I apologize if my original post wasn't clear, but I did modify the file that included "db-lib.rkt" as such:<br><div><br></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><span class=""><div><span style="font-size:10px"> </span></div><span style="font-size:10px">Saw this in another thread here, but the proposed solution didnt work, <br></span></span><div><span style="font-size:10px"><br>...<br><br></span></div><span class=""><div><span style="font-size:10px">so I add this to "db-citation.rkt"</span></div><div><br style="font-size:10px"></div><div><blockquote style="font-size:10px;margin:0px 0px 0px 40px;border:none;padding:0px"><div> (require racket/trace)</div></blockquote></div><div><blockquote style="font-size:10px;margin:0px 0px 0px 40px;border:none;padding:0px"><div> (trace db-exec)</div></blockquote></div><div><div style="font-size:10px"><br></div></div><div><div style="font-size:10px">And then at the prompt I get the following:</div></div><div><div style="font-size:10px"><br></div></div><div><blockquote style="font-size:10px;margin:0px 0px 0px 40px;border:none;padding:0px"><div>Welcome to Racket v5.2.1.</div></blockquote></div><div><blockquote style="font-size:10px;margin:0px 0px 0px 40px;border:none;padding:0px"><div>racket@> (enter! "db-citation.rkt")</div></blockquote></div><div><blockquote style="font-size:10px;margin:0px 0px 0px 40px;border:none;padding:0px"><div>db-citation.rkt:26:11: set!: cannot mutate module-required identifier in: db-exec</div></blockquote></div><div><div style="font-size:10px"><br></div></div><div><div style="font-size:10px">Alright, so what is the magic incantation here that allows one to debug/trace calls in included modules?<br><br></div></div></span></blockquote><div>And was trying to implement Vince's solution and was asking why the above didn't work.<br><br></div>I also tried going to the library source and adding at the top:<br><br><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div> (require racket/trace)</div><div> (trace db-exec)<br><br></div></blockquote><div>Running this again just now, I see that this gives me an error of<br><br></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div>racket@> (enter! "db-citation.rkt")</div></div></blockquote><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div>... and own in the regression tests ..></div></blockquote><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div>hooking test: drop-end-chars-test-0</div></div><div><div>link: reference (phase 0) to a variable in module "/home/deep/src/db-lib.rkt" that is uninitialized (phase level 0); reference appears in module: "/home/deep/src/db-citation.rkt" in: db-exec</div></div><div><div><br></div></div><div><div> === context ===</div></div><div><div>/home/deep/src/db-citation.rkt: [running body]</div></div><div><div>/usr/share/racket/collects/racket/enter.rkt:33:0: do-enter!</div></div><div><div>/usr/share/racket/collects/racket/private/misc.rkt:87:7</div></div></blockquote><div><br></div><div>Which is a big hint, I moved the traces to the bottom of the file, yes and now they work! Thanks.</div><div><br></div><div>Top of the library file:</div><div><br></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div>(require racket/trace)</div></blockquote><div><br></div><div>Bottom of the library I copy all of the provides from the top, and then do a text replace with the "provide"-> "trace" and thus:<br><br></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div>(trace db-exec)</div><div>(trace db-rows)</div><div>...</div><div><br></div></blockquote>Yes, and now calls to the library are tracing. So to trace calls to a library, one edits the library, puts the require at the top, copies all the provides to the bottom, edits that to change the provides to trace, and then off it goes. .. could wrap the trace calls in a parameter switch (current-db-trace) or some such...<div><div class="h5"><div><br><div><div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Jan 19, 2015 at 11:03 PM, J. Ian Johnson <span dir="ltr"><<a href="mailto:ianj@ccs.neu.edu" target="_blank">ianj@ccs.neu.edu</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">To be fair, trace is more than that.<br>
<br>
Vincent's solution does work, but you have to modify the file - you can't do this from the REPL.<br>
You can modify the file containing the identifier you want to trace, if changing call sites is not palatable to you. Add `(require racket/trace)` at the top, and after the function definition `(trace function)`. Alternatively, if you only want to trace at given points in time, define and provide a function `(define (add-trace) (trace function))` so you can call `add-trace` when you want to turn on tracing.<br>
<br>
A missing feature for racket/trace is to provide a setter function so that modules that export a mutating function can be traced without depending on racket/trace. If a module contains a `set!` for an identifier, it disables any inlining for that identifier.<br>
e.g.<br>
(trace #:setter set-function!)<br>
<span><br>
-Ian<br>
<br>
----- Original Message -----<br>
From: "Thomas Lynch" <<a href="mailto:thomas.lynch@reasoningtechnology.com" target="_blank">thomas.lynch@reasoningtechnology.com</a>><br>
</span><div><div>To: "J. Ian Johnson" <<a href="mailto:ianj@ccs.neu.edu" target="_blank">ianj@ccs.neu.edu</a>><br>
Cc: "users" <<a href="mailto:users@racket-lang.org" target="_blank">users@racket-lang.org</a>><br>
Sent: Monday, January 19, 2015 9:49:51 AM<br>
Subject: Re: [racket] trace: set!: cannot mutate module-required identifier - alright .. how do you do this?<br>
<br>
So to trace calls to the interface functions of a library I am to write a<br>
gasket for the library. I may as well put a display of the args in the<br>
gasket functions as at this point it is the same amount of code as hooking<br>
the trace. Of course then I have implemented trace.<br>
<br>
So to use trace in racket all you have to do is implement trace ..<br>
really??<br>
<br>
On Mon, Jan 19, 2015 at 10:06 PM, J. Ian Johnson <<a href="mailto:ianj@ccs.neu.edu" target="_blank">ianj@ccs.neu.edu</a>> wrote:<br>
<br>
> Yes, racket 101 (305?) is that identifiers can only be set!'d in their<br>
> defining module. This is to allow necessary optimizations such as inlining.<br>
><br>
> If you want to trace `f` from a different module. you can `(define (g .<br>
> args) (apply f args)) (trace g)`, use `g` wherever you use `f`. You won't<br>
> get any calls the library makes internally, but if you're just tracing for<br>
> your own code, you'll be golden.<br>
><br>
> -Ian<br>
><br>
> ----- Original Message -----<br>
> From: "Thomas Lynch" <<a href="mailto:thomas.lynch@reasoningtechnology.com" target="_blank">thomas.lynch@reasoningtechnology.com</a>><br>
> To: "users" <<a href="mailto:users@racket-lang.org" target="_blank">users@racket-lang.org</a>><br>
> Sent: Monday, January 19, 2015 8:59:55 AM<br>
> Subject: [racket] trace: set!: cannot mutate module-required identifier -<br>
> alright .. how do you do this?<br>
><br>
> Saw this in another thread here, but the proposed solution didnt work,<br>
> well at least the way I understood it. So ..<br>
><br>
> In file db-lib.rkt I have a definition:<br>
><br>
><br>
><br>
><br>
> (provide db-exec)<br>
> (define (db-exec a) ...)<br>
><br>
> Then in racket<br>
><br>
><br>
><br>
><br>
> > (enter! "db-user.rkt")<br>
><br>
> Where db-citation.rkt has<br>
><br>
><br>
><br>
><br>
> (require "db-lib.rkt")<br>
><br>
> Now at the read-eval-print prompt I try<br>
><br>
><br>
><br>
><br>
> (enter! "db-citation.rkt")<br>
><br>
> And when I do (trace db-exec) I get the cannot mutate error. (Surely this<br>
> must be a racket 101 type problem.) So I try to include the module at the<br>
> current scope..<br>
><br>
><br>
><br>
><br>
> racket@db-citation.rkt> (require "db-lib.rkt")<br>
> racket@db-citation.rkt> (require racket/trace)<br>
> racket@db-citation.rkt> (trace db-exec)<br>
><br>
> racket@db-citation.rkt> stdin::1130: set!: cannot mutate module-required<br>
> identifier in: db-exec<br>
> ok, so that doesn't work, so I start over again. This time after reading<br>
> the thread on this list<br>
><br>
><br>
><br>
><br>
> From: Vincent St-Amour (stamourv at <a href="http://ccs.neu.edu" target="_blank">ccs.neu.edu</a> )<br>
> Date: Mon Oct 10 13:49:46 EDT 2011<br>
><br>
> which concludes by saying 'put the trace in your program that should<br>
> work', so I add this to "db-citation.rkt"<br>
><br>
><br>
><br>
><br>
> (require racket/trace)<br>
> (trace db-exec)<br>
><br>
> And then at the prompt I get the following:<br>
><br>
><br>
><br>
><br>
> Welcome to Racket v5.2.1.<br>
> racket@> (enter! "db-citation.rkt")<br>
> db-citation.rkt:26:11: set!: cannot mutate module-required identifier in:<br>
> db-exec<br>
><br>
> Alright, so what is the magic incantation here that allows one to<br>
> debug/trace calls in included modules?<br>
><br>
> Thanks!<br>
><br>
> Thomas<br>
><br>
> ____________________<br>
> Racket Users list:<br>
> <a href="http://lists.racket-lang.org/users" target="_blank">http://lists.racket-lang.org/users</a><br>
><br>
</div></div></blockquote></div><br></div></div></div></div></div></div></div>
</blockquote></div><br></div>