ghc-dump-util 0.1.2.0 → 0.2.1.0
raw patch · 4 files changed
+287/−82 lines, 4 filesdep +ansi-terminaldep +luciddep +prettyprinterdep −ansi-wl-pprintdep ~bytestringdep ~ghc-dump-corePVP ok
version bump matches the API change (PVP)
Dependencies added: ansi-terminal, lucid, prettyprinter, prettyprinter-ansi-terminal
Dependencies removed: ansi-wl-pprint
Dependency ranges changed: bytestring, ghc-dump-core
API changes (from Hackage documentation)
- GhcDump.Pretty: instance Text.PrettyPrint.ANSI.Leijen.Internal.Pretty Data.Text.Internal.Text
- GhcDump.Pretty: instance Text.PrettyPrint.ANSI.Leijen.Internal.Pretty GhcDump.Ast.AltCon
- GhcDump.Pretty: instance Text.PrettyPrint.ANSI.Leijen.Internal.Pretty GhcDump.Ast.Binder
- GhcDump.Pretty: instance Text.PrettyPrint.ANSI.Leijen.Internal.Pretty GhcDump.Ast.BinderId
- GhcDump.Pretty: instance Text.PrettyPrint.ANSI.Leijen.Internal.Pretty GhcDump.Ast.CoreStats
- GhcDump.Pretty: instance Text.PrettyPrint.ANSI.Leijen.Internal.Pretty GhcDump.Ast.Expr
- GhcDump.Pretty: instance Text.PrettyPrint.ANSI.Leijen.Internal.Pretty GhcDump.Ast.ExternalName
- GhcDump.Pretty: instance Text.PrettyPrint.ANSI.Leijen.Internal.Pretty GhcDump.Ast.IdDetails
- GhcDump.Pretty: instance Text.PrettyPrint.ANSI.Leijen.Internal.Pretty GhcDump.Ast.Lit
- GhcDump.Pretty: instance Text.PrettyPrint.ANSI.Leijen.Internal.Pretty GhcDump.Ast.Module
- GhcDump.Pretty: instance Text.PrettyPrint.ANSI.Leijen.Internal.Pretty GhcDump.Ast.ModuleName
- GhcDump.Pretty: instance Text.PrettyPrint.ANSI.Leijen.Internal.Pretty GhcDump.Ast.OccInfo
- GhcDump.Pretty: instance Text.PrettyPrint.ANSI.Leijen.Internal.Pretty GhcDump.Ast.TopBinding
- GhcDump.Pretty: instance Text.PrettyPrint.ANSI.Leijen.Internal.Pretty GhcDump.Ast.TyCon
- GhcDump.Pretty: instance Text.PrettyPrint.ANSI.Leijen.Internal.Pretty GhcDump.Ast.Type
- GhcDump.Pretty: instance Text.PrettyPrint.ANSI.Leijen.Internal.Pretty GhcDump.Ast.Unique
+ GhcDump.Pretty: (<$$>) :: Doc ann -> Doc ann -> Doc ann
+ GhcDump.Pretty: instance Prettyprinter.Internal.Pretty GhcDump.Ast.AltCon
+ GhcDump.Pretty: instance Prettyprinter.Internal.Pretty GhcDump.Ast.Binder
+ GhcDump.Pretty: instance Prettyprinter.Internal.Pretty GhcDump.Ast.BinderId
+ GhcDump.Pretty: instance Prettyprinter.Internal.Pretty GhcDump.Ast.CoreStats
+ GhcDump.Pretty: instance Prettyprinter.Internal.Pretty GhcDump.Ast.Expr
+ GhcDump.Pretty: instance Prettyprinter.Internal.Pretty GhcDump.Ast.ExternalName
+ GhcDump.Pretty: instance Prettyprinter.Internal.Pretty GhcDump.Ast.IdDetails
+ GhcDump.Pretty: instance Prettyprinter.Internal.Pretty GhcDump.Ast.Lit
+ GhcDump.Pretty: instance Prettyprinter.Internal.Pretty GhcDump.Ast.Module
+ GhcDump.Pretty: instance Prettyprinter.Internal.Pretty GhcDump.Ast.ModuleName
+ GhcDump.Pretty: instance Prettyprinter.Internal.Pretty GhcDump.Ast.OccInfo
+ GhcDump.Pretty: instance Prettyprinter.Internal.Pretty GhcDump.Ast.TopBinding
+ GhcDump.Pretty: instance Prettyprinter.Internal.Pretty GhcDump.Ast.TyCon
+ GhcDump.Pretty: instance Prettyprinter.Internal.Pretty GhcDump.Ast.Type
+ GhcDump.Pretty: instance Prettyprinter.Internal.Pretty GhcDump.Ast.Unique
+ GhcDump.Pretty: pprTick :: Tick -> Doc ann
+ GhcDump.ToHtml: exprToHtml :: Expr -> Html ()
+ GhcDump.ToHtml: topBindingsToHtml :: [TopBinding] -> Html ()
- GhcDump.Pretty: comment :: Doc -> Doc
+ GhcDump.Pretty: comment :: Doc ann -> Doc ann
- GhcDump.Pretty: dcolon :: Doc
+ GhcDump.Pretty: dcolon :: Doc ann
- GhcDump.Pretty: hang' :: Doc -> Int -> Doc -> Doc
+ GhcDump.Pretty: hang' :: Doc ann -> Int -> Doc ann -> Doc ann
- GhcDump.Pretty: maybeParens :: Bool -> Doc -> Doc
+ GhcDump.Pretty: maybeParens :: Bool -> Doc ann -> Doc ann
- GhcDump.Pretty: ppWhen :: Bool -> Doc -> Doc
+ GhcDump.Pretty: ppWhen :: Bool -> Doc ann -> Doc ann
- GhcDump.Pretty: pprBinder :: PrettyOpts -> Binder -> Doc
+ GhcDump.Pretty: pprBinder :: PrettyOpts -> Binder -> Doc ann
- GhcDump.Pretty: pprBinding :: PrettyOpts -> Binder -> Expr -> Doc
+ GhcDump.Pretty: pprBinding :: PrettyOpts -> Binder -> Expr -> Doc ann
- GhcDump.Pretty: pprExpr :: PrettyOpts -> Expr -> Doc
+ GhcDump.Pretty: pprExpr :: PrettyOpts -> Expr -> Doc ann
- GhcDump.Pretty: pprExpr' :: PrettyOpts -> Bool -> Expr -> Doc
+ GhcDump.Pretty: pprExpr' :: PrettyOpts -> Bool -> Expr -> Doc ann
- GhcDump.Pretty: pprIdInfo :: PrettyOpts -> IdInfo Binder Binder -> IdDetails -> Doc
+ GhcDump.Pretty: pprIdInfo :: PrettyOpts -> IdInfo Binder Binder -> IdDetails -> Doc ann
- GhcDump.Pretty: pprModule :: PrettyOpts -> Module -> Doc
+ GhcDump.Pretty: pprModule :: PrettyOpts -> Module -> Doc ann
- GhcDump.Pretty: pprRational :: Rational -> Doc
+ GhcDump.Pretty: pprRational :: Rational -> Doc ann
- GhcDump.Pretty: pprTopBinding :: PrettyOpts -> TopBinding -> Doc
+ GhcDump.Pretty: pprTopBinding :: PrettyOpts -> TopBinding -> Doc ann
- GhcDump.Pretty: pprType :: PrettyOpts -> Type -> Doc
+ GhcDump.Pretty: pprType :: PrettyOpts -> Type -> Doc ann
- GhcDump.Pretty: pprType' :: PrettyOpts -> TyPrec -> Type -> Doc
+ GhcDump.Pretty: pprType' :: PrettyOpts -> TyPrec -> Type -> Doc ann
- GhcDump.Pretty: pprTypeSig :: PrettyOpts -> Binder -> Doc
+ GhcDump.Pretty: pprTypeSig :: PrettyOpts -> Binder -> Doc ann
- GhcDump.Pretty: pprUnfolding :: PrettyOpts -> Unfolding Binder Binder -> Doc
+ GhcDump.Pretty: pprUnfolding :: PrettyOpts -> Unfolding Binder Binder -> Doc ann
- GhcDump.Pretty: pretty :: Pretty a => a -> Doc
+ GhcDump.Pretty: pretty :: Pretty a => a -> Doc ann
- GhcDump.Pretty: prettyList :: Pretty a => [a] -> Doc
+ GhcDump.Pretty: prettyList :: Pretty a => [a] -> Doc ann
- GhcDump.Pretty: smallRArrow :: Doc
+ GhcDump.Pretty: smallRArrow :: Doc ann
Files
- Main.hs +56/−30
- ghc-dump-util.cabal +25/−10
- src/GhcDump/Pretty.hs +46/−42
- src/GhcDump/ToHtml.hs +160/−0
Main.hs view
@@ -3,35 +3,40 @@ import Control.Monad import Data.Maybe import Data.List (sortBy)-import Data.Monoid import Data.Ord+import System.IO (stdout) import Options.Applicative-import Text.PrettyPrint.ANSI.Leijen hiding ((<$>), (<>))-import qualified Text.PrettyPrint.ANSI.Leijen as PP+import Prettyprinter as PP+import Prettyprinter.Render.Terminal as PP+import qualified System.Console.ANSI import Text.Regex.TDFA import Text.Regex.TDFA.Common (Regex) import Text.Regex.TDFA.Text () +import GhcDump.ToHtml import GhcDump.Pretty import GhcDump.Util import GhcDump.Ast -data Column a = Col { colWidth :: Int, colHeader :: String, colGet :: (a -> Doc) }+data Column a = Col { colWidth :: Int+ , colHeader :: String+ , colGet :: a -> Doc AnsiStyle+ } type Table a = [Column a] -renderTable :: forall a. Table a -> [a] -> Doc+renderTable :: forall a. Table a -> [a] -> Doc AnsiStyle renderTable cols xs =- row (PP.bold . text . colHeader)+ row (PP.annotate PP.bold . pretty . colHeader) <$$> vcat [ row (flip colGet x) | x <- xs ] where- row :: (Column a -> Doc) -> Doc+ row :: (Column a -> Doc AnsiStyle) -> Doc AnsiStyle row toCell = go cols where- go :: [Column a] -> Doc- go [] = PP.empty+ go :: [Column a] -> Doc AnsiStyle+ go [] = mempty go [col] = align $ toCell col go (col : rest) = fillBreak (colWidth col) (align $ toCell col) PP.<+> go rest @@ -50,6 +55,14 @@ nameMatches :: Binder -> Bool nameMatches b = matchTest re (binderUniqueName b) +renderIOTerm :: PP.LayoutOptions -> Doc AnsiStyle -> IO ()+renderIOTerm layoutOpts doc = do+ supportsANSI <- System.Console.ANSI.hSupportsANSI System.IO.stdout+ let doc' = if supportsANSI+ then doc+ else PP.unAnnotate doc+ PP.renderIO stdout $ PP.layoutPretty layoutOpts doc'+ modes :: Parser (IO ()) modes = subparser $ mode "show" showMode (progDesc "print Core")@@ -69,6 +82,23 @@ where makeRegexM' = makeRegexM :: String -> ReadM Regex + bindingsSort :: Parser (Module -> Module)+ bindingsSort =+ option (str >>= readSortField)+ (long "sort" <> short 's' <> value id+ <> help "Sort by (accepted values: none, terms, types, coercions, type)")+ where+ readSortField "none" = return $ id+ readSortField "terms" = return $ onBinds $ sortBy (flip $ comparing $ csTerms . getStats)+ readSortField "types" = return $ onBinds $ sortBy (flip $ comparing $ csTypes . getStats)+ readSortField "coercions" = return $ onBinds $ sortBy (flip $ comparing $ csCoercions . getStats)+ readSortField "type" = return $ onBinds $ sortBy (comparing $ binderType . unBndr . getBinder)+ readSortField f = fail $ "unknown sort field "++f++ onBinds :: ([(Binder, CoreStats, Expr)] -> [(Binder, CoreStats, Expr)])+ -> Module -> Module+ onBinds f mod = mod { moduleTopBindings = [RecTopBinding $ f $ moduleBindings mod] }+ prettyOpts :: Parser PrettyOpts prettyOpts = PrettyOpts@@ -78,35 +108,31 @@ <*> switch (short 'U' <> long "show-unfoldings" <> help "Show unfolding templates") showMode =- run <$> filterCond <*> prettyOpts <*> dumpFile+ run <$> filterCond <*> bindingsSort <*> prettyOpts <*> html <*> dumpFile where- run filterFn opts fname = do- dump <- filterFn <$> GhcDump.Util.readDump fname- print $ pprModule opts dump+ html = switch (short 'H' <> long "html" <> help "Render to HTML")+ run filterFn sortBindings opts html fname = do+ dump <- sortBindings . filterFn <$> GhcDump.Util.readDump fname+ if html+ then writeFile "out.html" $ show $ topBindingsToHtml (moduleTopBindings dump)+ else renderIOTerm PP.defaultLayoutOptions $ pprModule opts dump listBindingsMode =- run <$> filterCond <*> sortField <*> prettyOpts <*> dumpFile+ run <$> filterCond <*> bindingsSort <*> prettyOpts <*> dumpFile where- sortField =- option (str >>= readSortField)- (long "sort" <> short 's' <> value id- <> help "Sort by (accepted values: terms, types, coercions, type)")- where- readSortField "terms" = return $ sortBy (flip $ comparing $ csTerms . getStats)- readSortField "types" = return $ sortBy (flip $ comparing $ csTypes . getStats)- readSortField "coercions" = return $ sortBy (flip $ comparing $ csCoercions . getStats)- readSortField "type" = return $ sortBy (comparing $ binderType . unBndr . getBinder)- readSortField f = fail $ "unknown sort field "++f- run filterFn sortBindings opts fname = do- dump <- filterFn <$> GhcDump.Util.readDump fname- let table = [ Col 20 "Name" (pprBinder opts . getBinder)+ dump <- sortBindings . filterFn <$> GhcDump.Util.readDump fname+ let table = [ Col 30 "Name" (pprBinder opts . getBinder) , Col 6 "Terms" (pretty . csTerms . getStats) , Col 6 "Types" (pretty . csTypes . getStats) , Col 6 "Coerc." (pretty . csCoercions . getStats)- , Col 300 "Type" (pprType opts . binderType . unBndr . getBinder)+ , Col 3000 "Type" (pprType opts . binderType . unBndr . getBinder) ]- print $ renderTable table (sortBindings $ moduleBindings dump)+ let layoutOpts = PP.defaultLayoutOptions { layoutPageWidth = Unbounded }+ renderIOTerm layoutOpts $ vcat+ [ pretty (modulePhase dump)+ , renderTable table (moduleBindings dump)+ ] summarizeMode = run <$> some dumpFile@@ -116,7 +142,7 @@ return (fname, mod)) fnames let totalSize :: Module -> CoreStats totalSize = foldMap getStats . moduleBindings- let table = [ Col 35 "Name" (text . fst)+ let table = [ Col 35 "Name" (pretty . fst) , Col 8 "Terms" (pretty . csTerms . totalSize . snd) , Col 8 "Types" (pretty . csTypes . totalSize . snd) , Col 8 "Coerc." (pretty . csCoercions . totalSize . snd)
ghc-dump-util.cabal view
@@ -1,5 +1,6 @@+cabal-version: 3.0 name: ghc-dump-util-version: 0.1.2.0+version: 0.2.1.0 synopsis: Handy tools for working with ghc-dump dumps description: @ghc-dump@ is a library, GHC plugin, and set of tools for recording and@@ -11,39 +12,53 @@ This package provides the AST and compiler plugin. See the @ghc-dump-util@ package for a useful command-line tool for working with dumps produced by this plugin.-license: BSD3+license: BSD-3-Clause license-file: LICENSE author: Ben Gamari maintainer: ben@well-typed.com copyright: (c) 2017 Ben Gamari category: Development build-type: Simple-tested-with: GHC==7.10.3, GHC==8.0.2, GHC==8.2.2, GHC==8.4.4, GHC==8.6.5, GHC==8.8.3, GHC==8.10.1-cabal-version: >=1.10+tested-with: GHC==7.10.3,+ GHC==8.0.2,+ GHC==8.2.2,+ GHC==8.4.4,+ GHC==8.6.5,+ GHC==8.8.3,+ GHC==8.10.4,+ GHC==9.0.1,+ GHC==9.2.1, source-repository head type: git location: https://github.com/bgamari/ghc-dump library- exposed-modules: GhcDump.Repl, GhcDump.Util, GhcDump.Pretty, GhcDump.Reconstruct+ exposed-modules: GhcDump.Repl,+ GhcDump.Util,+ GhcDump.Pretty,+ GhcDump.Reconstruct,+ GhcDump.ToHtml hs-source-dirs: src build-depends: base < 5.0,- ghc-dump-core >=0.1 && <0.2,- bytestring >=0.10 && <0.11,+ ghc-dump-core >=0.2 && <0.3,+ bytestring >=0.10 && <0.12, unordered-containers >= 0.2, hashable >= 1.2,+ lucid, text >= 1.0,- ansi-wl-pprint >= 0.6,+ prettyprinter, serialise >=0.2 && <0.3 default-language: Haskell2010 executable ghc-dump main-is: Main.hs build-depends: base < 5.0,- ghc-dump-core >=0.1 && <0.2,+ ghc-dump-core, ghc-dump-util,- ansi-wl-pprint >= 0.6,+ ansi-terminal,+ prettyprinter,+ prettyprinter-ansi-terminal, regex-tdfa >= 1.3.1.0, optparse-applicative >= 0.13 default-language: Haskell2010
src/GhcDump/Pretty.hs view
@@ -14,8 +14,11 @@ import Data.Ratio import qualified Data.Text as T import qualified Data.ByteString.Char8 as BS-import Text.PrettyPrint.ANSI.Leijen+import Prettyprinter +(<$$>) :: Doc ann -> Doc ann -> Doc ann+a <$$> b = vcat [a,b]+ data PrettyOpts = PrettyOpts { showUniques :: Bool , showIdInfo :: Bool , showLetTypes :: Bool@@ -29,19 +32,15 @@ , showUnfoldings = False } --- orphan-instance Pretty T.Text where- pretty = text . T.unpack- instance Pretty ExternalName where- pretty n@ExternalName{} = pretty (externalModuleName n) <> "." <> text (T.unpack $ externalName n)+ pretty n@ExternalName{} = pretty (externalModuleName n) <> "." <> pretty (T.unpack $ externalName n) pretty ForeignCall = "<foreign>" instance Pretty ModuleName where- pretty = text . T.unpack . getModuleName+ pretty = pretty . T.unpack . getModuleName instance Pretty Unique where- pretty = text . show+ pretty = pretty . show instance Pretty BinderId where pretty (BinderId b) = pretty b@@ -49,20 +48,20 @@ instance Pretty Binder where pretty = pprBinder defaultPrettyOpts -pprBinder :: PrettyOpts -> Binder -> Doc+pprBinder :: PrettyOpts -> Binder -> Doc ann pprBinder opts b | showUniques opts = pretty $ binderUniqueName b | otherwise = pretty $ binderName $ unBndr b instance Pretty TyCon where- pretty (TyCon t _) = text $ T.unpack t+ pretty (TyCon t _) = pretty $ T.unpack t -pprRational :: Rational -> Doc+pprRational :: Rational -> Doc ann pprRational r = pretty (numerator r) <> "/" <> pretty (denominator r) instance Pretty Lit where- pretty (MachChar x) = "'" <> char x <> "'#"- pretty (MachStr x) = "\"" <> text (BS.unpack x) <> "\"#"+ pretty (MachChar x) = "'" <> pretty x <> "'#"+ pretty (MachStr x) = "\"" <> pretty (BS.unpack x) <> "\"#" pretty MachNullAddr = "nullAddr#" pretty (MachInt x) = pretty x <> "#" pretty (MachInt64 x) = pretty x <> "#"@@ -76,16 +75,16 @@ instance Pretty CoreStats where pretty c = "Core Size"- <>braces (hsep [ "terms="<>int (csTerms c)- , "types="<>int (csTypes c)- , "cos="<>int (csCoercions c)- , "vbinds="<>int (csValBinds c)- , "jbinds="<>int (csJoinBinds c)+ <>braces (hsep [ "terms="<>pretty (csTerms c)+ , "types="<>pretty (csTypes c)+ , "cos="<>pretty (csCoercions c)+ , "vbinds="<>pretty (csValBinds c)+ , "jbinds="<>pretty (csJoinBinds c) ]) -pprIdInfo :: PrettyOpts -> IdInfo Binder Binder -> IdDetails -> Doc+pprIdInfo :: PrettyOpts -> IdInfo Binder Binder -> IdDetails -> Doc ann pprIdInfo opts i d- | not $ showIdInfo opts = empty+ | not $ showIdInfo opts = mempty | otherwise = comment $ "IdInfo:" <+> align doc where doc = sep $ punctuate ", "@@ -99,7 +98,7 @@ , "unfolding=" <> pprUnfolding opts (idiUnfolding i) ] ++ (if idiIsOneShot i then ["one-shot"] else []) -pprUnfolding :: PrettyOpts -> Unfolding Binder Binder -> Doc+pprUnfolding :: PrettyOpts -> Unfolding Binder Binder -> Doc ann pprUnfolding _ NoUnfolding = "NoUnfolding" pprUnfolding _ BootUnfolding = "BootUnfolding" pprUnfolding _ OtherCon{} = "OtherCon"@@ -122,7 +121,7 @@ if strong then "Strong Loopbrk" else "Weak Loopbrk" instance Pretty IdDetails where- pretty = text . show+ pretty = pretty . show data TyPrec -- See Note [Precedence in types] in TyCoRep.hs = TopPrec -- No parens@@ -131,10 +130,10 @@ | TyConPrec -- Tycon args; no parens for atomic deriving( Eq, Ord ) -pprType :: PrettyOpts -> Type -> Doc+pprType :: PrettyOpts -> Type -> Doc ann pprType opts = pprType' opts TopPrec -pprType' :: PrettyOpts -> TyPrec -> Type -> Doc+pprType' :: PrettyOpts -> TyPrec -> Type -> Doc ann pprType' opts _ (VarTy b) = pprBinder opts b pprType' opts p t@(FunTy _ _) = maybeParens (p >= FunPrec) $ sep $ punctuate " ->" (map (pprType' opts FunPrec) (splitFunTys t)) pprType' opts p (TyConApp tc []) = pretty tc@@ -146,23 +145,23 @@ pprType' opts _ LitTy = "LIT" pprType' opts _ CoercionTy = "Co" -maybeParens :: Bool -> Doc -> Doc+maybeParens :: Bool -> Doc ann -> Doc ann maybeParens True = parens maybeParens False = id instance Pretty Type where pretty = pprType defaultPrettyOpts -pprExpr :: PrettyOpts -> Expr -> Doc+pprExpr :: PrettyOpts -> Expr -> Doc ann pprExpr opts = pprExpr' opts False -pprExpr' :: PrettyOpts -> Bool -> Expr -> Doc+pprExpr' :: PrettyOpts -> Bool -> Expr -> Doc ann pprExpr' opts _parens (EVar v) = pprBinder opts v pprExpr' opts _parens (EVarGlobal v) = pretty v pprExpr' opts _parens (ELit l) = pretty l pprExpr' opts parens e@(EApp{}) = let (x, ys) = collectArgs e in maybeParens parens $ hang' (pprExpr' opts True x) 2 (sep $ map pprArg ys)- where pprArg (EType t) = char '@' <> pprType' opts TyConPrec t+ where pprArg (EType t) = pretty '@' <> pprType' opts TyConPrec t pprArg x = pprExpr' opts True x pprExpr' opts parens x@(ETyLam _ _) = let (bs, x') = collectTyBinders x in maybeParens parens@@ -170,7 +169,7 @@ pprExpr' opts parens x@(ELam _ _) = let (bs, x') = collectBinders x in maybeParens parens $ hang' ("λ" <+> sep (map (pprBinder opts) bs) <+> smallRArrow) 2 (pprExpr' opts False x')-pprExpr' opts parens (ELet xs y) = maybeParens parens $ "let" <+> (align $ vcat $ map (uncurry (pprBinding opts)) xs)+pprExpr' opts parens (ELet xs y) = maybeParens parens $ "let" <> (align $ vcat $ map (uncurry (pprBinding opts)) xs) <$$> "in" <+> align (pprExpr' opts False y) where pprBind (b, rhs) = pprBinder opts b <+> equals <+> align (pprExpr' opts False rhs) pprExpr' opts parens (ECase x b alts) = maybeParens parens@@ -180,18 +179,23 @@ , "}" ] where pprAlt (Alt con bndrs rhs) = hang' (hsep (pretty con : map (pprBinder opts) bndrs) <+> smallRArrow) 2 (pprExpr' opts False rhs)+pprExpr' opts parens (ETick tick e) = maybeParens parens+ $ sep [ "<" <> pprTick tick <> ">", pprExpr' opts parens e ] pprExpr' opts parens (EType t) = maybeParens parens $ "TYPE:" <+> pprType opts t pprExpr' opts parens ECoercion = "CO" +pprTick :: Tick -> Doc ann+pprTick (SourceNote n) = "srcnote"+ instance Pretty AltCon where- pretty (AltDataCon t) = text $ T.unpack t+ pretty (AltDataCon t) = pretty $ T.unpack t pretty (AltLit l) = pretty l- pretty AltDefault = text "DEFAULT"+ pretty AltDefault = "DEFAULT" instance Pretty Expr where pretty = pprExpr defaultPrettyOpts -pprTopBinding :: PrettyOpts -> TopBinding -> Doc+pprTopBinding :: PrettyOpts -> TopBinding -> Doc ann pprTopBinding opts tb = case tb of NonRecTopBinding b s rhs -> pprTopBind (b,s,rhs)@@ -204,11 +208,11 @@ <$$> hang' (pprBinder opts b <+> equals) 2 (pprExpr opts rhs) <> line -pprTypeSig :: PrettyOpts -> Binder -> Doc+pprTypeSig :: PrettyOpts -> Binder -> Doc ann pprTypeSig opts b@(Bndr b') = pprBinder opts b <+> dcolon <+> align (pprType opts (binderType b')) -pprBinding :: PrettyOpts -> Binder -> Expr -> Doc+pprBinding :: PrettyOpts -> Binder -> Expr -> Doc ann pprBinding opts b@(Bndr b'@Binder{}) rhs = ppWhen (showLetTypes opts) (pprTypeSig opts b) <$$> pprIdInfo opts (binderIdInfo b') (binderIdDetails b')@@ -220,27 +224,27 @@ instance Pretty TopBinding where pretty = pprTopBinding defaultPrettyOpts -pprModule :: PrettyOpts -> Module -> Doc+pprModule :: PrettyOpts -> Module -> Doc ann pprModule opts m = comment (pretty $ modulePhase m)- <$$> text "module" <+> pretty (moduleName m) <+> "where" <> line+ <$$> "module" <+> pretty (moduleName m) <+> "where" <> line <$$> vsep (map (pprTopBinding opts) (moduleTopBindings m)) instance Pretty Module where pretty = pprModule defaultPrettyOpts -comment :: Doc -> Doc+comment :: Doc ann -> Doc ann comment x = "{-" <+> x <+> "-}" -dcolon :: Doc+dcolon :: Doc ann dcolon = "::" -smallRArrow :: Doc+smallRArrow :: Doc ann smallRArrow = "→" -hang' :: Doc -> Int -> Doc -> Doc+hang' :: Doc ann -> Int -> Doc ann -> Doc ann hang' d1 n d2 = hang n $ sep [d1, d2] -ppWhen :: Bool -> Doc -> Doc+ppWhen :: Bool -> Doc ann -> Doc ann ppWhen True x = x-ppWhen False _ = empty+ppWhen False _ = mempty
+ src/GhcDump/ToHtml.hs view
@@ -0,0 +1,160 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}++module GhcDump.ToHtml (topBindingsToHtml, exprToHtml) where++import Data.List+import Lucid+import GhcDump.Ast+import GhcDump.Util+import qualified Data.ByteString.Char8 as BS+import qualified Data.Text as T+import Data.Monoid ((<>))+import Prelude++topBindingsToHtml :: [TopBinding] -> Html ()+topBindingsToHtml = foldMap topBindingToHtml++topBindingToHtml :: TopBinding -> Html ()+topBindingToHtml = mapM_ (\(bndr, _, rhs) -> bindingToHtml bndr rhs) . topBindings++divClass :: T.Text -> Html a -> Html a+divClass cls contents = div_ [class_ cls] contents++spanClass :: T.Text -> Html a -> Html a+spanClass cls contents = span_ [class_ cls] contents++keyword :: Html a -> Html a+keyword = divClass "kw"++lambda :: Html ()+lambda = "λ "++rarrow :: Html ()+rarrow = " → "++spaced :: Html () -> Html ()+spaced x = " " <> x <> " "++exprToHtml :: Expr -> Html ()+exprToHtml (EVar v) = bndrToHtml v+exprToHtml (EVarGlobal v) = externalNameToHtml v+exprToHtml (ELit lit) = litToHtml lit+exprToHtml e@(EApp _ _)+ | (x, ys) <- collectArgs e+ = divClass "app" $ do+ exprToHtml x+ " "+ mconcat $ intersperse " " $ map exprToHtml ys+exprToHtml e@(ETyLam _ _)+ | (bndrs, rhs) <- collectTyBinders e+ = divClass "lam" $ do+ lambda+ bndrsToHtml bndrs+ rarrow+ divClass "rhs" $ exprToHtml rhs+exprToHtml e@(ELam _ _)+ | (bndrs, rhs) <- collectBinders e+ = divClass "lam" $ do+ lambda+ bndrsToHtml bndrs+ rarrow+ divClass "rhs" $ exprToHtml rhs+exprToHtml (ELet bs e) = divClass "let" $ do+ keyword "let "+ divClass "binds" $ foldMap (uncurry bindingToHtml) bs+ keyword " in "+ divClass "body" $ exprToHtml e+exprToHtml (ECase scrut b alts) = divClass "case" $ do+ keyword "case "+ divClass "scrut" $ exprToHtml scrut+ keyword " of "+ divClass "alts" $ mapM_ altToHtml alts+exprToHtml (ETick tick e) = divClass "tick" $ do+ keyword "tick "+ exprToHtml e+exprToHtml (EType ty) = divClass "type" $ typeToHtml ty+exprToHtml (ECoercion) = "$co"++bndrToHtml :: Binder -> Html ()+bndrToHtml bndr =+ sigil <> divClass "bndr" (toHtml (binderUniqueName bndr))+ where+ sigil+ | isTyBinder bndr = "@"+ | otherwise = mempty++bndrsToHtml :: [Binder] -> Html ()+bndrsToHtml bndrs =+ divClass "bndrs" $ foldMap (spaced . bndrToHtml) bndrs++typeSigToHtml :: Binder -> Type -> Html ()+typeSigToHtml bndr ty = divClass "sig" $ do+ bndrToHtml bndr+ " :: "+ typeToHtml ty++bindingToHtml :: Binder -> Expr -> Html ()+bindingToHtml bndr rhs = divClass "bind" $ do+ bndrToHtml bndr+ " = "+ divClass "rhs" $ exprToHtml rhs++moduleNameToHtml :: ModuleName -> Html ()+moduleNameToHtml m =+ divClass "mod" $ toHtml $ getModuleName m++externalNameToHtml :: ExternalName -> Html ()+externalNameToHtml (ExternalName mod nam _) =+ divClass "ext-name" $ moduleNameToHtml mod <> "." <> toHtml nam+externalNameToHtml (ForeignCall) =+ "$foreign-call"++altToHtml :: Alt -> Html ()+altToHtml Alt{..} = div_ $ do+ case altCon of+ AltDataCon dc -> divClass "datacon" $ toHtml dc+ AltLit lit -> litToHtml lit+ AltDefault -> divClass "kw" "DEFAULT"+ bndrsToHtml altBinders+ rarrow+ divClass "rhs" $ exprToHtml altRHS++typeToHtml :: Type -> Html ()+typeToHtml (VarTy v) = bndrToHtml v+typeToHtml t@(FunTy _ _)+ | ts <- splitFunTys t+ = divClass "funty" $ mconcat $ intersperse rarrow $ map typeToHtml ts+typeToHtml (TyConApp tc tys)+ = divClass "tyconapp" $ tyConToHtml tc <> " " <> mconcat (intersperse " " (map typeToHtml tys))+typeToHtml (AppTy a b)+ = divClass "appty" $ typeToHtml a <> typeToHtml b+typeToHtml t@(ForAllTy _ _)+ | (bndrs, ty) <- splitForAlls t+ = divClass "forallty" $ do+ keyword "forall "+ bndrsToHtml bndrs+ ". "+ typeToHtml t+typeToHtml (LitTy) = "LIT"+typeToHtml (CoercionTy) = "COERCION"++tyConToHtml :: TyCon -> Html ()+tyConToHtml (TyCon name _) = divClass "tycon" $ toHtml name++litToHtml :: Lit -> Html ()+litToHtml (MachChar c) = "'" <> toHtml [c] <> "'"+litToHtml (MachStr s) = "'" <> toHtml (BS.unpack s) <> "'"+litToHtml (MachNullAddr) = "$nullAddr"+litToHtml (MachInt n) = showHtml n <> "#"+litToHtml (MachInt64 n) = showHtml n <> "#"+litToHtml (MachWord n) = showHtml n <> "##"+litToHtml (MachWord64 n) = showHtml n <> "##64"+litToHtml (MachFloat n) = showHtml (realToFrac n :: Double) <> "##"+litToHtml (MachDouble n) = showHtml (realToFrac n :: Double) <> "##"+litToHtml (MachLabel s) = "&" <> toHtml s+litToHtml (LitInteger n) = showHtml n+litToHtml (LitNatural n) = showHtml n++showHtml :: Show a => a -> Html ()+showHtml = toHtml . show