p.s. add a separate regular old (provide ...) for module interface routines that are not traceable ...
On Tue, Jan 20, 2015 at 5:59 PM, Thomas Lynch < thomas.ly...@reasoningtechnology.com> wrote: > Alright, here is one solution to the trace of libraries. > > 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. > > (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. > > 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 .. > > > ;;-------------------------------------------------------------------------------- > ;; defines a trace-able module interface > ;; > ;; (interface "lib-name" provide-functions ...) > ;; > ;; lib-name-trace to turn on tracing > ;; lib-name-untrace to turn off tracing > ;; > (define-syntax (provide-with-trace stx) > (let( > [datum (syntax->datum stx)] > ) > (let( > [prefix (cadr datum)] > [interface-functions (cddr datum)] > ) > (let( > [name-trace-fun (string->symbol (string-append prefix > "-trace"))] > [name-untrace-fun (string->symbol (string-append prefix > "-untrace"))] > ) > #| > (displayln name-trace-fun) > (displayln name-untrace-fun) > |# > (let( > [code-block `(begin)] > [trace-require '(require racket/trace)] > [trace-fun > (append > '(define) > (list (list name-trace-fun)) > (map (λ(e)`(trace ,e)) interface-functions) > ) > ] > [untrace-fun > (append > '(define) > (list (list name-untrace-fun)) > (map (λ(e)`(untrace ,e)) interface-functions) > ) > ] > [provide-calls (map (λ(e)`(provide ,e)) > interface-functions)] > ) > #| > (displayln code-block) > (displayln trace-require) > (displayln trace-fun) > (displayln untrace-fun) > (displayln provide-calls) > |# > (let*( > [program > (append > code-block > (list trace-require) > (list trace-fun) > (list untrace-fun) > provide-calls > ) > ] > ) > ;;(displayln program) > (datum->syntax stx program) > )))))) > > > > 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: > > > ;;-------------------------------------------------------------------------------- > ;; module interface > ;; > (provide-with-trace "db-lib" > db-init > db-exec > db-exec* > db-value > db-value* > db-maybe-value > db-maybe-value* > db-row > db-row* > db-rows > db-rows* > db-list > db-list* > db-lib-trace > db-lib-untrace > ) > > > 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. > > We plan to use this approach for all modules. > > Seems to be working. Hope someone finds this useful. > > -Thomas > > > > On Mon, Jan 19, 2015 at 11:31 PM, Thomas Lynch < > thomas.ly...@reasoningtechnology.com> wrote: > >> 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. >> >> I apologize if my original post wasn't clear, but I did modify the file >> that included "db-lib.rkt" as such: >> >> >> Saw this in another thread here, but the proposed solution didnt work, >> >> ... >> >> so I add this to "db-citation.rkt" >> >> (require racket/trace) >> >> (trace db-exec) >> >> >> And then at the prompt I get the following: >> >> Welcome to Racket v5.2.1. >> >> racket@> (enter! "db-citation.rkt") >> >> db-citation.rkt:26:11: set!: cannot mutate module-required identifier in: >> db-exec >> >> >> Alright, so what is the magic incantation here that allows one to >> debug/trace calls in included modules? >> >> And was trying to implement Vince's solution and was asking why the above >> didn't work. >> >> I also tried going to the library source and adding at the top: >> >> (require racket/trace) >> (trace db-exec) >> >> Running this again just now, I see that this gives me an error of >> >> racket@> (enter! "db-citation.rkt") >> >> ... and own in the regression tests ..> >> >> hooking test: drop-end-chars-test-0 >> 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 >> >> === context === >> /home/deep/src/db-citation.rkt: [running body] >> /usr/share/racket/collects/racket/enter.rkt:33:0: do-enter! >> /usr/share/racket/collects/racket/private/misc.rkt:87:7 >> >> >> Which is a big hint, I moved the traces to the bottom of the file, yes >> and now they work! Thanks. >> >> Top of the library file: >> >> (require racket/trace) >> >> >> 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: >> >> (trace db-exec) >> (trace db-rows) >> ... >> >> 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... >> >> >> On Mon, Jan 19, 2015 at 11:03 PM, J. Ian Johnson <i...@ccs.neu.edu> >> wrote: >> >>> To be fair, trace is more than that. >>> >>> Vincent's solution does work, but you have to modify the file - you >>> can't do this from the REPL. >>> 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. >>> >>> 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. >>> e.g. >>> (trace #:setter set-function!) >>> >>> -Ian >>> >>> ----- Original Message ----- >>> From: "Thomas Lynch" <thomas.ly...@reasoningtechnology.com> >>> To: "J. Ian Johnson" <i...@ccs.neu.edu> >>> Cc: "users" <users@racket-lang.org> >>> Sent: Monday, January 19, 2015 9:49:51 AM >>> Subject: Re: [racket] trace: set!: cannot mutate module-required >>> identifier - alright .. how do you do this? >>> >>> So to trace calls to the interface functions of a library I am to write a >>> gasket for the library. I may as well put a display of the args in the >>> gasket functions as at this point it is the same amount of code as >>> hooking >>> the trace. Of course then I have implemented trace. >>> >>> So to use trace in racket all you have to do is implement trace .. >>> really?? >>> >>> On Mon, Jan 19, 2015 at 10:06 PM, J. Ian Johnson <i...@ccs.neu.edu> >>> wrote: >>> >>> > Yes, racket 101 (305?) is that identifiers can only be set!'d in their >>> > defining module. This is to allow necessary optimizations such as >>> inlining. >>> > >>> > If you want to trace `f` from a different module. you can `(define (g . >>> > args) (apply f args)) (trace g)`, use `g` wherever you use `f`. You >>> won't >>> > get any calls the library makes internally, but if you're just tracing >>> for >>> > your own code, you'll be golden. >>> > >>> > -Ian >>> > >>> > ----- Original Message ----- >>> > From: "Thomas Lynch" <thomas.ly...@reasoningtechnology.com> >>> > To: "users" <users@racket-lang.org> >>> > Sent: Monday, January 19, 2015 8:59:55 AM >>> > Subject: [racket] trace: set!: cannot mutate module-required >>> identifier - >>> > alright .. how do you do this? >>> > >>> > Saw this in another thread here, but the proposed solution didnt work, >>> > well at least the way I understood it. So .. >>> > >>> > In file db-lib.rkt I have a definition: >>> > >>> > >>> > >>> > >>> > (provide db-exec) >>> > (define (db-exec a) ...) >>> > >>> > Then in racket >>> > >>> > >>> > >>> > >>> > > (enter! "db-user.rkt") >>> > >>> > Where db-citation.rkt has >>> > >>> > >>> > >>> > >>> > (require "db-lib.rkt") >>> > >>> > Now at the read-eval-print prompt I try >>> > >>> > >>> > >>> > >>> > (enter! "db-citation.rkt") >>> > >>> > And when I do (trace db-exec) I get the cannot mutate error. (Surely >>> this >>> > must be a racket 101 type problem.) So I try to include the module at >>> the >>> > current scope.. >>> > >>> > >>> > >>> > >>> > rac...@db-citation.rkt> (require "db-lib.rkt") >>> > rac...@db-citation.rkt> (require racket/trace) >>> > rac...@db-citation.rkt> (trace db-exec) >>> > >>> > rac...@db-citation.rkt> stdin::1130: set!: cannot mutate >>> module-required >>> > identifier in: db-exec >>> > ok, so that doesn't work, so I start over again. This time after >>> reading >>> > the thread on this list >>> > >>> > >>> > >>> > >>> > From: Vincent St-Amour (stamourv at ccs.neu.edu ) >>> > Date: Mon Oct 10 13:49:46 EDT 2011 >>> > >>> > which concludes by saying 'put the trace in your program that should >>> > work', so I add this to "db-citation.rkt" >>> > >>> > >>> > >>> > >>> > (require racket/trace) >>> > (trace db-exec) >>> > >>> > And then at the prompt I get the following: >>> > >>> > >>> > >>> > >>> > Welcome to Racket v5.2.1. >>> > racket@> (enter! "db-citation.rkt") >>> > db-citation.rkt:26:11: set!: cannot mutate module-required identifier >>> in: >>> > db-exec >>> > >>> > Alright, so what is the magic incantation here that allows one to >>> > debug/trace calls in included modules? >>> > >>> > Thanks! >>> > >>> > Thomas >>> > >>> > ____________________ >>> > Racket Users list: >>> > http://lists.racket-lang.org/users >>> > >>> >> >> >
____________________ Racket Users list: http://lists.racket-lang.org/users