could ghci debugger search for free variables better?

Simon Marlow marlowsd at gmail.com
Mon Nov 3 07:34:29 EST 2008


Peter Hercek wrote:
> Simon Marlow wrote:
>> We thought about this when working on the debugger, and the problem is 
>> that to make the debugger retain all the variables that are in scope 
>> rather than just free in the expression adds a lot of overhead, and it 
>> fundamentally changes the structure of the generated code: everything 
>> becomes recursive, for one thing.  Well, perhaps you could omit all 
>> the recursive references (except the ones that are also free?), but 
>> there would still be a lot of overhead due to having to retain all 
>> those extra references.
>>
>> It also risks creating serious space leaks, by retaining references to 
>> things that the program would normally discard.
>>
>> Fortunately it's usually easy to work around the limitation, just by 
>> adding extra references to your code, e.g. in a let expression that 
>> isn't used.
> 
> Yes, Pepe pointed this to me too along with the "Step inside
>  GHCi debugger" paper in monad reader. The problem is that
>  I mostly can find out what is wrong when I look at values of
>  some important variables when some important place in my code
>  is hit. Using the trick with const function to manually add
>  references is not that much better than simple "printf
>  debugging" (adding Debug.Trace.trace calls to the code).
>  Tracing the execution history is nice too but it provides
>  much more than what is needed and obscures the important parts.
> 
> OK, It is frustrating that I find "printf debugging" often more
>  productive than ghci debugger.
> 
> I see that it is not a good idea to keep references to all the
>  variables in scope but maybe few improvements are possible:
> 
> 1) As there is :steplocal, there should be also :tracelocal.
>    It would keep history of evaluations within given function
>    then when user asks for a variable it would be searched
>    first in the selected expression and if not found in the
>    expressions from the tracelocal history. If the result
>    would be printed from tracelocal history it should be indicated
>    so in the output. This would avoid the tedious task of
>    searching the trace history manually and moreover it would
>    limit the history to the interesting parts (so hopefully
>    the depth of 50 would be enough). The results from the
>    tracelocal history may not be from the expected scope
>    sometimes but the same problem is with "printf debugging".

Good suggestion - please submit it via the bugtracker,

http://hackage.haskell.org/trac/ghc/newticket?type=feature+request

> 2) I noticed only now that I do not know how to script
>    breakpoints. I tried
>    :set stop if myFreeVar == 666 then :list else :continue
>    ... and it did not work. My goal was to create a conditional
>    breakpoint. I also wanted to use it instead of "printf
>    debugging" using something like
>    :set stop { :force myFreeVar; :continue }
>    Ideally it should be possible to attach
>    different script for each breakpoint and the functions
>    for controlling debugger should be available in the
>    Haskell. I would expect this is already partially possible
>    now (using :set stop) and possibly some functions from
>    ghci api which correspond to ghci commands (like :set etc.).
>    But I do not know how, any pointers from experienced ghci
>    debugger users?

I think you want :cmd.  e.g.

:set stop :cmd if myFreeVar == 666 then return ":list" else return ":continue"

> Ghci debugger did not know some functions in my code which
>  I would expect it to know; e.g. field selection functions
>  from a record which is not exported from the module but
>  which are available withing module. Is this expected?
>  (I did not have any *.hi *.o files around when ghci did run
>  the code.)

It could be a bug, if you could figure out how to reproduce it and submit a 
bug report that would be great.

> Och and sometimes it did not recognize a free variable in
>  the selected expression. The code looked like
>  let myFn x = x `div` getDivisor state > 100 in
>  if myFn xxx then ...
>  the expression "myFn xxx" was selected while browsing trace
>  history but xxx was not recognized, but when I browsed into
>  myFn definition in the trace log the x (which represented
>  the same value) was recognized. Is this expected?

Again, please submit a bug report.  The debugger is supposed to give you 
access to all of the free variables of the current expression.

Cheers,
	Simon



More information about the Glasgow-haskell-users mailing list