
#11047: Provide call stacks in GHCi -------------------------------------+------------------------------------- Reporter: simonmar | Owner: simonmar Type: task | Status: new Priority: high | Milestone: 8.0.1 Component: GHCi | Version: 7.11 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #545, #4837 | Differential Rev(s): Phab:D1407 Wiki Page: | -------------------------------------+------------------------------------- Description changed by simonmar: Old description:
I want call stacks to be available in GHCi with no effort on the part of the user, or changes to the source code. The call stack will be available both programatically and via GHCi commands:
* `GHC.Stack.currentCallStack` returns the current call stack as `[String]`. This can be used from `error` and copied into the exception string. * `Debug.Trace.traceStack` prints out the stack anywhere. * GHCi will have a new command `:where` to print out the stack when stopped at a breakpoint
The stack trace will be the accurate (i.e. not exposing details of lazy evaluation or tail calls) and detailed (including locations of calls, not just the enclosing function definition).
= Implmeentation =
Here's how it's going to work:
* We make GHCi work with profiling (done: Phab:D1407) * We make breakpoint ticks behave like SCC annotations, and update the interpreter to implement the cost-centre-stack semantics.
= Exmaple =
Here's an example from my prototype:
{{{ g :: Int -> [Int] g n = traceStack "g" [n]
h :: Int -> Bool h n = case g n of [] -> True (x:xs) -> False
map :: (a -> b) -> [a] -> [b] map f [] = [] map f (x:xs) = f x : map f xs
k n = map h [n] }}}
{{{ [1 of 1] Compiling Main ( /home/smarlow/scratch/dbg1.hs, interpreted ) Ok, modules loaded: Main. *Main> k 1 [g Stack trace: Main.g (/home/smarlow/scratch/dbg1.hs:13:7-24) Main.g (/home/smarlow/scratch/dbg1.hs:13:1-24) Main.h (/home/smarlow/scratch/dbg1.hs:16:12-14) Main.h (/home/smarlow/scratch/dbg1.hs:(16,7)-(18,24)) Main.h (/home/smarlow/scratch/dbg1.hs:(16,1)-(18,24)) Main.map (/home/smarlow/scratch/dbg1.hs:22:16-18) Main.map (/home/smarlow/scratch/dbg1.hs:22:16-29) Main.map (/home/smarlow/scratch/dbg1.hs:(21,1)-(22,29)) Main.k (/home/smarlow/scratch/dbg1.hs:24:7-15) Main.k (/home/smarlow/scratch/dbg1.hs:24:1-15) False] *Main> }}}
We could trim some of the extra detail from the stack trace so that each function appears once; there are several choices here, currently I'm collecting and displaying the most detail.
= Deployment =
One disadvantage of this is that it requires GHCi to be built with profiling, and all the libraries have to be built with profiling too. There are two options for deployment:
1. We deploy two versions of GHCi (profiled and non-profiled), or 2. We expand on what GHCJS did, and make the interpreted code run in a separate process, thus separating the GHCi binary itself from the code being interpreted. This would allow the interpreted code to be run with the profiled RTS while GHCi itself is unprofiled.
New description: I want call stacks to be available in GHCi with no effort on the part of the user, or changes to the source code. The call stack will be available both programatically and via GHCi commands: * `GHC.Stack.currentCallStack` returns the current call stack as `[String]`. This can be used from `error` and copied into the exception string. * `Debug.Trace.traceStack` prints out the stack anywhere. * GHCi will have a new command `:where` to print out the stack when stopped at a breakpoint The stack trace will be the accurate (i.e. not exposing details of lazy evaluation or tail calls) and detailed (including locations of calls, not just the enclosing function definition). = Implementation = Here's how it's going to work: * We make GHCi work with profiling (done: Phab:D1407) * We make breakpoint ticks behave like SCC annotations, and update the interpreter to implement the cost-centre-stack semantics. = Example = Here's an example from my prototype: {{{ g :: Int -> [Int] g n = traceStack "g" [n] h :: Int -> Bool h n = case g n of [] -> True (x:xs) -> False map :: (a -> b) -> [a] -> [b] map f [] = [] map f (x:xs) = f x : map f xs k n = map h [n] }}} {{{ [1 of 1] Compiling Main ( /home/smarlow/scratch/dbg1.hs, interpreted ) Ok, modules loaded: Main. *Main> k 1 [g Stack trace: Main.g (/home/smarlow/scratch/dbg1.hs:13:7-24) Main.g (/home/smarlow/scratch/dbg1.hs:13:1-24) Main.h (/home/smarlow/scratch/dbg1.hs:16:12-14) Main.h (/home/smarlow/scratch/dbg1.hs:(16,7)-(18,24)) Main.h (/home/smarlow/scratch/dbg1.hs:(16,1)-(18,24)) Main.map (/home/smarlow/scratch/dbg1.hs:22:16-18) Main.map (/home/smarlow/scratch/dbg1.hs:22:16-29) Main.map (/home/smarlow/scratch/dbg1.hs:(21,1)-(22,29)) Main.k (/home/smarlow/scratch/dbg1.hs:24:7-15) Main.k (/home/smarlow/scratch/dbg1.hs:24:1-15) False] *Main> }}} We could trim some of the extra detail from the stack trace so that each function appears once; there are several choices here, currently I'm collecting and displaying the most detail. = Deployment = One disadvantage of this is that it requires GHCi to be built with profiling, and all the libraries have to be built with profiling too. There are two options for deployment: 1. We deploy two versions of GHCi (profiled and non-profiled), or 2. We expand on what GHCJS did, and make the interpreted code run in a separate process, thus separating the GHCi binary itself from the code being interpreted. This would allow the interpreted code to be run with the profiled RTS while GHCi itself is unprofiled. -- -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11047#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler