guile-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: guile-debugging: how to access source properties from trap context


From: Neil Jerram
Subject: Re: guile-debugging: how to access source properties from trap context
Date: Tue, 03 Jan 2006 22:57:44 +0000
User-agent: Gnus/5.1007 (Gnus v5.10.7) Emacs/21.4 (gnu/linux)

Holger Blasum <address@hidden> writes:

> Hello Neil,
>
> On 01-02 and 02-02, Neil Jerram wrote:
>> Neil Jerram <address@hidden> writes:
> ... 
>> debug> step
> ...
>> debug> info frame
> (iterate ad nauseam)
>
> Thanks that was I was looking for! Hadn't thought of using
> "info frame" to spit out the source properties (argh even gdb
> does this).

Perhaps it would make sense for the debugger to show the source
position automatically on each step?  What do you think?

>
> FWIW, maybe I should explain (didnt want to bloat the first posting 
> with that) that I am trying to study the inner workings of a theorem prover 
> (minlog) so I'm tracing -crudely put- "where the action is". In addition, 
> one (admittedly brute force) way of profiling anything in any system 
> is just to pipe a long list of "step" + "info frame" into the guile 
> [or whatever] stepper and parse the output 
> for position information. (Moreover unlike a gprof-approach
> I prefer not to loose the sequential order of what 
> is called.)

So are you really looking for a _non_-interactive solution then?

In that case I recommend the trace-trap and trace-until-exit
behaviours provided by (ossau trace), and `set-trace-layout' to
configure exactly what trace output you want at each trap point.
Here's an example:

guile> (use-modules (ossau breakpoints) (ossau trace))
guile> (load "matrix.scm")
guile> (break-in 'mkmatrix #:behaviour (list trace-trap trace-until-exit))
#<<break-in> 808b450>
guile> (do-main 4)
|  2: [mkmatrix]
|  3: [let (let # #) (# #)]
|  3: [let (let # #) (# #)]
|  3: (address@hidden (x 1) address@hidden (quote this-is-a-matric))
|  2: (let ((x 1)) (quote this-is-a-matric))
|  3: [quote (quote this-is-a-matric) (# # #)]
|  3: [quote (quote this-is-a-matric) (# # #)]
|  3: (address@hidden this-is-a-matric)
|  2: (quote this-is-a-matric)
|  2: this-is-a-matric
this-is-a-matric
guile> (set-trace-layout "address@hidden: ~a\n" trace/source trace/info)        
  
guile> (do-main 4)
      matrix.scm:6:2: [mkmatrix]
      matrix.scm:2:2: (let ((x 1)) (quote this-is-a-matric))
     matrix.scm:3:20: (quote this-is-a-matric)
     matrix.scm:3:20: this-is-a-matric
this-is-a-matric
guile> 

(There are fewer trace lines for the second invocation of (do-main 4)
because of the effects of memoization, not because of the
set-trace-layout change.)

>
> What in that context of stepping would interest me is: is there 
> also a trap not only for evaluations and applications but also for 
> definitions (I mean performance-wise definitions dont come for free 
> either). 

Definitions are no different in principle, but it is harder to set up
a breakpoint to cover them, and they're not actually that interesting.

To set a breakpoint on a top level definition, you have to use
`break-at' with the file name, line number and column number of the
definition's opening parenthesis.  This kind of works ...

guile> (use-modules (ossau breakpoints) (ossau trace))
guile> (break-at "matrix.scm" 1 0 #:behaviour (list trace-trap 
trace-until-exit))
#<<break-at> 808b490>
guile> (set-trace-layout "address@hidden: ~a\n" trace/source trace/info)
guile> (load "matrix.scm")
      matrix.scm:1:0: (define (mkmatrix) (define yy 23) (let ((x 1)) (quote 
this-is-a-matric)))
                    : [define (define # # #) (#)]
                    : [define (define # # #) (#)]
                    : (lambda () (define yy 23) (let ((x 1)) (quote 
this-is-a-matric)))
                    : [lambda (lambda () (define yy 23) ...) (#<eval-closure 
4028db30>)]
                    : [lambda (lambda () (define yy 23) ...) (#<eval-closure 
4028db30>)]
                    : (address@hidden () address@hidden (define yy 23) (let ((x 
1)) (quote this-is-a-matric)))
                    : [module-make-local-var! #<directory (guile-user) 8085240> 
mkmatrix]
                    : [module-make-local-var! #<directory (guile-user) 8085240> 
mkmatrix]
                    : (or (let ((b (module-obarray-ref (module-obarray m) v))) 
(and (variable? b) (begin (module-modified m) b))) (and (module-binder m) 
((module-binder m) m v #t)) (begin (let ((answer (make-undefined-variable))) 
(variable-set-name-hint! answer v) (module-obarray-set! (module-obarray m) v 
answer) (module-modified m) answer)))
                    : (let ((b (module-obarray-ref (module-obarray m) v))) (and 
(variable? b) (begin (module-modified m) b)))
                    : (module-obarray-ref (module-obarray m) v)
                    : (module-obarray m)
         ...

but (i) it's not very illuminating, because none of the body of the
definition is actually evaluated at this time, and (ii) once the
implicit lambda has been evaluated, the evaluator then goes into a
whole load of guff to do with the module system (which continues for
much longer than shown here).

(Internal definitions are a bit easier and clearer, because they don't
involve the module system.  For example, if I add an internal define
to my definition of mkmatrix:

guile> (use-modules (ossau breakpoints) (ossau trace))
guile> (load "matrix.scm")
guile> (break-in 'mkmatrix #:behaviour (list trace-trap trace-until-exit))
#<<break-in> 808b440>
guile> (set-trace-layout "address@hidden: ~a\n" trace/source trace/info)
guile> (do-main 4)
      matrix.scm:7:2: [mkmatrix]
                    : [define (define yy 23) ((()) #<eval-closure 4028db30>)]
                    : [define (define yy 23) ((()) #<eval-closure 4028db30>)]
                    : (address@hidden yy 23)
                    : [let (let # #) (# #)]
                    : [let (let # #) (# #)]
                    : (address@hidden (x 1) address@hidden (quote 
this-is-a-matric))
                    : (letrec ((yy 23)) (let ((x 1)) (quote this-is-a-matric)))
                    : [let (let # #) (# # #)]
                    : [let (let # #) (# # #)]
                    : (address@hidden (x 1) address@hidden (quote 
this-is-a-matric))
      matrix.scm:3:2: (let ((x 1)) (quote this-is-a-matric))
                    : [quote (quote this-is-a-matric) ((x . 1) ((yy) 23) (()) 
...)]
                    : [quote (quote this-is-a-matric) ((x . 1) ((yy) 23) (()) 
...)]
                    : (address@hidden this-is-a-matric)
     matrix.scm:4:20: (quote this-is-a-matric)
     matrix.scm:4:20: this-is-a-matric
this-is-a-matric
guile> (do-main 4)
      matrix.scm:7:2: [mkmatrix]
                    : (letrec ((yy 23)) (let ((x 1)) (quote this-is-a-matric)))
      matrix.scm:3:2: (let ((x 1)) (quote this-is-a-matric))
     matrix.scm:4:20: (quote this-is-a-matric)
     matrix.scm:4:20: this-is-a-matric
this-is-a-matric
guile> 

but I don't think you were talking about internal definitions.)

>> It's not important for the rest of my reply, but can you indicate
>> exactly where in the doc you are referring to, so I can review
>> whether this encouragement is worded as well as it could be?
>
> 2.4.4 Trap Context: "This information can be accessed through
> the procedures beginning tc: that are exported by the (ossau
> traps) modules", this had insinuated to me that any
> public method would have appeared as 'tc:'-prefixed one (defined 
> in the <trap-context> class in the beginning of that source 
> file) as opposed to the non 'tc:'-prefixed extra goodies 
> you have now mentioned '(trace/source trap-context)'.

Thanks.  Can you suggest some wording that would make it clear that
these are not the _only_ available procedures for getting information
out of a trap context?  (Perhaps something including a reference back
to 2.4.2?)

>
> While we are at it, to give feedback, for the imperative-language-
> impaired like me "2.10 Step Traps" maybe could be renamed to sth 
> like "2.10 Step Traps and gdb-like stepping" including the small 
> sample you had sent. And a note on profiling (perhaps 2.15?) 
> could be sweet. (Disclaimer: these are just ramblings.)

What about instead adding a whole new "Examples" chapter before the
current "Traps" one, containing the examples that we've discussed in
this thread, and other useful ones as they arise in future?  I think
that would be easier for a reader to find than an example buried
inside 2.10, and would allow 2.10 and its neighbours to keep their
existing more reference-style flavour.

Also, I'm still not quite clear what you mean by profiling.  Which of
the examples that we've discussed best fits what you have in mind?

>
> At last, some words on "[FIXME: should we include examples of traditional
> debuggers and explain why they can't be used to debug interpreted
> Scheme or Lisp?]" 
> http://www.gnu.org/software/guile/docs/guile-ref/Debugging-Features.html#Debugging%20Features
> might be of interest to anyone still following this thread ;)

I'm afraid I have no idea what the author of those words had in mind!
But in any case these words are no longer present in the CVS HEAD
version of the reference manual, so they will not be there when the
next major version of Guile (1.8) is released.

Regards,
        Neil





reply via email to

[Prev in Thread] Current Thread [Next in Thread]