cool stuff!-)

btw, the basic breakpoint functionality could indeed be provided
as a compiler/IDE transformation, but calling out to GHCi makes
a lot more sense: you can do calculations, and you can decide
which parts of the local info to browse (so you don't get overwhelmed with bindings if you happen to be in OpenGL.*
or the like). perhaps a ":browse current"?

here's the kind of home-brewn debugging stuff I've been using
(strangely, it hadn't occured to me that the IDE could take on the
task of inferring and inserting the local bindings; and it would all be nicer without needing Show/Read, eg, the ghci route could presumably also handle functions, or change function parameters from within a guard, where most trace calls tend to end up?-).

cheers,
claus
----------------------------------------
import Debug.Trace
import System.IO.Unsafe

breakpoint msg locals cont = trace ("breakpoint: "++msg) $ trace ("locals: "++show locals) $ case readsPrec 0 (unsafePerformIO getLine) of [(locals,"")] -> trace ("new values: "++show locals++"\n") $ cont locals
   _ -> cont locals
loop 0 x = x
loop i x = breakpoint "loop" (i,x) $ \(i,x)->
          loop (i-1) (x*2)

test _ = print $ loop 3 1

*Main> test ()
breakpoint: loop
locals: (3,1)

breakpoint: loop
locals: (2,2)

breakpoint: loop
locals: (1,4)

8
*Main> test ()
breakpoint: loop
locals: (3,1)
(0,0)
new values: (0,0)

breakpoint: loop
locals: (-1,0)

breakpoint: loop
locals: (-2,0)
(2,4)
new values: (2,4)

breakpoint: loop
locals: (1,8)

16


----- Original Message ----- From: "Simon Marlow" <[EMAIL PROTECTED]>
To: "Lemmih" <[EMAIL PROTECTED]>
Cc: <[EMAIL PROTECTED]>
Sent: Monday, April 03, 2006 10:04 AM
Subject: Re: Debugging with GHCi.


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?

What happens when the local variables have polymorphic type? 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.

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.

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.

Cheers,
Simon
_______________________________________________
Cvs-ghc mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/cvs-ghc
_______________________________________________
Cvs-ghc mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/cvs-ghc

Reply via email to