From: Pepe Iborra Date: Sun, 10 Dec 2006 18:41:23 +0000 (+0000) Subject: GHCi debugger documentation X-Git-Tag: 2006-12-17~15 X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=commitdiff_plain;h=3e4ee05cb301bd9f10d6a64b610c21c1f890f50b GHCi debugger documentation --- diff --git a/docs/users_guide/flags.xml b/docs/users_guide/flags.xml index 149ef63..a993b42 100644 --- a/docs/users_guide/flags.xml +++ b/docs/users_guide/flags.xml @@ -477,6 +477,18 @@ static - + + + Generate bytecode enabled for debugging + dynamic + - + + + + Do not include debugging information in bytecodes + dynamic + - + diff --git a/docs/users_guide/ghci.xml b/docs/users_guide/ghci.xml index f56c079..bbc2b6f 100644 --- a/docs/users_guide/ghci.xml +++ b/docs/users_guide/ghci.xml @@ -764,7 +764,7 @@ it <- e Eq, or Ord. The same type-default behaviour can be enabled in an ordinary Haskell - module, using the flag -fextended-default-rules. + module, using the flag -fextended-default-rules. @@ -906,6 +906,21 @@ $ ghci -lm + :breakpoint list|add|del|stop|step ... + :breakpoint + + + Permits to add, delete or list the breakpoints in a debugging session. + In order to make this command available, the + -fdebugging flag must be active. The easiest way is to launch + GHCi with the -fdebugging option. For more + details on how the debugger works, see . + + + + + + :browse *module ... :browse @@ -1147,6 +1162,50 @@ Prelude> :main foo bar + :print names ... + :print + + + Prints a semievaluated value without forcing its evaluation. + :print works just like :sprint but additionally, + :print binds the unevaluated parts -called + suspensions- + to names which you can play with. For example: + +Prelude> let li = map Just [1..5] +Prelude> :sp li +li - _ +Prelude> :p li +li - (_t1::[Maybe Integer]) +Prelude> head li +Just 1 +Prelude> :sp li +li - [Just 1 | _] +Prelude> :p li +li - [Just 1 | (_t2::[Maybe Integer])] +Prelude> last li +Just 5 +Prelude> :sp li +li - [Just 1,_,_,_,Just 5] +Prelude> :p li +li - [Just 1,(_t3::Maybe Integer),(_t4::Maybe Integer),(_t5::Maybe Integer),Just 4] +Prelude> _t4 +Just 3 +Prelude> :p li +li - [Just 1,(_t6::Maybe Integer),Just 3,(_t7::Maybe Integer),Just 4] + + The example uses :print and :sprint + to help us observe how the li variable is evaluated progressively as we operate + with it. Note for instance how last traverses all the elements of + the list to compute its result, but without evaluating the individual elements. + Finally note that the Prolog convention of [head | tail] is used by + :sprint to display unevaluated lists. + + + + + + :quit :quit @@ -1250,7 +1309,36 @@ Prelude> :main foo bar Show the list of modules currently load. - + + + :sprint + :sprint + + + Prints a semievaluated value without forcing its evaluation. + :sprint and its sibling :print + are very useful to observe how lazy evaluation works in your code. For example: + +Prelude> let li = map Just [1..5] +Prelude> :sp li +li - _ +Prelude> head li +Just 1 +Prelude> :sp li +li - [Just 1 | _] +Prelude> last li +Just 5 +Prelude> :sp li +li - [Just 1,_,_,_,Just 5] + + The example uses :sprint to help us observe how the li variable is evaluated progressively as we operate + with it. Note for instance how last traverses all the elements of + the list to compute its result, but without evaluating the individual elements. + Finally note that the Prolog convention of [head | tail] is used by + :sprint to display unevaluated lists. + + + :ctags filename @@ -1448,7 +1536,234 @@ Prelude> :set -fno-glasgow-exts staticoptions + + The GHCi debugger + debugger + GHCi embeds an utility debugger with a very basic set of operations. The debugger + is always available in ghci, you do not need to do anything to activate it. + The following conditions must hold before the debugger can be used with a module: + + + The module must have been loaded interpreted, i.e. not loaded from an .o file compiled by ghc + + + The module must have been loaded with the -fdebugging flag + + + Using the debugger + The debugger allows the insertion of breakpoints at specific locations in the source code. These locations are goberned by event type, and not by line as in traditional debuggers for imperative languages. + Once a breakpointed event is hit, the debugger stops the execution and you can examine the local variables in scope + in the context of the event, and evaluate arbitrary Haskell expressions in + a special interactive environment prompt.No matter what you do at the + breakpoint context, you cannot change the value assigned to the bindings of + your program. When you are done you issue the :quit + command and the execution goes on. All the other GHCi commands are supported + too, but the commands :load and :reload, + will cause a breakpoint session to stop. + + + Events + Events are the places in source code where you can set a breakpoint. + +qsort [] = [] +qsort (x:xs) = + let left = filter (\y -> y < x) xs + right = case filter (\y -> y > x) xs of + right_val -> right_val + in qsort left ++ [x] ++ qsort right +main = do { + arg <- getLine ; + let num = read arg :: [Int] ; + print (qsort num) ; + putStrLn "GoodBye!" } + + The GHCi debugger recognizes the following event types: + + + Function definition and local bindings in let/where + + + Lambda expression entry point + + + Let expression body + + + Case alternative body + + + do notation statements + + + In reality however, we eliminate some redundant event sites. + For instance, sites with two co-located breakpoint events are coalesced into a single one, + and sites with no bindings in scope are assumed to be uninteresting and eliminated + too. + + + + You don't need to do anything special in order to start the debugging session. + Simply use ghci to evaluate your Haskell expressions and whenever a breakpoint + is hit, the debugger will enter the stage: + +*main:Main> :break add Main 2 +Breakpoint set at (2,15) +*main:Main> qsort [10,9..1] +Local bindings in scope: + x :: a, xs :: [a], left :: [a], right :: [a] +qsort2.hs:2:15-46> + + What is happening here is that GHCi has interrupted the evaluation of + qsort at the breakpoint set in line 2, as the prompt indicates. + At this point you can freely explore the contents of the bindings in scope, + but with two catches. + First, take into account that due to the lazy nature of Haskell, some of + these bindings may be unevaluated, and that exploring their contents may + trigger a computation. + Second: look at the types of the things in scope. + GHCi has left its types parameterised by a variable! + This is due to the type of the qsort function, which is + polymorphic on the type of its argument. It does not + tell us really what the types of x and xs can be. + In general, polymorphic programs deal with polymorphic values, + and this means that some of the bindings available in a breakpoint site + will be parametrically typed. + + So, what can we do with a value without concrete type? Very few interesting + things. The :print command in ghci allows you to + explore its contents and see if it is evaluated or not. + This is useful because you cannot just type x in the + prompt and expect GHCi to return you the value of a. Perhaps you know for + sure that + x is of type Int which is an instance of + Show, but GHCi does not have this information. + :print however is fine, because it does not need to know the + type of x to do its work. + Let's go on with the debugging session of the qsort + example: + +qsort2.hs:2:15-46> x +This is an untyped, unevaluated computation. You can use seq to +force its evaluation and then :print to recover its type +qsort2.hs:2:15-46> seq x () +() +qsort2.hs:2:15-46> x +This is an untyped, unevaluated computation. You can use seq to +force its evaluation and then :print to recover its type +qsort2.hs:2:15-46> :t x +x :: GHC.Base.Unknown +qsort2.hs:2:15-46> :p x +x - 10 + + + + GHCi reminds us that this value is untyped, and instructs us to force its evaluation + + + This line forces the evaluation of x + + + Even though x has been evaluated, we cannot simply use its name to see its value! + This is a bit counterintuitive, but currently in GHCi the type of a binding is a + static property and cannot change during a session. + Thus, the binding x still has type Unknown, + even if in fact the value it is bound to already got a concrete type. + + + We can explore x using the :print + command, which does find out that x is of type Int and prints + its value accordingly. + + + The example shows the standard way to proceeed with polymorphic values in a breakpoint. In the + future, the restriction of static types will be removed and x will get a proper + type after step (2) in the example. + + + Commands + Breakpoints can be set in several ways using the :breakpoint command. Note that you can take advantage of the command abbreviation feature of GHCi and use simply :bre to save quite a few keystrokes. + + + + :breakpoint add module line + + + Adds a breakpoint at the first event found at line line in module, if any. + + + + + :breakpoint add module line column + + + Adds a breakpoint at the first event found after column column + at line line in module, if any. + + + + + :breakpoint list + + + Lists the currently set up breakpoints. + + + + + :breakpoint del num + + + Deletes the breakpoint at position num in the list of + breakpoints shown by :breakpoint list. + + + + + :breakpoint del module line + + + Dels the breakpoint at line line in module, if any. + + + + + :breakpoint del module linecol + + + Deletes the first breakpoint found after column column + at line line in module, if any. + + + + + :breakpoint stop + + + Stop the program being executed. This interrupts a debugging session + and returns to the top level. + + + + + Limitations + + + + are only available + at the scope of a breakpoint if there is a explicit type signature. + + + + + Modules compiled by GHCi under the -fdebugging + flag will perform slower: the debugging mode introduces some overhead. + Modules compiled to object code by ghc are not affected. + + + + + The <filename>.ghci</filename> file .ghcifile