Debugging with GHCi.
Lemmih
lemmih at gmail.com
Mon Apr 3 07:13:45 EDT 2006
On 4/3/06, Simon Marlow <simonmarhaskell at gmail.com> wrote:
> Lemmih wrote:
> > Greetings,
> >
> > A few days ago I wondered whether it would be possible to call GHCi
> > from interpreted byte-code. It turned out that it was, and it was even
> > fairly easy. Here's a preliminary result:
> >
> > Test.lhs:
> >
> >>import GHC.Base
> >>run :: Int -> ()
> >>run i
> >> = let b = False
> >> c x = x + a + i
> >> in breakPoint ()
> >> where d = "str"
> >> a = 10
> >>runIO :: IO String
> >>runIO = do putStr "Enter line: "
> >> line1 <- getLine
> >> breakPoint $ do
> >> putStr "Enter another line: "
> >> line2 <- getLine
> >> return (unwords [line1,line2])
> >
> >
> >
> > Output from a GHCi session:
> >
> > ghc/compiler/stage2/ghc-inplace --interactive Test.lhs -v0
> > *Main> run 100
> > Local bindings in scope:
> > a :: Int, c :: Int -> Int, b :: Bool, i :: Int, d :: [Char]
> > Test.lhs:6> (a, b, c 10, d)
> > (10,False,120,"str")
> > Test.lhs:6> :q
> > Returning to normal execution...
> > ()
> > *Main> runIO
> > Enter line: Hello
> > Local bindings in scope:
> > line1 :: String
> > Test.lhs:12> map Char.toUpper line1
> > "HELLO"
> > Test.lhs:12> :q
> > Returning to normal execution...
> > Enter another line: World
> > "Hello World"
> > *Main> :q
>
> Wow! This is quite similar to the functionality I wanted to provide for
> a debugger, but you seem to have found a clever way to implement it.
> Let me guess - 'breakpoint' is a dummy function that the compiler spots
> and replaces by a call to the GHCi front end, passing information about
> local variables?
Yes, exactly.
> What happens when the local variables have polymorphic type?
I've decided to ignore polymorphic variables for now. It's usually
possible to cast the variables to concrete types with
Data.Typeable.cast.
> For this
> case, my plan was to implement a generic object viewer, using the
> information that GHCi already knows about datatypes - if you can map
> info tables to DataCons, then it is possible to display any constructors
> in the heap. Some support from the Linker is required. Displaying a
> thunk wouldn't evaluate the thunk, it would just print something like
> '_x37', or maybe a more detailed representation of the thunk such as the
> source location of the expression it represents.
Is it possible to display such detailed representations without
compiling the standard libraries in debug mode?
> I also wanted to make it possible to insert breakpoints dynamically,
> i.e. without recompiling the code. It would involve overwriting a BCO
> in the heap with a special breakpoint object. BCOs will also need
> information about the names of free variables and a source location. In
> general, the compiler will need to track source locations through the
> middle end more than it currently does.
This sounds really difficult. Are you sure it won't result in a low
power/complexity ratio? I mean, is it really that much of a problem to
recompile the code?
> The ultimate goal is that you could click on a source line in hIDE to
> set a breakopint, run the program, and display the contents of local
> variables when the breakpoint is hit.
I agree on the overall goal. However, I don't like the idea of
line-based checkpoints, and the entry point of a program (if it even
exists) should receive no special attention over any other function.
--
Friendly,
Lemmih
More information about the Cvs-ghc
mailing list