Changes between Version 98 and Version 99 of NewGhciDebugger


Ignore:
Timestamp:
May 17, 2007 12:28:18 PM (7 years ago)
Author:
simonmar
Comment:

docs now incorporated into the manual

Legend:

Unmodified
Added
Removed
Modified
  • NewGhciDebugger

    v98 v99  
    11 
    22[[PageOutline]] 
    3  
    4 = Documentation for the new GHCi debugger = 
    5  
    6 These notes detail the breakpoint debugger which is being incorportated into GHCi. Note that there was/is a previous prototype debugger, and we share some of its code (specifically the term printer) (see: [wiki:GhciDebugger]). 
    7  
    8 ---- 
    9  
    10 == User's Manual == 
    11  
    12 === Command summary === 
    13  
    14 Parameters to commands are indicated in angular brackets `<...>`, optional parameters are followed by a question mark. Ellipses `...` indicate where a sequence of parameters is allowed. Everything else is literal text, as you would type it at the prompt. 
    15  
    16 Setting breakpoints: 
    17 {{{ 
    18    :break <module>? <line> 
    19    :break <module>? <line> <column> 
    20    :break <module>? <identifier> 
    21 }}} 
    22 Listing breakpoints: 
    23 {{{ 
    24    :show breaks    
    25 }}} 
    26 Deleting breakpoints: 
    27 {{{ 
    28    :delete <break_number> ... <break_number> 
    29    :delete * 
    30 }}} 
    31 Inspecting values: 
    32 {{{ 
    33    :print <expression> 
    34 }}} 
    35 Single stepping: 
    36 {{{ 
    37    :step 
    38    :step <expression> 
    39 }}} 
    40 Continuting execution from a breakpoint: 
    41 {{{ 
    42    :continue 
    43 }}} 
    44  
    45 === Starting the debugger === 
    46  
    47 The debugger is integrated with GHCi, and it is on by default. XXX Not true at the moment; you still have to use the -fhpc flag. The debugger slows program execution down by a factor of approximately XXX times. You can turn it off (to avoid the slowdown) using the XXX command line argument, when you start GHCi. 
    48  
    49 === Setting breakpoints === 
    50  
    51 The general rule of thumb for breakpoints is that you can set a breakpoint on any thing which is not a value (though there are some exceptions). For example, a literal character is a value, but a case expression is not.  
    52  
    53 We call the places where you can set breakpoints as '''breakable expressions''' (even if some of them aren't strictly expressions). 
    54  
    55 You '''can''' set breakpoints on the following things: (XXX) Check this list carefully! 
    56  1. Function applications. We allow breakpoints on partial applications, even though they are technically values. Also, if there is an application with more than one argument, we only allow breaks on the whole expression, not on the sub-applications within: e.g. for the expression `map f list`, we allow a break on the whole expression, but not on the sub-application of `map f`. 
    57  2. Case expressions. 
    58  3. Function declarations (all the equations of a function). 
    59  4. Case alternatives. 
    60  5. Do statements. 
    61  6. Guards. 
    62  7. Bodies of functions, pattern bindings, lambdas, guarded equations. 
    63  
    64 Conversely, you '''cannot''' set breakpoints on the following things, except if they occur as the outermost expression in the body of a declaration: 
    65  1. Literals. 
    66  2. Variables. 
    67  3. Do blocks. XXX check this one 
    68  4. List comprehensions. XXX check this one 
    69  
    70 You can set a breakpoint in three ways: 
    71  1. By line number. 
    72  2. By line and column number. 
    73  3. By function name (not implemented yet). 
    74  
    75 In each case you can specify in which module you want to set the breakpoint, however, if that is omitted, the debugger will choose a suitable default module for you (XXX give a better explanation of what module is chosen by default). 
    76  
    77 The syntax for setting breakpoints by line number is: 
    78  
    79 {{{ 
    80    :break <module>? <line> 
    81 }}} 
    82  
    83 This will activate the breakpoint which corresponds to the leftmost outermost breakable expression which ''begins'' and ''ends'' on the line indicated by the `<line>` parameter, if such an expression exists. XXX If no such expression exists then what happens? Currently the debugger will report an error message, but perhaps it is nicer for it to probe a few lines ahead until it finds a breakable expression, or give up after some threshold number of lines? 
    84  
    85 The syntax for setting breakpoints by line and column is: 
    86  
    87 {{{ 
    88    :break <module>? <line> <column> 
    89 }}} 
    90  
    91 This will activate the breakpoint which corresponds to the ''smallest'' breakable expression which encloses the source location `(<line>, <column>)`, if such an expression exists. If no such expression exists the debugger will report an error message. 
    92  
    93 The syntax for setting breakpoints by function name is: (XXX not yet implemented) 
    94  
    95 {{{ 
    96    :break <module>? <identifier> 
    97 }}} 
    98  
    99 This will activate the outermost breakpoint associated with the definition of `<identifier>`. If `<identifier>` is defined by multiple equations, the breakpoint will cover them all. This means the computation will stop whenever any of those equations is evaluated. XXX What about local functions? XXX What about functions defined in type classes (default methods) and instance declarations? 
    100  
    101 === Listing the active breakpoints === 
    102  
    103 You can list the set of active breakpoints with the following command: 
    104  
    105 {{{ 
    106    :show breaks 
    107 }}} 
    108  
    109 Each breakpoint is given a unique number, which can be used to identify the breakpoint should you wish to delete it (see the `:delete` command). Here is an example list of breakpoints: 
    110  
    111 {{{ 
    112    0) Main (12,4)-(12,8) 
    113    1) Foo (13,9)-(13,13) 
    114    2) Bar (14,4)-(14,47) 
    115 }}} 
    116  
    117 Breakpoint 0 is set in the module `Main` on the breakable expression which spans between the source locations (12,4) to (12,8). Similarly for breakpoints 1 and 2. [GHC counts '\t' as a single char for row number counts, we should mention this, or normalize the numbers - AJG] 
    118  
    119 === Deleting breakpoints === 
    120  
    121 You can delete any active breakpoint with the `:delete` command. Breakpoints are refered to by their unique number which is displayed by the `:show breaks` command (see above). You can refer to more than one breakpoint at a time, for example: 
    122 {{{ 
    123    :delete <break_number> ... <break_number> 
    124 }}} 
    125 This will delete all the breakpoints which are identified by the numbers `<break_number> ... <break_number>`. If you specify a breakpoint which does not exist, the debugger will simply ignore it. 
    126  
    127 You can also delete all the active breakpoints by giving the asterisk as an argument to `delete`, like so: 
    128 {{{ 
    129    :delete * 
    130 }}} 
    131 XXX I don't think the delete command actually turns the breakpoint off yet. Seems I forgot to do that. However, it does delete it, in the sense that ghci no longer prints it out when you ask to show the breakpoints. 
    132  
    133 === What happens when the debugger hits a breakpoint? === 
    134  
    135 When an executing computation hits an active breakpoint, control is returned to the GHCi prompt. The debugger will print out a message indicating where the breakpoint occurred, and the names and types of the local variables which are in scope at that point. Here is an example: 
    136  
    137 {{{ 
    138    Stopped at breakpoint in Main. Location: (6,6)-(6,20). 
    139    Locals: x :: Bool, f :: Bool -> Bool, xs :: [Bool], fx :: Bool, j :: Bool 
    140    *Main> 
    141 }}} 
    142  
    143 The string "`*Main>`" is GHCi's prompt marker. Note that it can change depending on what modules you have loaded.  
    144  
    145 All the normal GHCi commands work at the prompt, including the evaluation of arbitrary expressions. In addition to the normal prompt behaviour, the local variables of the breakpoint are also made available. For instance, in the above example the variable `f` is a function from booleans to booleans, and we can apply it to an argument in the usual way: 
    146  
    147 {{{ 
    148    *Main> f False 
    149    True 
    150 }}} 
    151  
    152 If there are no local variables in scope at a breakpoint, the debugger will print this message: 
    153 {{{ 
    154    No locals in scope. 
    155 }}} 
    156  
    157 The debugger also provides commands for inspecting the values of local variables without forcing their evaluation any further (see Inspecting values below).  
    158  
    159 You can continue execution of the current computation with the `:continue` and `:step` commands, explained below. 
    160  
    161 === Inspecting values === 
    162  
    163 It is important to note that, due to the non-strict semantics of Haskell (particularly lazy evaluation), the values of local variables at a breakpoint may only be partially evaluated. Therefore printing values may cause them to be further evaluated. This raises some interesting issues for the debugger because evaluating something could raise an exception, or it could cause another breakpoint to be fired, or it could cause non-termination. For these reasons we want to be able to print values in a way which preserves their current state of evaluation. The debugger provides the `:print` command for this purpose. 
    164  
    165 For example, suppose the local variable `xs` is bound to a list of booleans, but the list is completely unevaluated at a breakpoint. We can inspect its value without forcing any more evaluation like so: 
    166 {{{ 
    167    *Main> :print xs 
    168    xs = (_t1::[Bool]) 
    169 }}}  
    170 The debugger uses fresh variable names (starting with underscores) to display unevaluated expressions (often called ''thunks''). Here `_t1` is a thunk. A side effect of the `:print` command is that these fresh variables are made available to the command line, so we can refer to them future commands.  
    171  
    172 Sometimes we want to evaluate thunks a little bit further. This is easy to do because they are bound to variable names. For example, we can evaluate the outermost data constructor of `_t1` using `seq` like so: 
    173 {{{ 
    174    *Main> seq _t1 () 
    175    () 
    176 }}} 
    177 This forces the evaluation of the thunk bound to `_t1` to Weak Head Normal Form (WHNF), and then returns `()`. The purpose of the expression is to force the evaluation of `_t1`, we don't actually care about the answer, so `()` makes a good dummy value. 
    178  
    179 If we print `xs` again we can see that it has been evaluated a little bit more: 
    180 {{{ 
    181    *Main> :print xs 
    182    xs = [True | (_t2::[Bool])] 
    183 }}} 
    184 Here we discover that the value of `xs` is a list with `True` as its head and a thunk as its tail. The thunk is bound to the fresh variable `_t2`, which can be manipulated at the command line as usual. 
    185  
    186 Another way to force further evaluation of a thunk is to use it inside another expression. For instance, we could examine the spine of the list `xs` by computing its length: 
    187 {{{ 
    188    *Main> length xs 
    189    3 
    190    *Main> :print xs 
    191    xs = [True,(_t3::Bool),(_t4::Bool)] 
    192 }}} 
    193  
    194 === Single stepping === 
    195  
    196 When a computation has hit a breakpoint it is sometimes useful to continue execution up until the next breakable expression is evaluated, regardless of whether there is a breakpoint set at that location. This functionality is provided by the `:step` command: 
    197 {{{ 
    198    :step 
    199 }}} 
    200  
    201 The `:step` command accepts an optional argument expression. The expression is evaluated as usual, but the computation will stop at the first breakable expression which is encountered: 
    202 {{{ 
    203    :step <expression> 
    204 }}} 
    205  
    206 === Continuing execution after a breakpoint === 
    207  
    208 A computation which has stopped at a breakpoint can be resumed with the `:continue` command: 
    209 {{{ 
    210    :continue 
    211 }}} 
    212  
    213 === Nested breakpoints === 
    214  
    215 The debugger supports nested breakpoints. That is, when you are stopped at a breakpoint, you can issue a command which causes something to be evaluated, and that evaluation might stop at its own breakpoint. And so on ''ad infinitum''. The debugger maintains a stack of breakpoints, so that whenever a new breakpoint is reached it pushes information about how to resume on top of the stack. The `:step` and `:continue` commands resume execution of the topmost breakpoint on the stack. If the breakpoint stack is empty, and you try to resume execution by giving the `:step` command with no arguments, or the `:continue` command, the debugger will report this message: 
    216 {{{ 
    217    There is no computation running. 
    218 }}} 
    219  
    220 ---- 
    2213 
    2224== Known problems in the debugger ==