module GHC.Vis.View.Common (
visSignal,
visRunning,
visState,
visBoxes,
visHidden,
visHeapHistory,
getHeapGraph,
inHistoryMode,
parseBoxes,
parseBoxesHeap,
evaluate
)
where
#if __GLASGOW_HASKELL__ < 706
import Prelude hiding (catch)
#endif
import Control.Concurrent
import Control.DeepSeq
import Control.Exception hiding (evaluate)
import Control.Monad.State hiding (State, fix)
import qualified Data.IntMap as M
import Data.IORef
import Data.Maybe (catMaybes)
import Data.List
import System.IO.Unsafe
import GHC.Vis.Internal
import GHC.Vis.Types
import GHC.HeapView
visSignal :: MVar Signal
visSignal = unsafePerformIO (newEmptyMVar :: IO (MVar Signal))
visRunning :: MVar Bool
visRunning = unsafePerformIO (newMVar False)
defaultDepth :: Int
defaultDepth = 100
defaultView :: ViewType
#ifdef GRAPH_VIEW
defaultView = GraphView
#else
defaultView = ListView
#endif
visState :: IORef State
visState = unsafePerformIO $ newIORef $ State (0, 0) defaultView 1 (0, 0) False False defaultDepth
visBoxes :: MVar [NamedBox]
visBoxes = unsafePerformIO (newMVar [] :: IO (MVar [NamedBox]))
visHidden :: MVar [Box]
visHidden = unsafePerformIO (newMVar [] :: IO (MVar [Box]))
visHeapHistory :: MVar (Int, [(HeapGraph Identifier, [(Identifier, HeapGraphIndex)])])
visHeapHistory = unsafePerformIO (newMVar (0, [(HeapGraph M.empty, [])]) :: IO (MVar (Int, [(HeapGraph Identifier, [(Identifier, HeapGraphIndex)])])))
getHeapGraph :: IO (HeapGraph Identifier, [(Identifier, HeapGraphIndex)])
getHeapGraph = do
(pos, xs) <- readMVar visHeapHistory
return $ xs !! pos
inHistoryMode :: IO Bool
inHistoryMode = liftM ((> 0) . fst) $ readMVar visHeapHistory
evaluate :: String -> IO ()
evaluate identifier = do (_,HeapGraph m) <- printAll
(show (M.map go m) `deepseq` return ()) `catch`
\(e :: SomeException) -> putStrLn $ "Caught exception while evaluating: " ++ show e
where go hge@(HeapGraphEntry (Box a) _ _ n) | n == identifier = seq a hge
| otherwise = hge
parseBoxes :: IO [[VisObject]]
parseBoxes = generalParseBoxes evalState
parseBoxesHeap :: IO ([[VisObject]], PState)
parseBoxesHeap = generalParseBoxes runState
generalParseBoxes :: (PrintState [[VisObject]] -> PState -> b) -> IO b
generalParseBoxes f = do
(hg@(HeapGraph m), starts) <- getHeapGraph
let bindings = boundMultipleTimes hg $ map snd starts
let g i = do
r <- parseClosure i
return $ simplify r
return $ f (mapM (g . snd) starts) $ PState 1 1 1 bindings $ HeapGraph $ M.map (\hge -> hge{hgeData = ""}) m
boundMultipleTimes :: HeapGraph a -> [HeapGraphIndex] -> [HeapGraphIndex]
boundMultipleTimes (HeapGraph m) roots = map head $ filter (not.null) $ map tail $ group $ sort $
roots ++ concatMap (catMaybes . allPtrs . hgeClosure) (M.elems m)
simplify :: [VisObject] -> [VisObject]
simplify [] = []
simplify [Named a bs] = [Named a $ simplify bs]
simplify [a] = [a]
simplify (Unnamed a : Unnamed b : xs) = simplify $ Unnamed (a ++ b) : xs
simplify (Named a bs : xs) = Named a (simplify bs) : simplify xs
simplify (a:xs) = a : simplify xs
printAll :: IO (String, HeapGraph String)
printAll = do
(t, PState{heapGraph = h}) <- parseBoxesHeap
return (show t, h)