packages feed

ghc-dump-core (empty) → 0.1.0.0

raw patch · 6 files changed

+583/−0 lines, 6 filesdep +basedep +bytestringdep +filepathsetup-changed

Dependencies added: base, bytestring, filepath, ghc, serialise, text

Files

+ GhcDump/Ast.hs view
@@ -0,0 +1,236 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE DeriveGeneric #-}+module GhcDump.Ast where++import GHC.Generics++import Data.Monoid+import qualified Data.ByteString as BS+import Codec.Serialise+import qualified Data.Text as T++import Unique (mkUnique)++data Unique = Unique !Char !Int+            deriving (Eq, Ord, Generic)+instance Serialise Unique++-- | This is dependent upon GHC+instance Show Unique where+    show (Unique c n) = show $ mkUnique c n++data ExternalName = ExternalName { externalModuleName :: !ModuleName+                                 , externalName :: !T.Text+                                 , externalUnique :: !Unique+                                 }+                  | ForeignCall+                  deriving (Eq, Ord, Generic, Show)+instance Serialise ExternalName++newtype BinderId = BinderId Unique+                 deriving (Eq, Ord, Serialise, Show)++newtype SBinder = SBndr { unSBndr :: Binder' SBinder BinderId }+                deriving (Eq, Ord, Generic, Show)+instance Serialise SBinder++newtype Binder = Bndr { unBndr :: Binder' Binder Binder }+               deriving (Eq, Ord, Generic, Show)+instance Serialise Binder++binderUniqueName :: Binder -> T.Text+binderUniqueName (Bndr b) =+    binderName b <> T.pack "_" <> T.pack (show u)+  where BinderId u = binderId b++data Binder' bndr var = Binder { binderName   :: !T.Text+                               , binderId     :: !BinderId+                               , binderIdInfo :: IdInfo bndr var+                               , binderIdDetails :: IdDetails+                               , binderType   :: Type' bndr var+                               }+                      | TyBinder { binderName :: !T.Text+                                 , binderId   :: !BinderId+                                 , binderKind :: Type' bndr var+                                 }+                      deriving (Eq, Ord, Generic, Show)+instance (Serialise bndr, Serialise var) => Serialise (Binder' bndr var)++data IdInfo bndr var+    = IdInfo { idiArity         :: !Int+             , idiIsOneShot     :: Bool+             , idiUnfolding     :: Unfolding bndr var+             , idiInlinePragma  :: !T.Text+             , idiOccInfo       :: OccInfo+             , idiStrictnessSig :: !T.Text+             , idiDemandSig     :: !T.Text+             , idiCallArity     :: !Int+             }+    deriving (Eq, Ord, Generic, Show)+instance (Serialise bndr, Serialise var) => Serialise (IdInfo bndr var)++data Unfolding bndr var+    = NoUnfolding+    | BootUnfolding+    | OtherCon [AltCon]+    | DFunUnfolding+    | CoreUnfolding { unfTemplate   :: Expr' bndr var+                    , unfIsValue    :: Bool+                    , unfIsConLike  :: Bool+                    , unfIsWorkFree :: Bool+                    , unfGuidance   :: T.Text+                    }+    deriving (Eq, Ord, Generic, Show)+instance (Serialise bndr, Serialise var) => Serialise (Unfolding bndr var)++data OccInfo = OccManyOccs -- | introduced in GHC 8.2+             | OccDead+             | OccOneOcc+             | OccLoopBreaker { occStrongLoopBreaker :: Bool }+    deriving (Eq, Ord, Generic, Show)+instance Serialise OccInfo++data IdDetails = VanillaId+               | RecSelId+               | DataConWorkId+               | DataConWrapId+               | ClassOpId+               | PrimOpId+               -- | FCallId  (these are treated as ExternalNames since they have no binding site)+               | TickBoxOpId+               | DFunId+               | CoVarId -- | introduced in GHC 8.0+               | JoinId { joinIdArity :: !Int }+               deriving (Eq, Ord, Generic, Show)+instance Serialise IdDetails++data Lit = MachChar Char+         | MachStr BS.ByteString+         | MachNullAddr+         | MachInt Integer+         | MachInt64 Integer+         | MachWord Integer+         | MachWord64 Integer+         | MachFloat Rational+         | MachDouble Rational+         | MachLabel T.Text+         | LitInteger Integer+         deriving (Eq, Ord, Generic, Show)+instance Serialise Lit++data TyCon = TyCon !T.Text !Unique+           deriving (Eq, Ord, Generic, Show)+instance Serialise TyCon++type SType = Type' SBinder BinderId+type Type = Type' Binder Binder++data Type' bndr var+    = VarTy var+    | FunTy (Type' bndr var) (Type' bndr var)+    | TyConApp TyCon [Type' bndr var]+    | AppTy (Type' bndr var) (Type' bndr var)+    | ForAllTy bndr (Type' bndr var)+    | LitTy+    | CoercionTy+    deriving (Eq, Ord, Generic, Show)+instance (Serialise bndr, Serialise var) => Serialise (Type' bndr var)++newtype ModuleName = ModuleName {getModuleName :: T.Text}+                   deriving (Eq, Ord, Serialise, Show)++type Module = Module' Binder Binder+type SModule = Module' SBinder BinderId++data Module' bndr var+    = Module { moduleName        :: ModuleName+             , modulePhase       :: T.Text+             , moduleTopBindings :: [TopBinding' bndr var]+             }+    deriving (Generic, Show)+instance (Serialise bndr, Serialise var) => Serialise (Module' bndr var)++moduleBindings :: Module' bndr var -> [(bndr, CoreStats, Expr' bndr var)]+moduleBindings = concatMap topBindings . moduleTopBindings++-- $binders+--+-- The binder story:+--+-- Things which might contain bound variables (e.g. expressions and types) have+-- a type variable which is instantiated at 'BinderId' in the serialised form or+-- 'Binder' after post-processing.+--+-- Note that bindings sites themselves are always 'Binder's.++type SExpr = Expr' SBinder BinderId+type Expr = Expr' Binder Binder++data Expr' bndr var+    = EVar var+    | EVarGlobal ExternalName+    | ELit Lit+    | EApp (Expr' bndr var) (Expr' bndr var)+    | ETyLam bndr (Expr' bndr var)+    | ELam bndr (Expr' bndr var)+    | ELet [(bndr, Expr' bndr var)] (Expr' bndr var)+    | ECase (Expr' bndr var) bndr [Alt' bndr var]+    | EType (Type' bndr var)+    | ECoercion+    deriving (Eq, Ord, Generic, Show)+instance (Serialise bndr, Serialise var) => Serialise (Expr' bndr var)++type SAlt = Alt' SBinder BinderId+type Alt = Alt' Binder Binder++data Alt' bndr var = Alt { altCon     :: !AltCon+                         , altBinders :: [bndr]+                         , altRHS     :: Expr' bndr var+                         }+                  deriving (Eq, Ord, Generic, Show)+instance (Serialise bndr, Serialise var) => Serialise (Alt' bndr var)++data AltCon = AltDataCon !T.Text+            | AltLit Lit+            | AltDefault+            deriving (Eq, Ord, Generic, Show)+instance Serialise AltCon++type STopBinding = TopBinding' SBinder BinderId+type TopBinding = TopBinding' Binder Binder++data TopBinding' bndr var+    = NonRecTopBinding bndr CoreStats (Expr' bndr var)+    | RecTopBinding [(bndr, CoreStats, Expr' bndr var)]+    deriving (Generic, Show)+instance (Serialise bndr, Serialise var) => Serialise (TopBinding' bndr var)++topBindings :: TopBinding' bndr var -> [(bndr, CoreStats, Expr' bndr var)]+topBindings (NonRecTopBinding a b c) = [(a,b,c)]+topBindings (RecTopBinding bs) = bs++data CoreStats+    = CoreStats { csTerms       :: !Int+                , csTypes       :: !Int+                , csCoercions   :: !Int+                , csValBinds   :: !Int+                , csJoinBinds  :: !Int+                }+    deriving (Generic, Show)+instance Serialise CoreStats++instance Monoid CoreStats where+    mempty = CoreStats 0 0 0 0 0+    CoreStats a b c d e `mappend` CoreStats a' b' c' d' e' =+        CoreStats (a+a') (b+b') (c+c') (d+d') (e+e')++{-+data Rule' bndr var+    = Rule { ruleName :: T.Text+           , ruleActivation :: Activation+           , ruleFn :: Name+           , ruleBinders :: [bndr]+           , ruleRHS :: Expr' bndr var+           , ruleAuto :: Bool+           }+-}
+ GhcDump/Convert.hs view
@@ -0,0 +1,232 @@+{-# LANGUAGE CPP #-}+module GhcDump.Convert where++import Data.Bifunctor+import qualified Data.Text as T+import qualified Data.Text.Encoding as TE++import Literal (Literal(..))+import Var (Var)+import qualified Var+import Id (isFCallId)+import Module (ModuleName, moduleNameFS, moduleName)+import Unique (Unique, getUnique, unpkUnique)+import Name (getOccName, occNameFS, OccName, getName, nameModule_maybe)+import qualified IdInfo+import qualified BasicTypes as OccInfo (OccInfo(..), isStrongLoopBreaker)+#if MIN_VERSION_ghc(8,0,0)+import qualified CoreStats+#else+import qualified CoreUtils as CoreStats+#endif+import qualified CoreSyn+import CoreSyn (Expr(..), CoreExpr, Bind(..), CoreAlt, CoreBind, AltCon(..))+import HscTypes (ModGuts(..))+import FastString (FastString, fastStringToByteString)+#if MIN_VERSION_ghc(8,0,0)+import TyCoRep as Type (Type(..), TyBinder(..))+#else+import TypeRep as Type (Type(..))+#endif+import Type (splitFunTy_maybe)+import TyCon (TyCon, tyConUnique)++import Outputable (ppr, showSDoc, SDoc)+import DynFlags (unsafeGlobalDynFlags)++import GhcDump.Ast as Ast++cvtSDoc :: SDoc -> T.Text+cvtSDoc = T.pack . showSDoc unsafeGlobalDynFlags++fastStringToText :: FastString -> T.Text+fastStringToText = TE.decodeUtf8 . fastStringToByteString++occNameToText :: OccName -> T.Text+occNameToText = fastStringToText . occNameFS++cvtUnique :: Unique.Unique -> Ast.Unique+cvtUnique u =+    let (a,b) = unpkUnique u+    in Ast.Unique a b++cvtVar :: Var -> BinderId+cvtVar = BinderId . cvtUnique . Var.varUnique++cvtBinder :: Var -> SBinder+cvtBinder v+  | Var.isId v =+    SBndr $ Binder { binderName   = occNameToText $ getOccName v+                   , binderId     = cvtVar v+                   , binderIdInfo = cvtIdInfo $ Var.idInfo v+                   , binderIdDetails = cvtIdDetails $ Var.idDetails v+                   , binderType   = cvtType $ Var.varType v+                   }+  | otherwise =+    SBndr $ TyBinder { binderName   = occNameToText $ getOccName v+                     , binderId     = cvtVar v+                     , binderKind   = cvtType $ Var.varType v+                     }++cvtIdInfo :: IdInfo.IdInfo -> Ast.IdInfo SBinder BinderId+cvtIdInfo i =+    IdInfo { idiArity         = IdInfo.arityInfo i+           , idiIsOneShot     = IdInfo.oneShotInfo i == IdInfo.OneShotLam+           , idiUnfolding     = cvtUnfolding $ IdInfo.unfoldingInfo i+           , idiInlinePragma  = cvtSDoc $ ppr $ IdInfo.inlinePragInfo i+           , idiOccInfo       = case IdInfo.occInfo i of+#if MIN_VERSION_ghc(8,1,0)+                                  OccInfo.ManyOccs{} -> OccManyOccs+#else+                                  OccInfo.NoOccInfo  -> OccManyOccs+#endif+                                  OccInfo.IAmDead    -> OccDead+                                  OccInfo.OneOcc{}   -> OccOneOcc+                                  oi@OccInfo.IAmALoopBreaker{} -> OccLoopBreaker (OccInfo.isStrongLoopBreaker oi)+           , idiStrictnessSig = cvtSDoc $ ppr $ IdInfo.strictnessInfo i+           , idiDemandSig     = cvtSDoc $ ppr $ IdInfo.demandInfo i+           , idiCallArity     = IdInfo.callArityInfo i+           }++cvtUnfolding :: CoreSyn.Unfolding -> Ast.Unfolding SBinder BinderId+cvtUnfolding CoreSyn.NoUnfolding = Ast.NoUnfolding+#if MIN_VERSION_ghc(8,2,0)+cvtUnfolding CoreSyn.BootUnfolding = Ast.BootUnfolding+#endif+cvtUnfolding (CoreSyn.OtherCon cons) = Ast.OtherCon (map cvtAltCon cons)+cvtUnfolding (CoreSyn.DFunUnfolding{}) = Ast.DFunUnfolding+cvtUnfolding u@(CoreSyn.CoreUnfolding{}) =+    Ast.CoreUnfolding { unfTemplate   = cvtExpr $ CoreSyn.uf_tmpl u+                      , unfIsValue    = CoreSyn.uf_is_value u+                      , unfIsConLike  = CoreSyn.uf_is_conlike u+                      , unfIsWorkFree = CoreSyn.uf_is_work_free u+                      , unfGuidance   = cvtSDoc $ ppr $ CoreSyn.uf_guidance u+                      }++cvtIdDetails :: IdInfo.IdDetails -> Ast.IdDetails+cvtIdDetails d =+    case d of+      IdInfo.VanillaId -> Ast.VanillaId+      IdInfo.RecSelId{} -> Ast.RecSelId+      IdInfo.DataConWorkId{} -> Ast.DataConWorkId+      IdInfo.DataConWrapId{} -> Ast.DataConWrapId+      IdInfo.ClassOpId{} -> Ast.ClassOpId+      IdInfo.PrimOpId{} -> Ast.PrimOpId+      IdInfo.FCallId{} -> error "This shouldn't happen"+      IdInfo.TickBoxOpId{} -> Ast.TickBoxOpId+      IdInfo.DFunId{} -> Ast.DFunId+#if MIN_VERSION_ghc(8,0,0)+      IdInfo.CoVarId{} -> Ast.CoVarId+#endif+#if MIN_VERSION_ghc(8,2,0)+      IdInfo.JoinId n -> Ast.JoinId n+#endif++cvtCoreStats :: CoreStats.CoreStats -> Ast.CoreStats+cvtCoreStats stats =+    Ast.CoreStats+      { csTerms     = CoreStats.cs_tm stats+      , csTypes     = CoreStats.cs_ty stats+      , csCoercions = CoreStats.cs_co stats+#if MIN_VERSION_ghc(8,2,0)+      , csValBinds  = CoreStats.cs_vb stats+      , csJoinBinds = CoreStats.cs_jb stats+#else+      , csValBinds  = 0+      , csJoinBinds = 0+#endif+      }++exprStats :: CoreExpr -> CoreStats.CoreStats+#if MIN_VERSION_ghc(8,0,0)+exprStats = CoreStats.exprStats+#else+-- exprStats wasn't exported in 7.10+exprStats _ = CoreStats.CS 0 0 0+#endif++cvtTopBind :: CoreBind -> STopBinding+cvtTopBind (NonRec b e) =+    NonRecTopBinding (cvtBinder b) (cvtCoreStats $ exprStats e) (cvtExpr e)+cvtTopBind (Rec bs) =+    RecTopBinding $ map to bs+  where to (b, e) = (cvtBinder b, cvtCoreStats $ exprStats e, cvtExpr e)++cvtExpr :: CoreExpr -> Ast.SExpr+cvtExpr expr =+  case expr of+    Var x+        -- foreign calls are local but have no binding site.+        -- TODO: use hasNoBinding here.+      | isFCallId x   -> EVarGlobal ForeignCall+      | Just m <- nameModule_maybe $ getName x+                      -> EVarGlobal $ ExternalName (cvtModuleName $ Module.moduleName m)+                                                   (occNameToText $ getOccName x)+                                                   (cvtUnique $ getUnique x)+      | otherwise     -> EVar (cvtVar x)+    Lit l             -> ELit (cvtLit l)+    App x y           -> EApp (cvtExpr x) (cvtExpr y)+    Lam x e+      | Var.isTyVar x -> ETyLam (cvtBinder x) (cvtExpr e)+      | otherwise     -> ELam (cvtBinder x) (cvtExpr e)+    Let (NonRec b e) body -> ELet [(cvtBinder b, cvtExpr e)] (cvtExpr body)+    Let (Rec bs) body -> ELet (map (bimap cvtBinder cvtExpr) bs) (cvtExpr body)+    Case e x _ as     -> ECase (cvtExpr e) (cvtBinder x) (map cvtAlt as)+    Cast x _          -> cvtExpr x+    Tick _ e          -> cvtExpr e+    Type t            -> EType $ cvtType t+    Coercion _        -> ECoercion++cvtAlt :: CoreAlt -> Ast.SAlt+cvtAlt (con, bs, e) = Alt (cvtAltCon con) (map cvtBinder bs) (cvtExpr e)++cvtAltCon :: CoreSyn.AltCon -> Ast.AltCon+cvtAltCon (DataAlt altcon) = Ast.AltDataCon $ occNameToText $ getOccName altcon+cvtAltCon (LitAlt l)       = Ast.AltLit $ cvtLit l+cvtAltCon DEFAULT          = Ast.AltDefault++cvtLit :: Literal -> Ast.Lit+cvtLit l =+    case l of+      Literal.MachChar x -> Ast.MachChar x+      Literal.MachStr x -> Ast.MachStr x+      Literal.MachNullAddr -> Ast.MachNullAddr+      Literal.MachInt x -> Ast.MachInt x+      Literal.MachInt64 x -> Ast.MachInt64 x+      Literal.MachWord x -> Ast.MachWord x+      Literal.MachWord64 x -> Ast.MachWord64 x+      Literal.MachFloat x -> Ast.MachFloat x+      Literal.MachDouble x -> Ast.MachDouble x+      Literal.MachLabel x _ _ -> Ast.MachLabel $ fastStringToText  x+      Literal.LitInteger x _ -> Ast.LitInteger x++cvtModule :: String -> ModGuts -> Ast.SModule+cvtModule phase guts =+    Ast.Module name (T.pack phase) (map cvtTopBind $ mg_binds guts)+  where name = cvtModuleName $ Module.moduleName $ mg_module guts++cvtModuleName :: Module.ModuleName -> Ast.ModuleName+cvtModuleName = Ast.ModuleName . fastStringToText . moduleNameFS++cvtType :: Type.Type -> Ast.SType+cvtType t+  | Just (a,b) <- splitFunTy_maybe t = Ast.FunTy (cvtType a) (cvtType b)+cvtType (Type.TyVarTy v)       = Ast.VarTy (cvtVar v)+cvtType (Type.AppTy a b)       = Ast.AppTy (cvtType a) (cvtType b)+cvtType (Type.TyConApp tc tys) = Ast.TyConApp (cvtTyCon tc) (map cvtType tys)+#if MIN_VERSION_ghc(8,2,0)+cvtType (Type.ForAllTy (Var.TvBndr b _) t) = Ast.ForAllTy (cvtBinder b) (cvtType t)+#elif MIN_VERSION_ghc(8,0,0)+cvtType (Type.ForAllTy (Named b _) t) = Ast.ForAllTy (cvtBinder b) (cvtType t)+cvtType (Type.ForAllTy (Anon _) t)    = cvtType t+#else+cvtType (Type.ForAllTy b t)    = Ast.ForAllTy (cvtBinder b) (cvtType t)+#endif+cvtType (Type.LitTy _)         = Ast.LitTy+#if MIN_VERSION_ghc(8,0,0)+cvtType (Type.CastTy t _)      = cvtType t+cvtType (Type.CoercionTy _)    = Ast.CoercionTy+#endif++cvtTyCon :: TyCon.TyCon -> Ast.TyCon+cvtTyCon tc = TyCon (occNameToText $ getOccName tc) (cvtUnique $ tyConUnique tc)
+ GhcDump/Plugin.hs view
@@ -0,0 +1,40 @@+{-# LANGUAGE CPP #-}++module GhcDump.Plugin where++import Data.Maybe+import qualified Data.ByteString.Lazy as BSL+import qualified Codec.Serialise as Ser+import GhcPlugins hiding (TB)+import CoreMonad (pprPassDetails)+import ErrUtils (showPass)+import Text.Printf+import System.FilePath++import GhcDump.Convert++plugin :: Plugin+plugin = defaultPlugin { installCoreToDos = install }++install :: [CommandLineOption] -> [CoreToDo] -> CoreM [CoreToDo]+install _opts todo = do+    dflags <- getDynFlags+    return (intersperseDumps dflags todo)++intersperseDumps :: DynFlags -> [CoreToDo] -> [CoreToDo]+intersperseDumps dflags = go 0 "desugar"+  where+    go n phase (todo : rest) = pass n phase : todo : go (n+1) phase' rest+      where phase' = showSDocDump dflags (ppr todo <> text ":" <+> pprPassDetails todo)+    go n phase [] = [pass n phase]++    pass n phase = CoreDoPluginPass "DumpCore" (liftIO . dumpIn dflags n phase)++dumpIn :: DynFlags -> Int -> String -> ModGuts -> IO ModGuts+dumpIn dflags n phase guts = do+    let prefix = fromMaybe "dump" $ dumpPrefix dflags+        fname = printf "%spass-%04u.cbor" prefix n+    showPass dflags $ "GhcDump: Dumping core to "++fname+    let in_dump_dir = maybe id (</>) (dumpDir dflags)+    BSL.writeFile (in_dump_dir fname) $ Ser.serialise (cvtModule phase guts)+    return guts
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2017, Ben Gamari++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Ben Gamari nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ ghc-dump-core.cabal view
@@ -0,0 +1,43 @@+name:                ghc-dump-core+version:             0.1.0.0+synopsis:            An AST and compiler plugin for dumping GHC's Core representation.+description:+  @ghc-dump@ is a library, GHC plugin, and set of tools for recording and+  analysing GHC's Core representation. The plugin is compatible with GHC 7.10+  through 8.3, exporting a consistent (albeit somewhat lossy) representation+  across these versions. The AST is encoded as CBOR, which is small and easy to+  deserialise.+  .+  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.+  .+  = Usage+  .+  "GhcDump.Plugin" provides a Core-to-Core plugin which dumps a representation+  of the Core AST to a file after every Core-to-Core pass. To use it, simply+  install this package and add @-fplugin GhcDump.Plugin@ to your GHC+  command-line. See the [README](https://github.com/bgamari/ghc-dump)+  for further analysis tips.++license:             BSD3+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+cabal-version:       >=1.10++library+  exposed-modules:     GhcDump.Convert, GhcDump.Ast, GhcDump.Plugin+  ghc-options:         -Wall+  other-extensions:    GeneralizedNewtypeDeriving+  build-depends:       base >=4.8 && <4.11,+                       bytestring >= 0.10,+                       text >=1.2 && <1.3,+                       filepath >= 1.4,+                       serialise >= 0.2 && <0.3,+                       ghc >= 7.10 && < 8.4+  default-language:    Haskell2010