ghc-vis 0.1 → 0.2
raw patch · 5 files changed
+115/−20 lines, 5 filessetup-changedPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- GHC.Vis: evaluate :: String -> IO ()
- GHC.Vis: visSignal :: MVar Signal
+ GHC.Vis: clear :: IO ()
+ GHC.Vis: eval :: String -> IO ()
+ GHC.Vis: export :: String -> IO ()
+ GHC.Vis: switch :: IO ()
+ GHC.Vis: update :: IO ()
+ GHC.Vis: view :: a -> String -> IO ()
Files
- Setup.hs +15/−1
- ghc-vis.cabal +3/−2
- ghci +6/−11
- nonghci-test.hs +21/−0
- src/GHC/Vis.hs +70/−6
Setup.hs view
@@ -1,3 +1,17 @@ module Main where+ import Distribution.Simple-main = defaultMain+import Distribution.Simple.Setup+import Distribution.Simple.LocalBuildInfo++import System.FilePath++main = defaultMainWithHooks $+ simpleUserHooks { postInst = postInstHook (postInst simpleUserHooks) }++postInstHook oldHook args iflags pDesc lbi = do+ let instDataDir = datadir $ absoluteInstallDirs pDesc lbi (fromFlag $ copyDest defaultCopyFlags)+ putStrLn "To use ghc-vis you have to load its ghci file in GHCi. To do this automatically when GHCi is started run:"+ putStrLn $ "echo \":script " ++ (instDataDir </> "ghci") ++ "\" >> ~/.ghci"++ oldHook args iflags pDesc lbi
ghc-vis.cabal view
@@ -1,5 +1,5 @@ name: ghc-vis-version: 0.1+version: 0.2 license: BSD3 license-file: LICENSE category: GHC, Debug, Development@@ -18,7 +18,7 @@ To use this package add the accompanying @ghci@ file to your @.ghci@ like this: .- > echo ":script $HOME/.cabal/share/ghc-vis-0.1/ghci" >> ~/.ghci+ > echo ":script $HOME/.cabal/share/ghc-vis-0.2/ghci" >> ~/.ghci . Now you can run ghci and experiment with @ghc-vis@. Start the visualization:@@ -76,6 +76,7 @@ > > :clear data-files: ghci+Extra-source-files: nonghci-test.hs Library Exposed-modules: GHC.Vis GHC.Vis.Internal GHC.Vis.Graph GHC.Vis.Types GHC.Vis.GTK.Graph GHC.Vis.GTK.List GHC.Vis.GTK.Common
ghci view
@@ -1,12 +1,7 @@-let _put s = "System.Timeout.timeout 1000000 (Control.Concurrent.MVar.putMVar GHC.Vis.visSignal $ GHC.Vis.Types." ++ s ++ ") >> return ()"- :def vis \_ -> return $ "GHC.Vis.visualization"-:def view \x -> return $ _put $ "NewSignal (GHC.HeapView.asBox (" ++ x ++ ")) " ++ show x-:def eval \x -> return $ "GHC.Vis.evaluate \"" ++ x ++ "\"\n" ++ _put "UpdateSignal"-:def switch \_ -> return $ _put "SwitchSignal"-:def update \_ -> return $ _put "UpdateSignal"-:def clear \_ -> return $ _put "ClearSignal"-:def export \x -> return $ _put $ "ExportSignal " ++ show x---- Remove our temporary bindings--- :r+:def view \x -> return $ "GHC.Vis.view (" ++ x ++ ") " ++ show x+:def eval \x -> return $ "GHC.Vis.eval \"" ++ x ++ "\""+:def switch \_ -> return $ "GHC.Vis.switch"+:def update \_ -> return $ "GHC.Vis.update"+:def clear \_ -> return $ "GHC.Vis.clear"+:def export \x -> return $ "GHC.Vis.export " ++ show x
+ nonghci-test.hs view
@@ -0,0 +1,21 @@+import GHC.Vis++main = do+ putStrLn "Start"+ let a = "teeest"+ let b = [1..3]+ let c = b ++ b+ let d = [1..]+ putStrLn $ show $ d !! 1++ visualization+ view a "a"+ view b "b"+ view c "c"+ view d "d"++ getChar+ switch++ getChar+ putStrLn "End"
src/GHC/Vis.hs view
@@ -3,11 +3,43 @@ Copyright : (c) Dennis Felsing License : 3-Clause BSD-style Maintainer : dennis@felsin9.de++Although ghc-vis is meant to be used in GHCi it can also be used as a library+in regular Haskell programs which are run or compiled by GHC. You can run those+programs using \"runghc example.hs\" or \"ghc -threaded example.hs && ./example\".+Without the \"-threaded\"-Flag ghc-vis does not work correctly. This is an+example using ghc-vis outside of GHCi:++> import GHC.Vis+>+> main = do+> putStrLn "Start"+> let a = "teeest"+> let b = [1..3]+> let c = b ++ b+> let d = [1..]+> putStrLn $ show $ d !! 1+>+> visualization+> view a "a"+> view b "b"+> view c "c"+> view d "d"+>+> getChar+> switch+>+> getChar+> putStrLn "End" -} module GHC.Vis (- visualization,- visSignal,- evaluate+ visualization, -- TODO: Maybe rename to vis+ view,+ eval,+ switch,+ update,+ clear,+ export ) where @@ -27,7 +59,10 @@ import System.Timeout import System.Mem -import GHC.Vis.Types+import GHC.HeapView hiding (name)++import GHC.Vis.Types hiding (view)+import qualified GHC.Vis.Types as T import GHC.Vis.GTK.Common import qualified GHC.Vis.GTK.Graph as Graph import qualified GHC.Vis.GTK.List as List@@ -51,6 +86,35 @@ vr <- swapMVar visRunning True unless vr $ void $ forkIO visMainThread +-- | Add expressions with a name to the visualization window.+view :: a -> String -> IO ()+view a name = put $ NewSignal (asBox a) name++-- | Evaluate an object that is shown in the visualization. (Names start with 't')+eval :: String -> IO ()+eval t = evaluate t >> update++-- | Switch between the list view and the graph view+switch :: IO ()+switch = put SwitchSignal++-- | When an object is updated by accessing it, you have to call this to+-- refresh the visualization window. You can also click on an object to force+-- an update.+update :: IO ()+update = put UpdateSignal++-- | Clear the visualization window, removing all expressions from it.+clear :: IO ()+clear = put ClearSignal++-- | Export the current visualization view to an SVG file.+export :: String -> IO () -- TODO: Work with different file formats (svg, pdf, png)+export filename = put $ ExportSignal filename++put :: Signal -> IO ()+put s = (timeout signalTimeout $ putMVar visSignal s) >> return ()+ visMainThread :: IO () visMainThread = do initGUI@@ -115,7 +179,7 @@ \y -> if (x,n) `elem` y then return y else return $ y ++ [(x,n)]) ClearSignal -> modifyMVar_ visBoxes (\_ -> return []) UpdateSignal -> return ()- SwitchSignal -> modifyIORef visState (\s -> s {view = succN (view s)})+ SwitchSignal -> modifyIORef visState (\s -> s {T.view = succN (T.view s)}) ExportSignal f -> catch (runCorrect Graph.export List.export >>= \e -> e f) (\e -> do let err = show (e :: IOException) hPutStrLn stderr $ "Couldn't export to file \"" ++ f ++ "\": " ++ err@@ -134,6 +198,6 @@ runCorrect :: f -> f -> IO f runCorrect f1 f2 = do s <- readIORef visState- return $ case view s of+ return $ case T.view s of GraphView -> f1 ListView -> f2