packages feed

ghc-exactprint 0.3.1.1 → 0.4.0.0

raw patch · 49 files changed

+1849/−484 lines, 49 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Language.Haskell.GHC.ExactPrint: exactPrintWithAnns :: Annotate ast => Located ast -> Anns -> String
- Language.Haskell.GHC.ExactPrint.Print: exactPrintWithAnns :: Annotate ast => Located ast -> Anns -> String
- Language.Haskell.GHC.ExactPrint.Print: instance GHC.Base.Monoid Language.Haskell.GHC.ExactPrint.Print.EPWriter
- Language.Haskell.GHC.ExactPrint.Transform: decl2BindT :: LHsDecl RdrName -> Transform [LHsBind RdrName]
- Language.Haskell.GHC.ExactPrint.Transform: decl2SigT :: LHsDecl RdrName -> Transform [LSig RdrName]
- Language.Haskell.GHC.ExactPrint.Transform: declFun :: (forall a. Data a => Located a -> b) -> LHsDecl RdrName -> b
- Language.Haskell.GHC.ExactPrint.Transform: instance Language.Haskell.GHC.ExactPrint.Transform.HasDecls (HsBinds.HsLocalBinds RdrName.RdrName)
- Language.Haskell.GHC.ExactPrint.Transform: instance Language.Haskell.GHC.ExactPrint.Transform.HasDecls (HsBinds.LHsBind RdrName.RdrName)
- Language.Haskell.GHC.ExactPrint.Transform: instance Language.Haskell.GHC.ExactPrint.Transform.HasDecls (HsBinds.LHsBinds RdrName.RdrName)
- Language.Haskell.GHC.ExactPrint.Transform: instance Language.Haskell.GHC.ExactPrint.Transform.HasDecls (HsDecls.LHsDecl RdrName.RdrName)
- Language.Haskell.GHC.ExactPrint.Transform: instance Language.Haskell.GHC.ExactPrint.Transform.HasDecls (HsExpr.GRHSs RdrName.RdrName (HsExpr.LHsExpr RdrName.RdrName))
- Language.Haskell.GHC.ExactPrint.Transform: instance Language.Haskell.GHC.ExactPrint.Transform.HasDecls (HsExpr.MatchGroup RdrName.RdrName (HsExpr.LHsExpr RdrName.RdrName))
- Language.Haskell.GHC.ExactPrint.Transform: instance Language.Haskell.GHC.ExactPrint.Transform.HasDecls (HsExpr.Stmt RdrName.RdrName (HsExpr.LHsExpr RdrName.RdrName))
- Language.Haskell.GHC.ExactPrint.Transform: instance Language.Haskell.GHC.ExactPrint.Transform.HasDecls [HsBinds.LHsBind RdrName.RdrName]
- Language.Haskell.GHC.ExactPrint.Transform: instance Language.Haskell.GHC.ExactPrint.Transform.HasDecls [HsExpr.LMatch RdrName.RdrName (HsExpr.LHsExpr RdrName.RdrName)]
- Language.Haskell.GHC.ExactPrint.Transform: pushDeclAnnT :: LHsDecl RdrName -> Transform (LHsDecl RdrName)
- Language.Haskell.GHC.ExactPrint.Transform: wrapDeclT :: LHsBind RdrName -> Transform (LHsDecl RdrName)
- Language.Haskell.GHC.ExactPrint.Transform: wrapSigT :: LSig RdrName -> Transform (LHsDecl RdrName)
+ Language.Haskell.GHC.ExactPrint.Print: instance GHC.Base.Monoid w => GHC.Base.Monoid (Language.Haskell.GHC.ExactPrint.Print.EPWriter w)
+ Language.Haskell.GHC.ExactPrint.Print: semanticPrint :: (Annotate ast, Monoid b) => (forall a. Data a => Located a -> b -> b) -> (String -> b) -> (String -> b) -> Located ast -> Anns -> b
+ Language.Haskell.GHC.ExactPrint.Print: semanticPrintM :: (Annotate ast, Monoid b, Monad m) => (forall a. Data a => Located a -> b -> m b) -> (String -> m b) -> (String -> m b) -> Located ast -> Anns -> m b
+ Language.Haskell.GHC.ExactPrint.Transform: TransformT :: RWST () [String] (Anns, Int) m a -> TransformT m a
+ Language.Haskell.GHC.ExactPrint.Transform: [runTransformT] :: TransformT m a -> RWST () [String] (Anns, Int) m a
+ Language.Haskell.GHC.ExactPrint.Transform: addTrailingComma :: (Data a) => Located a -> DeltaPos -> Anns -> Anns
+ Language.Haskell.GHC.ExactPrint.Transform: addTrailingCommaT :: (Data a) => Located a -> Transform ()
+ Language.Haskell.GHC.ExactPrint.Transform: class (Monad m) => HasTransform m
+ Language.Haskell.GHC.ExactPrint.Transform: cloneT :: (Data a, Typeable a) => a -> Transform (a, [(SrcSpan, SrcSpan)])
+ Language.Haskell.GHC.ExactPrint.Transform: decl2Bind :: LHsDecl name -> [LHsBind name]
+ Language.Haskell.GHC.ExactPrint.Transform: decl2Sig :: LHsDecl name -> [LSig name]
+ Language.Haskell.GHC.ExactPrint.Transform: hasDeclsSybTransform :: (Data t2, Typeable t2, Monad m) => (forall t. HasDecls t => t -> m t) -> (LHsBind RdrName -> m (LHsBind RdrName)) -> t2 -> m t2
+ Language.Haskell.GHC.ExactPrint.Transform: hsDeclsGeneric :: (Data t, Typeable t) => t -> Transform [LHsDecl RdrName]
+ Language.Haskell.GHC.ExactPrint.Transform: hsDeclsPatBind :: (Monad m) => LHsBind RdrName -> TransformT m [LHsDecl RdrName]
+ Language.Haskell.GHC.ExactPrint.Transform: hsDeclsPatBindD :: (Monad m) => LHsDecl RdrName -> TransformT m [LHsDecl RdrName]
+ Language.Haskell.GHC.ExactPrint.Transform: hsDeclsValBinds :: (Monad m) => HsLocalBinds RdrName -> TransformT m [LHsDecl RdrName]
+ Language.Haskell.GHC.ExactPrint.Transform: instance GHC.Base.Functor m => GHC.Base.Functor (Language.Haskell.GHC.ExactPrint.Transform.TransformT m)
+ Language.Haskell.GHC.ExactPrint.Transform: instance GHC.Base.Monad m => Control.Monad.Reader.Class.MonadReader () (Language.Haskell.GHC.ExactPrint.Transform.TransformT m)
+ Language.Haskell.GHC.ExactPrint.Transform: instance GHC.Base.Monad m => Control.Monad.State.Class.MonadState (Language.Haskell.GHC.ExactPrint.Types.Anns, GHC.Types.Int) (Language.Haskell.GHC.ExactPrint.Transform.TransformT m)
+ Language.Haskell.GHC.ExactPrint.Transform: instance GHC.Base.Monad m => Control.Monad.Writer.Class.MonadWriter [GHC.Base.String] (Language.Haskell.GHC.ExactPrint.Transform.TransformT m)
+ Language.Haskell.GHC.ExactPrint.Transform: instance GHC.Base.Monad m => GHC.Base.Applicative (Language.Haskell.GHC.ExactPrint.Transform.TransformT m)
+ Language.Haskell.GHC.ExactPrint.Transform: instance GHC.Base.Monad m => GHC.Base.Monad (Language.Haskell.GHC.ExactPrint.Transform.TransformT m)
+ Language.Haskell.GHC.ExactPrint.Transform: instance Language.Haskell.GHC.ExactPrint.Transform.HasDecls (HsExpr.LStmt RdrName.RdrName (HsExpr.LHsExpr RdrName.RdrName))
+ Language.Haskell.GHC.ExactPrint.Transform: instance Language.Haskell.GHC.ExactPrint.Transform.HasTransform (Language.Haskell.GHC.ExactPrint.Transform.TransformT Data.Functor.Identity.Identity)
+ Language.Haskell.GHC.ExactPrint.Transform: liftT :: HasTransform m => Transform a -> m a
+ Language.Haskell.GHC.ExactPrint.Transform: logDataWithAnnsTr :: (Monad m) => (Data a) => String -> a -> TransformT m ()
+ Language.Haskell.GHC.ExactPrint.Transform: modifyDeclsT :: (HasDecls t, HasTransform m) => ([LHsDecl RdrName] -> m [LHsDecl RdrName]) -> t -> m t
+ Language.Haskell.GHC.ExactPrint.Transform: modifyValD :: (HasTransform m) => SrcSpan -> Decl -> (Match -> [Decl] -> m ([Decl], Maybe t)) -> m (Decl, Maybe t)
+ Language.Haskell.GHC.ExactPrint.Transform: newtype TransformT m a
+ Language.Haskell.GHC.ExactPrint.Transform: removeTrailingCommaT :: (Data a) => Located a -> Transform ()
+ Language.Haskell.GHC.ExactPrint.Transform: replaceDeclsPatBind :: (Monad m) => LHsBind RdrName -> [LHsDecl RdrName] -> TransformT m (LHsBind RdrName)
+ Language.Haskell.GHC.ExactPrint.Transform: replaceDeclsPatBindD :: (Monad m) => LHsDecl RdrName -> [LHsDecl RdrName] -> TransformT m (LHsDecl RdrName)
+ Language.Haskell.GHC.ExactPrint.Transform: replaceDeclsValbinds :: (Monad m) => HsLocalBinds RdrName -> [LHsDecl RdrName] -> TransformT m (HsLocalBinds RdrName)
+ Language.Haskell.GHC.ExactPrint.Transform: runTransformFrom :: Int -> Anns -> Transform a -> (a, (Anns, Int), [String])
+ Language.Haskell.GHC.ExactPrint.Transform: runTransformFromT :: (Monad m) => Int -> Anns -> TransformT m a -> m (a, (Anns, Int), [String])
+ Language.Haskell.GHC.ExactPrint.Transform: setEntryDP :: (Data a) => Located a -> DeltaPos -> Anns -> Anns
+ Language.Haskell.GHC.ExactPrint.Transform: setEntryDPT :: (Data a) => Located a -> DeltaPos -> Transform ()
+ Language.Haskell.GHC.ExactPrint.Transform: setPrecedingLinesDeclT :: LHsDecl RdrName -> Int -> Int -> Transform ()
+ Language.Haskell.GHC.ExactPrint.Transform: setPrecedingLinesT :: (Data a) => Located a -> Int -> Int -> Transform ()
+ Language.Haskell.GHC.ExactPrint.Transform: transferEntryDP :: (Data a, Data b) => Located a -> Located b -> Anns -> Anns
+ Language.Haskell.GHC.ExactPrint.Transform: transferEntryDPT :: (Data a, Data b) => Located a -> Located b -> Transform ()
+ Language.Haskell.GHC.ExactPrint.Transform: wrapDecl :: LHsBind RdrName -> LHsDecl RdrName
+ Language.Haskell.GHC.ExactPrint.Transform: wrapSig :: LSig RdrName -> LHsDecl RdrName
+ Language.Haskell.GHC.ExactPrint.Types: declFun :: (forall a. Data a => Located a -> b) -> LHsDecl RdrName -> b
+ Language.Haskell.GHC.ExactPrint.Utils: annCommentEntryDelta :: Annotation -> DeltaPos -> DeltaPos
+ Language.Haskell.GHC.ExactPrint.Utils: annLeadingCommentEntryDelta :: Annotation -> DeltaPos
- Language.Haskell.GHC.ExactPrint: exactPrint :: Annotate ast => Located ast -> ApiAnns -> String
+ Language.Haskell.GHC.ExactPrint: exactPrint :: Annotate ast => Located ast -> Anns -> String
- Language.Haskell.GHC.ExactPrint.Print: exactPrint :: Annotate ast => Located ast -> ApiAnns -> String
+ Language.Haskell.GHC.ExactPrint.Print: exactPrint :: Annotate ast => Located ast -> Anns -> String
- Language.Haskell.GHC.ExactPrint.Transform: balanceTrailingComments :: (Data a, Data b) => Located a -> Located b -> Transform [(Comment, DeltaPos)]
+ Language.Haskell.GHC.ExactPrint.Transform: balanceTrailingComments :: (Monad m) => (Data a, Data b) => Located a -> Located b -> TransformT m [(Comment, DeltaPos)]
- Language.Haskell.GHC.ExactPrint.Transform: getAnnsT :: Transform Anns
+ Language.Haskell.GHC.ExactPrint.Transform: getAnnsT :: (Monad m) => TransformT m Anns
- Language.Haskell.GHC.ExactPrint.Transform: hsDecls :: HasDecls t => t -> Transform [LHsDecl RdrName]
+ Language.Haskell.GHC.ExactPrint.Transform: hsDecls :: (HasDecls t, Monad m) => t -> TransformT m [LHsDecl RdrName]
- Language.Haskell.GHC.ExactPrint.Transform: logTr :: String -> Transform ()
+ Language.Haskell.GHC.ExactPrint.Transform: logTr :: (Monad m) => String -> TransformT m ()
- Language.Haskell.GHC.ExactPrint.Transform: modifyAnnsT :: (Anns -> Anns) -> Transform ()
+ Language.Haskell.GHC.ExactPrint.Transform: modifyAnnsT :: (Monad m) => (Anns -> Anns) -> TransformT m ()
- Language.Haskell.GHC.ExactPrint.Transform: putAnnsT :: Anns -> Transform ()
+ Language.Haskell.GHC.ExactPrint.Transform: putAnnsT :: (Monad m) => Anns -> TransformT m ()
- Language.Haskell.GHC.ExactPrint.Transform: replaceDecls :: HasDecls t => t -> [LHsDecl RdrName] -> Transform t
+ Language.Haskell.GHC.ExactPrint.Transform: replaceDecls :: (HasDecls t, Monad m) => t -> [LHsDecl RdrName] -> TransformT m t
- Language.Haskell.GHC.ExactPrint.Transform: type Transform a = RWS () [String] (Anns, Int) a
+ Language.Haskell.GHC.ExactPrint.Transform: type Transform = TransformT Identity

Files

ChangeLog view
@@ -1,5 +1,22 @@+2015-09-28 v0.4.0.0+	* Rework HasDecls so that there are only instances for which it is+	idempotent. Provide functions for managing an LHsBind which is not+	idempotent, and performing general transformations on an AST+	including FunBinds.+	* Manage LHsDecl instances so that the Annotation always attaches+	to the wrapped item, so that they can be seamlessly used in a top+	level (wrapped) or local (unwrapped) context.+	* Tweak transformations based on HaRe integration.+	* This release supports the HaRe 8.0 release, which finally works+	with GHC 7.10.2+	* Rename `exactPrintWithAnns` to `exactPrint`. This will possibly+	break earlier client libraries, but is a simple rename.+	* Bring in semanticPrintM which allows wrapper functions to be+	provided for the generated output, for use when emitting e.g. HTML+	marked up source.+ 2015-08-13 v0.3.1.1-	* Add missing test files to sdist+	* Add missing test files to sdist, closes #23  2015-08-02 v0.3.1 
ghc-exactprint.cabal view
@@ -1,5 +1,5 @@ name:                ghc-exactprint-version:             0.3.1.1+version:             0.4.0.0 synopsis:            ExactPrint for GHC description:         Using the API Annotations available from GHC 7.10.2, this                      library provides a means to round trip any code that can
src/Language/Haskell/GHC/ExactPrint.hs view
@@ -17,7 +17,6 @@         , module Language.Haskell.GHC.ExactPrint.Transform          -- * Printing-        , exactPrintWithAnns         , exactPrint          ) where
src/Language/Haskell/GHC/ExactPrint/Annotate.hs view
@@ -26,7 +26,8 @@          annotate        , AnnotationF(..)        , Annotated-       , Annotate(..)) where+       , Annotate(..)+       ) where  import Data.Maybe ( fromMaybe ) #if __GLASGOW_HASKELL__ <= 710@@ -190,7 +191,7 @@ -- | Constructs a syntax tree which contains information about which -- annotations are required by each element. markLocated :: (Annotate ast) => GHC.Located ast -> Annotated ()-markLocated a = withLocated a markAST+markLocated ast = withLocated ast markAST  withLocated :: Data a             => GHC.Located a@@ -268,7 +269,7 @@     markMany GHC.AnnSemi -- possible leading semis     mapM_ markLocated imps -    mapM_ markLocated decs+    mapM_ (\(GHC.L l ast) -> markAST l ast) decs      mark GHC.AnnCloseC -- Possible '}' @@ -492,13 +493,17 @@    markTrailingSemi  -- ---------------------------------------------------------------------+ instance Annotate GHC.ModuleName where    markAST l mname =     markExternal l GHC.AnnVal (GHC.moduleNameString mname) -instance (GHC.DataId name,GHC.OutputableBndr name,GHC.HasOccName name,Annotate name)-  => Annotate (GHC.HsDecl name) where-  markAST l decl = do+-- ---------------------------------------------------------------------++-- instance (GHC.DataId name,GHC.OutputableBndr name,GHC.HasOccName name,Annotate name)+markLHsDecl :: (GHC.DataId name,GHC.OutputableBndr name,GHC.HasOccName name,Annotate name)+            => GHC.LHsDecl name -> Annotated ()+markLHsDecl (GHC.L l decl) =     case decl of       GHC.TyClD d       -> markLocated (GHC.L l d)       GHC.InstD d       -> markLocated (GHC.L l d)@@ -518,6 +523,10 @@       GHC.QuasiQuoteD d -> markLocated (GHC.L l d) #endif +instance (GHC.DataId name,GHC.OutputableBndr name,GHC.HasOccName name,Annotate name)+            => Annotate (GHC.HsDecl name) where+  markAST l d = markLHsDecl (GHC.L l d)+ -- ---------------------------------------------------------------------  instance (Annotate name)@@ -1660,11 +1669,7 @@                       else markWithString GHC.AnnClose "#)"  -  -- We set the layout for HsCase and HsIf even though they need not obey-  -- layout rules as when moving these expressions it's useful that they-  -- maintain "internal integrity", that is to say the subparts remain-  -- indented relative to each other.-  markAST l (GHC.HsCase e1 matches) = setLayoutFlag $ do+  markAST l (GHC.HsCase e1 matches) = do     mark GHC.AnnCase     markLocated e1     mark GHC.AnnOf@@ -1673,6 +1678,10 @@     markMatchGroup l matches     mark GHC.AnnCloseC +  -- We set the layout for HsIf even though it need not obey layout rules as+  -- when moving these expressions it's useful that they maintain "internal+  -- integrity", that is to say the subparts remain indented relative to each+  -- other.   markAST _ (GHC.HsIf _ e1 e2 e3) = setLayoutFlag $ do     mark GHC.AnnIf     markLocated e1@@ -1831,7 +1840,7 @@   markAST _ (GHC.HsBracket (GHC.DecBrL ds)) = do     markWithString GHC.AnnOpen "[d|"     mark GHC.AnnOpenC-    mapM_ markLocated ds+    mapM_ (\(GHC.L l d) -> markAST l d) ds     mark GHC.AnnCloseC     markWithString GHC.AnnClose "|]"   -- Introduced after the renamer
src/Language/Haskell/GHC/ExactPrint/Delta.hs view
@@ -65,7 +65,7 @@ import Language.Haskell.GHC.ExactPrint.Lookup import Language.Haskell.GHC.ExactPrint.Types import Language.Haskell.GHC.ExactPrint.Annotate (AnnotationF(..), Annotated-                                                , annotate,  Annotate(..))+                                                , annotate, Annotate(..))  import qualified GHC import qualified SrcLoc         as GHC
src/Language/Haskell/GHC/ExactPrint/Parsers.hs view
@@ -142,7 +142,7 @@ -- parseModule = parseModuleWithCpp defaultCppOptions -- @ ----- Note: 'GHC.ParsedSource' is a synonym for @Located (HsModule RdrName)@+-- Note: 'GHC.ParsedSource' is a synonym for 'GHC.Located' ('GHC.HsModule' 'GHC.RdrName') parseModule :: FilePath -> IO (Either (GHC.SrcSpan, String) (Anns, (GHC.Located (GHC.HsModule GHC.RdrName)))) parseModule = parseModuleWithCpp defaultCppOptions 
src/Language/Haskell/GHC/ExactPrint/Print.hs view
@@ -2,6 +2,7 @@ {-# LANGUAGE MultiWayIf #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE RankNTypes #-}  ----------------------------------------------------------------------------- -- |@@ -13,9 +14,9 @@ ----------------------------------------------------------------------------- module Language.Haskell.GHC.ExactPrint.Print         (-          exactPrintWithAnns--        , exactPrint+        exactPrint+        , semanticPrint+        , semanticPrintM          ) where @@ -24,7 +25,6 @@ import Language.Haskell.GHC.ExactPrint.Annotate   (AnnotationF(..), Annotated, Annotate(..), annotate) import Language.Haskell.GHC.ExactPrint.Lookup (keywordToString, unicodeString)-import Language.Haskell.GHC.ExactPrint.Delta ( relativiseApiAnns )  import Control.Monad.RWS import Data.Data (Data)@@ -33,60 +33,86 @@ import Data.Maybe (fromMaybe)  import Control.Monad.Trans.Free-+import Control.Monad.Identity  import qualified GHC  ------------------------------------------------------------------------------ -- Printing of source elements --- | Print an AST exactly as specified by the annotations on the nodes in the tree.--- The output of this function should exactly match the source file.-exactPrint :: Annotate ast => GHC.Located ast -> GHC.ApiAnns -> String-exactPrint ast ghcAnns = exactPrintWithAnns ast relativeAnns-  where-    relativeAnns = relativiseApiAnns ast ghcAnns- -- | Print an AST with a map of potential modified `Anns`. The usual way to--- generate such a map is by calling `relativiseApiAnns`.-exactPrintWithAnns :: Annotate ast+-- generate such a map is by using one of the parsers in+-- "Language.Haskell.GHC.ExactPrint.Parsers".+exactPrint :: Annotate ast                      => GHC.Located ast                      -> Anns                      -> String-exactPrintWithAnns ast an = runEP (annotate ast) an+exactPrint = semanticPrint (\_ b -> b) id id +-- | A more general version of `semanticPrint`.+semanticPrintM :: (Annotate ast, Monoid b, Monad m) =>+              (forall a . Data a => GHC.Located a -> b -> m b) -- ^ How to surround an AST fragment+              -> (String -> m b) -- ^ How to output a token+              -> (String -> m b) -- ^ How to output whitespace+              -> GHC.Located ast+              -> Anns+              -> m b+semanticPrintM astOut tokenOut whiteOut ast as =  runEP astOut tokenOut whiteOut (annotate ast) as ++-- | A more general version of 'exactPrint' which allows the customisation+-- of the output whilst retaining the original source formatting. This is+-- useful for smarter syntax highlighting.+semanticPrint :: (Annotate ast, Monoid b) =>+              (forall a . Data a => GHC.Located a -> b -> b) -- ^ How to surround an AST fragment+              -> (String -> b) -- ^ How to output a token+              -> (String -> b) -- ^ How to output whitespace+              -> GHC.Located ast+              -> Anns+              -> b+semanticPrint a b c d e = runIdentity (semanticPrintM (\ast s -> Identity (a ast s)) (return . b) (return . c) d e)++ ------------------------------------------------------ -- The EP monad and basic combinators -data EPReader = EPReader+data EPReader m a = EPReader             {               epAnn :: !Annotation+            , epAstPrint :: forall ast . Data ast => GHC.Located ast -> a -> m a+            , epTokenPrint :: String -> m a+            , epWhitespacePrint :: String -> m a             } -data EPWriter = EPWriter-              { output :: !(Endo String) }+data EPWriter a = EPWriter+              { output :: !a } -instance Monoid EPWriter where+instance Monoid w => Monoid (EPWriter w) where   mempty = EPWriter mempty   (EPWriter a) `mappend` (EPWriter b) = EPWriter (a <> b)  data EPState = EPState              { epPos    :: !Pos -- ^ Current output position              , epAnns   :: !Anns-             , epAnnKds :: ![[(KeywordId, DeltaPos)]] -- MP: Could this be moved to the local state with suitable refactoring?+             , epAnnKds :: ![[(KeywordId, DeltaPos)]] -- MP: Could this be moved to the local statE w mith suitable refactoring?              , epMarkLayout :: Bool              , epLHS :: LayoutStartCol              }  --------------------------------------------------------- -type EP a = RWS EPReader EPWriter EPState a+type EP w m a = RWST (EPReader m w) (EPWriter w) EPState m a -runEP :: Annotated () -> Anns -> String-runEP action ans =-  flip appEndo "" . output . snd-  . (\next -> execRWS next initialEPReader (defaultEPState ans))+++runEP :: (Monad m, Monoid a) =>+      (forall ast . Data ast => GHC.Located ast -> a -> m a)+      -> (String -> m a)+      -> (String -> m a)+      -> Annotated () -> Anns -> m a+runEP astPrint wsPrint tokenPrint action ans =+  fmap (output . snd) .+    (\next -> execRWST next (initialEPReader astPrint tokenPrint wsPrint) (defaultEPState ans))   . printInterpret $ action  -- ---------------------------------------------------------------------@@ -100,18 +126,25 @@              , epMarkLayout = False              } -initialEPReader :: EPReader-initialEPReader  = EPReader+initialEPReader ::+      (forall ast . Data ast => GHC.Located ast -> a -> m a)+      -> (String -> m a)+      -> (String -> m a)+      -> EPReader m a+initialEPReader astPrint tokenPrint wsPrint  = EPReader              {                epAnn = annNone+             , epAstPrint = astPrint+             , epWhitespacePrint = wsPrint+             , epTokenPrint = tokenPrint              }  -- --------------------------------------------------------------------- -printInterpret :: Annotated a -> EP a-printInterpret = iterTM go+printInterpret :: forall w m a . (Monad m, Monoid w) => Annotated a -> EP w m a+printInterpret m = iterTM go (hoistFreeT (return . runIdentity) m)   where-    go :: AnnotationF (EP a) -> EP a+    go :: (Monad m, Monoid w) => AnnotationF (EP w m a) -> EP w m a     go (MarkEOF next) =       printStringAtMaybeAnn (G GHC.AnnEofPos) "" >> next     go (MarkPrim kwid mstr next) =@@ -147,14 +180,14 @@  ------------------------------------------------------------------------- -storeOriginalSrcSpanPrint :: EP AnnKey+storeOriginalSrcSpanPrint :: (Monad m, Monoid w) => EP w m AnnKey storeOriginalSrcSpanPrint = do   Ann{..} <- asks epAnn   case annCapturedSpan of     Nothing -> error "Missing captured SrcSpan"     Just v  -> return v -printStoredString :: EP ()+printStoredString :: (Monad m, Monoid w) => EP w m () printStoredString = do   kd <- gets epAnnKds @@ -166,7 +199,7 @@     ((AnnString ss,_):_) -> printStringAtMaybeAnn (AnnString ss) ss     _                    -> return () -withSortKey :: [(GHC.SrcSpan, Annotated ())] -> EP ()+withSortKey :: (Monad m, Monoid w) => [(GHC.SrcSpan, Annotated ())] -> EP w m () withSortKey xs = do   Ann{..} <- asks epAnn   let ordered = case annSortKey of@@ -181,12 +214,12 @@  ------------------------------------------------------------------------- -allAnns :: GHC.AnnKeywordId -> EP ()+allAnns :: (Monad m, Monoid w) => GHC.AnnKeywordId -> EP w m () allAnns kwid = printStringAtMaybeAnnAll (G kwid) (keywordToString (G kwid))  ------------------------------------------------------------------------- -- |First move to the given location, then call exactP-exactPC :: Data ast => GHC.Located ast -> EP a -> EP a+exactPC :: (Data ast, Monad m, Monoid w) => GHC.Located ast -> EP w m a -> EP w m a exactPC ast action =     do       return () `debug` ("exactPC entered for:" ++ show (mkAnnKey ast))@@ -196,38 +229,49 @@                 , annFollowingComments=fcomments                 , annsDP=kds                 } = fromMaybe annNone ma+      EPReader{epAstPrint} <- ask       r <- withContext kds an        (mapM_ (uncurry printQueuedComment) comments        >> advance edp-       >> action+       >> censorM (epAstPrint ast) action        <* mapM_ (uncurry printQueuedComment) fcomments)       return r `debug` ("leaving exactPCfor:" ++ show (mkAnnKey ast)) -advance :: DeltaPos -> EP ()+censorM :: (Monoid w, Monad m) => (w -> m w) -> EP w m a -> EP w m a+censorM f m = passM (liftM (\x -> (x,f)) m)++passM :: (Monoid w, Monad m) => EP w m (a, w -> m w) -> EP w m a+passM m = RWST $ \r s -> do+      ~((a, f),s', EPWriter w) <- runRWST m r s+      w' <- f w+      return (a, s', EPWriter w')++advance :: (Monad m, Monoid w) => DeltaPos -> EP w m () advance cl = do   p <- getPos   colOffset <- getLayoutOffset   printWhitespace (undelta p cl colOffset) -getAndRemoveAnnotation :: (Data a) => GHC.Located a -> EP (Maybe Annotation)+getAndRemoveAnnotation :: (Monad m, Monoid w, Data a) => GHC.Located a -> EP w m (Maybe Annotation) getAndRemoveAnnotation a = gets ((getAnnotationEP a) . epAnns) -markPrim :: KeywordId -> Maybe String -> EP ()+markPrim :: (Monad m, Monoid w) => KeywordId -> Maybe String -> EP w m () markPrim kwid mstr =   let annString = fromMaybe (keywordToString kwid) mstr   in printStringAtMaybeAnn kwid annString -withContext :: [(KeywordId, DeltaPos)]+withContext :: (Monad m, Monoid w)+            => [(KeywordId, DeltaPos)]             -> Annotation-            -> EP a -> EP a-withContext kds an = withKds kds . withOffset an+            -> EP w m a -> EP w m a+withContext kds an x = withKds kds (withOffset an x)  -- --------------------------------------------------------------------- -- -- | Given an annotation associated with a specific SrcSpan, determines a new offset relative to the previous -- offset ---withOffset :: Annotation -> (EP a -> EP a)+withOffset :: (Monad m, Monoid w) => Annotation -> (EP w m a -> EP w m a) withOffset a =   local (\s -> s { epAnn = a }) @@ -235,7 +279,7 @@ -- --------------------------------------------------------------------- -- -- Necessary as there are destructive gets of Kds across scopes-withKds :: [(KeywordId, DeltaPos)] -> EP a -> EP a+withKds :: (Monad m, Monoid w) => [(KeywordId, DeltaPos)] -> EP w m a -> EP w m a withKds kd action = do   modify (\s -> s { epAnnKds = kd : epAnnKds s })   r <- action@@ -244,7 +288,7 @@  ------------------------------------------------------------------------ -setLayout :: EP () -> EP ()+setLayout :: (Monad m, Monoid w) => EP w m () -> EP w m () setLayout k = do   oldLHS <- gets epLHS   modify (\a -> a { epMarkLayout = True } )@@ -252,27 +296,27 @@                               , epLHS = oldLHS } )   k <* reset -getPos :: EP Pos+getPos :: (Monad m, Monoid w) => EP w m Pos getPos = gets epPos -setPos :: Pos -> EP ()+setPos :: (Monad m, Monoid w) => Pos -> EP w m () setPos l = modify (\s -> s {epPos = l})  -- |Get the current column offset-getLayoutOffset :: EP LayoutStartCol+getLayoutOffset :: (Monad m, Monoid w) => EP w m LayoutStartCol getLayoutOffset = gets epLHS  -- --------------------------------------------------------------------- -printStringAtMaybeAnn :: KeywordId -> String -> EP ()+printStringAtMaybeAnn :: (Monad m, Monoid w) => KeywordId -> String -> EP w m () printStringAtMaybeAnn an str = printStringAtMaybeAnnThen an str (return ()) -printStringAtMaybeAnnAll :: KeywordId -> String -> EP ()+printStringAtMaybeAnnAll :: (Monad m, Monoid w) => KeywordId -> String -> EP w m () printStringAtMaybeAnnAll an str = go   where     go = printStringAtMaybeAnnThen an str go -printStringAtMaybeAnnThen :: KeywordId -> String -> EP () -> EP ()+printStringAtMaybeAnnThen :: (Monad m, Monoid w) => KeywordId -> String -> EP w m () -> EP w m () printStringAtMaybeAnnThen an str next = do   annFinal <- getAnnFinal an   case (annFinal, an) of@@ -295,7 +339,7 @@ -- ---------------------------------------------------------------------  -- |destructive get, hence use an annotation once only-getAnnFinal :: KeywordId -> EP (Maybe ([(Comment, DeltaPos)], DeltaPos))+getAnnFinal :: (Monad m, Monoid w) => KeywordId -> EP w m (Maybe ([(Comment, DeltaPos)], DeltaPos)) getAnnFinal kw = do   kd <- gets epAnnKds   case kd of@@ -324,7 +368,7 @@  -- |This should be the final point where things are mode concrete, -- before output. Hence the point where comments can be inserted-printStringAtLsDelta :: [(Comment, DeltaPos)] -> DeltaPos -> String -> EP ()+printStringAtLsDelta :: (Monad m, Monoid w) => [(Comment, DeltaPos)] -> DeltaPos -> String -> EP w m () printStringAtLsDelta cs cl s = do   p <- getPos   colOffset <- getLayoutOffset@@ -340,7 +384,7 @@ isGoodDeltaWithOffset dp colOffset = isGoodDelta (DP (undelta (0,0) dp colOffset))  -- AZ:TODO: harvest the commonality between this and printStringAtLsDelta-printQueuedComment :: Comment -> DeltaPos -> EP ()+printQueuedComment :: (Monad m, Monoid w) => Comment -> DeltaPos -> EP w m () printQueuedComment Comment{commentContents} dp = do   p <- getPos   colOffset <- getLayoutOffset@@ -354,12 +398,12 @@ -- ---------------------------------------------------------------------  -- |non-destructive get-peekAnnFinal :: KeywordId -> EP (Maybe DeltaPos)+peekAnnFinal :: (Monad m, Monoid w) => KeywordId -> EP w m (Maybe DeltaPos) peekAnnFinal kw = do   (r, _) <- (\kd -> destructiveGetFirst kw ([], kd)) <$> gets (ghead "peekAnnFinal" . epAnnKds)   return (snd <$> r) -countAnnsEP :: KeywordId -> EP Int+countAnnsEP :: (Monad m, Monoid w) => KeywordId -> EP w m Int countAnnsEP an = length <$> peekAnnFinal an  -- ---------------------------------------------------------------------@@ -368,32 +412,39 @@ -- --------------------------------------------------------------------- -- Printing functions -printString :: Bool -> String -> EP ()+printString :: (Monad m, Monoid w) => Bool -> String -> EP w m () printString layout str = do   EPState{epPos = (l,c), epMarkLayout} <- get+  EPReader{epTokenPrint, epWhitespacePrint} <- ask   when (epMarkLayout && layout) (                       modify (\s -> s { epLHS = LayoutStartCol c, epMarkLayout = False } ))   setPos (l, c + length str)-  tell (mempty {output = Endo $ showString str })+  --+  -- tell (mempty {output = Endo $ showString str }) -newLine :: EP ()+  if not layout && c == 0+    then lift (epWhitespacePrint str) >>= \s -> tell (EPWriter { output = s})+    else lift (epTokenPrint str) >>= \s -> tell (EPWriter { output = s})+++newLine :: (Monad m, Monoid w) => EP w m () newLine = do     (l,_) <- getPos     printString False "\n"     setPos (l+1,1) -padUntil :: Pos -> EP ()+padUntil :: (Monad m, Monoid w) => Pos -> EP w m () padUntil (l,c) = do     (l1,c1) <- getPos     if | l1 == l && c1 <= c -> printString False $ replicate (c - c1) ' '        | l1 < l             -> newLine >> padUntil (l,c)        | otherwise          -> return () -printWhitespace :: Pos -> EP ()+printWhitespace :: (Monad m, Monoid w) => Pos -> EP w m () printWhitespace = padUntil -printCommentAt :: Pos -> String -> EP ()+printCommentAt :: (Monad m, Monoid w) => Pos -> String -> EP w m () printCommentAt p str = printWhitespace p >> printString False str -printStringAt :: Pos -> String -> EP ()+printStringAt :: (Monad m, Monoid w) => Pos -> String -> EP w m () printStringAt p str = printWhitespace p >> printString True str
src/Language/Haskell/GHC/ExactPrint/Transform.hs view
@@ -1,9 +1,11 @@ {-# LANGUAGE CPP #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE ViewPatterns #-} ----------------------------------------------------------------------------- -- |@@ -12,7 +14,7 @@ -- This module is currently under heavy development, and no promises are made -- about API stability. Use with care. ----- We weclome any feedback / contributions on this, as it is the main point of+-- We welcome any feedback / contributions on this, as it is the main point of -- the library. -- -----------------------------------------------------------------------------@@ -20,22 +22,41 @@         (         -- * The Transform Monad           Transform+        , TransformT(..)         , runTransform+        , runTransformFrom+        , runTransformFromT          -- * Transform monad operations         , logTr+        , logDataWithAnnsTr         , getAnnsT, putAnnsT, modifyAnnsT         , uniqueSrcSpanT -        , wrapSigT,wrapDeclT-        , pushDeclAnnT-        , decl2BindT,decl2SigT+        , cloneT          , getEntryDPT+        , setEntryDPT+        , transferEntryDPT+        , setPrecedingLinesDeclT+        , setPrecedingLinesT         , addSimpleAnnT+        , addTrailingCommaT+        , removeTrailingCommaT -        -- ** Managing lists, Transform monad+        -- ** Managing declarations, in Transform monad+        , HasTransform (..)         , HasDecls (..)+        , hasDeclsSybTransform+        , hsDeclsGeneric+        , hsDeclsPatBind, hsDeclsPatBindD+        , replaceDeclsPatBind, replaceDeclsPatBindD+        , modifyDeclsT+        , modifyValD+        -- *** Utility, does not manage layout+        , hsDeclsValBinds, replaceDeclsValbinds++        -- ** Managing lists, Transform monad         , insertAtStart         , insertAtEnd         , insertAfter@@ -53,16 +74,17 @@         -- * Operations         , isUniqueSrcSpan --        -- * Managing decls-        , declFun-         -- * Pure functions         , mergeAnns         , mergeAnnList         , setPrecedingLinesDecl         , setPrecedingLines         , getEntryDP+        , setEntryDP+        , transferEntryDP+        , addTrailingComma+        , wrapSig, wrapDecl+        , decl2Sig, decl2Bind          ) where @@ -79,9 +101,16 @@ import qualified Data.Generics as SYB  import Data.Data+import Data.List+import Data.Maybe  import qualified Data.Map as Map +import Data.Functor.Identity+-- import Control.Monad.Identity+import Control.Monad.State+import Control.Monad.Writer+ -- import Debug.Trace  ------------------------------------------------------------------------------@@ -89,29 +118,57 @@  -- | Monad type for updating the AST and managing the annotations at the same -- time. The W state is used to generate logging information if required.-type Transform a = RWS () [String] (Anns,Int) a+type Transform = TransformT Identity +-- |Monad transformer version of 'Transform' monad+newtype TransformT m a = TransformT { runTransformT :: RWST () [String] (Anns,Int) m a }+                deriving (Monad,Applicative,Functor+                         ,MonadReader ()+                         ,MonadWriter [String]+                         ,MonadState (Anns,Int)+                         -- ,MonadTrans+                         )+++ -- | Run a transformation in the 'Transform' monad, returning the updated -- annotations and any logging generated via 'logTr' runTransform :: Anns -> Transform a -> (a,(Anns,Int),[String])-runTransform ans f = runRWS f () (ans,0)+runTransform ans f = runTransformFrom 0 ans f +-- | Run a transformation in the 'Transform' monad, returning the updated+-- annotations and any logging generated via 'logTr', allocating any new+-- SrcSpans from the provided initial value.+runTransformFrom :: Int -> Anns -> Transform a -> (a,(Anns,Int),[String])+runTransformFrom seed ans f = runRWS (runTransformT f) () (ans,seed)++-- |Run a monad transformer stack for the 'TransformT' monad transformer+runTransformFromT :: (Monad m) => Int -> Anns -> TransformT m a -> m (a,(Anns,Int),[String])+runTransformFromT seed ans f = runRWST (runTransformT f) () (ans,seed)+ -- |Log a string to the output of the Monad-logTr :: String -> Transform ()+logTr :: (Monad m) => String -> TransformT m () logTr str = tell [str] +-- |Log a representation of the given AST with annotations to the output of the+-- Monad+logDataWithAnnsTr :: (Monad m) => (SYB.Data a) => String -> a -> TransformT m ()+logDataWithAnnsTr str ast = do+  anns <- getAnnsT+  logTr $ str ++ showAnnData anns 0 ast+ -- |Access the 'Anns' being modified in this transformation-getAnnsT :: Transform Anns+getAnnsT :: (Monad m) => TransformT m Anns getAnnsT = gets fst  -- |Replace the 'Anns' after any changes-putAnnsT :: Anns -> Transform ()+putAnnsT :: (Monad m) => Anns -> TransformT m () putAnnsT ans = do   (_,col) <- get   put (ans,col)  -- |Change the stored 'Anns'-modifyAnnsT :: (Anns -> Anns) -> Transform ()+modifyAnnsT :: (Monad m) => (Anns -> Anns) -> TransformT m () modifyAnnsT f = do   ans <- getAnnsT   putAnnsT (f ans)@@ -133,15 +190,24 @@ isUniqueSrcSpan ss = srcSpanStartLine ss == -1  -- ----------------------------------------------------------------------{---- TODO: I suspect this may be needed in future.- -- |Make a copy of an AST element, replacing the existing SrcSpans with new -- ones, and duplicating the matching annotations.-cloneT :: GHC.Located a -> Transform (GHC.Located a)-cloneT _ast = do-  error "Transform.cloneT undefined"--}+cloneT :: (Data a,Typeable a) => a -> Transform (a, [(GHC.SrcSpan, GHC.SrcSpan)])+cloneT ast = do+  runWriterT $ SYB.everywhereM (return `SYB.ext2M` replaceLocated) ast+  where+    replaceLocated :: forall loc a. (Typeable loc,Typeable a, Data a)+                    => (GHC.GenLocated loc a) -> WriterT [(GHC.SrcSpan, GHC.SrcSpan)] Transform (GHC.GenLocated loc a)+    replaceLocated (GHC.L l t) = do+      case cast l :: Maybe GHC.SrcSpan of+        Just ss -> do+          newSpan <- lift uniqueSrcSpanT+          lift $ modifyAnnsT (\anns -> case Map.lookup (mkAnnKey (GHC.L ss t)) anns of+                                  Nothing -> anns+                                  Just an -> Map.insert (mkAnnKey (GHC.L newSpan t)) an anns)+          tell [(ss, newSpan)]+          return $ fromJust . cast  $ GHC.L newSpan t+        Nothing -> return (GHC.L l t)  -- --------------------------------------------------------------------- @@ -178,113 +244,15 @@  -- --------------------------------------------------------------------- --- |Convert a 'GHC.LSig' into a 'GHC.LHsDecl', duplicating the 'GHC.LSig'--- annotation for the 'GHC.LHsDecl'. This needs to be set up so that the--- original annotation is restored after a 'pushDeclAnnT' call.-wrapSigT :: GHC.LSig GHC.RdrName -> Transform (GHC.LHsDecl GHC.RdrName)-wrapSigT d@(GHC.L _ s) = do-  newSpan <- uniqueSrcSpanT-  let-    f ans = case Map.lookup (mkAnnKey d) ans of-      Nothing -> ans-      Just ann ->-                  Map.insert (mkAnnKey (GHC.L newSpan s)) ann-                $ Map.insert (mkAnnKey (GHC.L newSpan (GHC.SigD s))) ann ans-  modifyAnnsT f-  return (GHC.L newSpan (GHC.SigD s))---- ------------------------------------------------------------------------- |Convert a 'GHC.LHsBind' into a 'GHC.LHsDecl', duplicating the 'GHC.LHsBind'--- annotation for the 'GHC.LHsDecl'. This needs to be set up so that the--- original annotation is restored after a 'pushDeclAnnT' call.-wrapDeclT :: GHC.LHsBind GHC.RdrName -> Transform (GHC.LHsDecl GHC.RdrName)-wrapDeclT d@(GHC.L _ s) = do-  newSpan <- uniqueSrcSpanT-  let-    f ans = case Map.lookup (mkAnnKey d) ans of-      Nothing -> ans-      Just ann ->-                  Map.insert (mkAnnKey (GHC.L newSpan           s )) ann-                $ Map.insert (mkAnnKey (GHC.L newSpan (GHC.ValD s))) ann ans-  modifyAnnsT f-  return (GHC.L newSpan (GHC.ValD s))---- ------------------------------------------------------------------------- |Copy the top level annotation to a new SrcSpan and the unwrapped decl. This--- is required so that 'decl2Sig' and 'decl2Bind' will produce values that have--- the required annotations.-pushDeclAnnT :: GHC.LHsDecl GHC.RdrName -> Transform (GHC.LHsDecl GHC.RdrName)-pushDeclAnnT ld@(GHC.L l decl) = do-  newSpan <- uniqueSrcSpanT-  let-    blend ann Nothing = ann-    blend ann (Just annd)-      = annd { annEntryDelta        = annEntryDelta ann-             , annPriorComments     = annPriorComments     ann  ++ annPriorComments     annd-             , annFollowingComments = annFollowingComments annd ++ annFollowingComments ann-             }-    duplicateAnn d ans =-      case Map.lookup (mkAnnKey ld) ans of-        Nothing -> error $ "pushDeclAnnT:no key found for:" ++ show (mkAnnKey ld)-        -- Nothing -> Anns ans-        Just ann -> Map.insert (mkAnnKey (GHC.L newSpan d))-                                      (blend ann (Map.lookup (mkAnnKey (GHC.L l d)) ans))-                                      ans-  case decl of-    GHC.TyClD d       -> modifyAnnsT (duplicateAnn d)-    GHC.InstD d       -> modifyAnnsT (duplicateAnn d)-    GHC.DerivD d      -> modifyAnnsT (duplicateAnn d)-    GHC.ValD d        -> modifyAnnsT (duplicateAnn d)-    GHC.SigD d        -> modifyAnnsT (duplicateAnn d)-    GHC.DefD d        -> modifyAnnsT (duplicateAnn d)-    GHC.ForD d        -> modifyAnnsT (duplicateAnn d)-    GHC.WarningD d    -> modifyAnnsT (duplicateAnn d)-    GHC.AnnD d        -> modifyAnnsT (duplicateAnn d)-    GHC.RuleD d       -> modifyAnnsT (duplicateAnn d)-    GHC.VectD d       -> modifyAnnsT (duplicateAnn d)-    GHC.SpliceD d     -> modifyAnnsT (duplicateAnn d)-    GHC.DocD d        -> modifyAnnsT (duplicateAnn d)-    GHC.RoleAnnotD d  -> modifyAnnsT (duplicateAnn d)-#if __GLASGOW_HASKELL__ < 711-    GHC.QuasiQuoteD d -> modifyAnnsT (duplicateAnn d)-#endif-  return (GHC.L newSpan decl)---- ------------------------------------------------------------------------- |Unwrap a 'GHC.LHsDecl' to its underlying 'GHC.LHsBind', transferring the top--- level annotation to a new unique 'GHC.SrcSpan' in the process.-decl2BindT :: GHC.LHsDecl GHC.RdrName -> Transform [GHC.LHsBind GHC.RdrName]-decl2BindT vd@(GHC.L _ (GHC.ValD d)) = do-  newSpan <- uniqueSrcSpanT-  logTr $ "decl2BindT:newSpan=" ++ showGhc newSpan-  let-    duplicateAnn ans =-      case Map.lookup (mkAnnKey vd) ans of-        Nothing -> ans-        Just ann -> Map.insert (mkAnnKey (GHC.L newSpan d)) ann ans-  modifyAnnsT duplicateAnn-  return [GHC.L newSpan d]-decl2BindT _ = return []+-- |Convert a 'GHC.LSig' into a 'GHC.LHsDecl'+wrapSig :: GHC.LSig GHC.RdrName -> GHC.LHsDecl GHC.RdrName+wrapSig (GHC.L l s) = GHC.L l (GHC.SigD s)  -- --------------------------------------------------------------------- --- |Unwrap a 'GHC.LHsDecl' to its underlying 'GHC.LSig', transferring the top--- level annotation to a new unique 'GHC.SrcSpan' in the process.-decl2SigT :: GHC.LHsDecl GHC.RdrName -> Transform [GHC.LSig GHC.RdrName]-decl2SigT vs@(GHC.L _ (GHC.SigD s)) = do-  newSpan <- uniqueSrcSpanT-  logTr $ "decl2SigT:newSpan=" ++ showGhc newSpan-  let-    duplicateAnn ans =-      case Map.lookup (mkAnnKey vs) ans of-        Nothing -> ans-        Just ann -> Map.insert (mkAnnKey (GHC.L newSpan s)) ann ans-  modifyAnnsT duplicateAnn-  return [GHC.L newSpan s]-decl2SigT _ = return []+-- |Convert a 'GHC.LHsBind' into a 'GHC.LHsDecl'+wrapDecl :: GHC.LHsBind GHC.RdrName -> GHC.LHsDecl GHC.RdrName+wrapDecl (GHC.L l s) = GHC.L l (GHC.ValD s)  -- --------------------------------------------------------------------- @@ -299,6 +267,20 @@  -- --------------------------------------------------------------------- +-- |Add a trailing comma annotation, unless there is already one+addTrailingCommaT :: (Data a) => GHC.Located a -> Transform ()+addTrailingCommaT ast = do+  modifyAnnsT (addTrailingComma ast (DP (0,0)))++-- ---------------------------------------------------------------------++-- |Remove a trailing comma annotation, if there is one one+removeTrailingCommaT :: (Data a) => GHC.Located a -> Transform ()+removeTrailingCommaT ast = do+  modifyAnnsT (removeTrailingComma ast)++-- ---------------------------------------------------------------------+ -- |'Transform' monad version of 'getEntryDP' getEntryDPT :: (Data a) => GHC.Located a -> Transform DeltaPos getEntryDPT ast = do@@ -307,6 +289,34 @@  -- --------------------------------------------------------------------- +-- |'Transform' monad version of 'getEntryDP'+setEntryDPT :: (Data a) => GHC.Located a -> DeltaPos -> Transform ()+setEntryDPT ast dp = do+  modifyAnnsT (setEntryDP ast dp)++-- ---------------------------------------------------------------------++-- |'Transform' monad version of 'transferEntryDP'+transferEntryDPT :: (Data a,Data b) => GHC.Located a -> GHC.Located b -> Transform ()+transferEntryDPT a b =+  modifyAnnsT (transferEntryDP a b)++-- ---------------------------------------------------------------------++-- |'Transform' monad version of 'setPrecedingLinesDecl'+setPrecedingLinesDeclT ::  GHC.LHsDecl GHC.RdrName -> Int -> Int -> Transform ()+setPrecedingLinesDeclT ld n c =+  modifyAnnsT (setPrecedingLinesDecl ld n c)++-- ---------------------------------------------------------------------++-- |'Transform' monad version of 'setPrecedingLines'+setPrecedingLinesT ::  (SYB.Data a) => GHC.Located a -> Int -> Int -> Transform ()+setPrecedingLinesT ld n c =+  modifyAnnsT (setPrecedingLines ld n c)++-- ---------------------------------------------------------------------+ -- | Left bias pair union mergeAnns :: Anns -> Anns -> Anns mergeAnns@@ -320,42 +330,15 @@ -- ---------------------------------------------------------------------  -- |Unwrap a HsDecl and call setPrecedingLines on it+-- ++AZ++ TODO: get rid of this, it is a synonym only setPrecedingLinesDecl :: GHC.LHsDecl GHC.RdrName -> Int -> Int -> Anns -> Anns-setPrecedingLinesDecl ld n c ans =-  declFun (\a -> setPrecedingLines a n c ans') ld-  where-    ans' = Map.insert (mkAnnKey ld) annNone ans--declFun :: (forall a . Data a => GHC.Located a -> b) -> GHC.LHsDecl GHC.RdrName -> b-declFun f (GHC.L l de) =-  case de of-      GHC.TyClD d       -> f (GHC.L l d)-      GHC.InstD d       -> f (GHC.L l d)-      GHC.DerivD d      -> f (GHC.L l d)-      GHC.ValD d        -> f (GHC.L l d)-      GHC.SigD d        -> f (GHC.L l d)-      GHC.DefD d        -> f (GHC.L l d)-      GHC.ForD d        -> f (GHC.L l d)-      GHC.WarningD d    -> f (GHC.L l d)-      GHC.AnnD d        -> f (GHC.L l d)-      GHC.RuleD d       -> f (GHC.L l d)-      GHC.VectD d       -> f (GHC.L l d)-      GHC.SpliceD d     -> f (GHC.L l d)-      GHC.DocD d        -> f (GHC.L l d)-      GHC.RoleAnnotD d  -> f (GHC.L l d)-#if __GLASGOW_HASKELL__ < 711-      GHC.QuasiQuoteD d -> f (GHC.L l d)-#endif+setPrecedingLinesDecl ld n c ans = setPrecedingLines ld n c ans  -- ---------------------------------------------------------------------  -- | Adjust the entry annotations to provide an `n` line preceding gap setPrecedingLines :: (SYB.Data a) => GHC.Located a -> Int -> Int -> Anns -> Anns-setPrecedingLines ast n c anne =-  Map.alter go (mkAnnKey ast) anne-  where-    go Nothing  = Just (annNone { annEntryDelta = DP (n, c) })-    go (Just a) = Just (a       { annEntryDelta = DP (n, c) })+setPrecedingLines ast n c anne = setEntryDP ast (DP (n,c)) anne  -- --------------------------------------------------------------------- @@ -369,20 +352,114 @@  -- --------------------------------------------------------------------- +-- |Set the true entry 'DeltaPos' from the annotation for a given AST+-- element. This is the 'DeltaPos' ignoring any comments.+setEntryDP :: (Data a) => GHC.Located a -> DeltaPos -> Anns -> Anns+setEntryDP ast dp anns =+  case Map.lookup (mkAnnKey ast) anns of+    Nothing  -> Map.insert (mkAnnKey ast) (annNone { annEntryDelta = dp}) anns+    Just ann -> Map.insert (mkAnnKey ast) (ann'    { annEntryDelta = annCommentEntryDelta ann' dp}) anns+      where+        ann' = setCommentEntryDP ann dp++-- ---------------------------------------------------------------------++-- |When setting an entryDP, the leading comment needs to be adjusted too+setCommentEntryDP :: Annotation -> DeltaPos -> Annotation+-- setCommentEntryDP ann dp = error $ "setCommentEntryDP:ann'=" ++ show ann'+setCommentEntryDP ann dp = ann'+  where+    ann' = case (annPriorComments ann) of+      [] -> ann+      [(pc,_)]     -> ann { annPriorComments = [(pc,dp)] }+      ((pc,_):pcs) -> ann { annPriorComments = ((pc,dp):pcs) }++-- ---------------------------------------------------------------------++-- |Take the annEntryDelta associated with the first item and associate it with the second.+-- Also transfer any comments occuring before it.+transferEntryDP :: (SYB.Data a, SYB.Data b) => GHC.Located a -> GHC.Located b -> Anns -> Anns+transferEntryDP a b anns = (const anns2) anns+  where+    maybeAnns = do -- Maybe monad+      anA <- Map.lookup (mkAnnKey a) anns+      anB <- Map.lookup (mkAnnKey b) anns+      let anB'  = Ann+            { annEntryDelta        = DP (0,0) -- Need to adjust for comments after+            , annPriorComments     = annPriorComments     anB+            , annFollowingComments = annFollowingComments anB+            , annsDP               = annsDP          anB+            , annSortKey           = annSortKey      anB+            , annCapturedSpan      = annCapturedSpan anB+            }+      return ((Map.insert (mkAnnKey b) anB' anns),annLeadingCommentEntryDelta anA)+    (anns',dp) = fromMaybe+                  (error $ "transferEntryDP: lookup failed (a,b)=" ++ show (mkAnnKey a,mkAnnKey b))+                  maybeAnns+    anns2 = setEntryDP b dp anns'++-- ---------------------------------------------------------------------++addTrailingComma :: (SYB.Data a) => GHC.Located a -> DeltaPos -> Anns -> Anns+addTrailingComma a dp anns =+  case Map.lookup (mkAnnKey a) anns of+    Nothing -> anns+    Just an ->+      case find isAnnComma (annsDP an) of+        Nothing -> Map.insert (mkAnnKey a) (an { annsDP = annsDP an ++ [(G GHC.AnnComma,dp)]}) anns+        Just _  -> anns+      where+        isAnnComma (G GHC.AnnComma,_) = True+        isAnnComma _                  = False++-- ---------------------------------------------------------------------++removeTrailingComma :: (SYB.Data a) => GHC.Located a -> Anns -> Anns+removeTrailingComma a anns =+  case Map.lookup (mkAnnKey a) anns of+    Nothing -> anns+    Just an ->+      case find isAnnComma (annsDP an) of+        Nothing -> anns+        Just _  -> Map.insert (mkAnnKey a) (an { annsDP = filter (not.isAnnComma) (annsDP an) }) anns+      where+        isAnnComma (G GHC.AnnComma,_) = True+        isAnnComma _                  = False++-- ---------------------------------------------------------------------++-- |The relatavise phase puts all comments appearing between the end of one AST+-- item and the beginning of the next as 'annPriorComments' for the second one.+-- This function takes two adjacent AST items and moves any 'annPriorComments'+-- from the second one to the 'annFollowingComments' of the first if they belong+-- to it instead. This is typically required before deleting or duplicating+-- either of the AST elements.+balanceComments :: (Data a,Data b) => GHC.Located a -> GHC.Located b -> Transform ()+balanceComments first second = do+  -- ++AZ++ : replace the nested casts with appropriate SYB.gmapM+  -- logTr $ "balanceComments entered"+  -- logDataWithAnnsTr "first" first+  case cast first :: Maybe (GHC.LHsDecl GHC.RdrName) of+    Just (GHC.L l (GHC.ValD fb@(GHC.FunBind{}))) -> do+      balanceCommentsFB (GHC.L l fb) second+    _ -> case cast first :: Maybe (GHC.LHsBind GHC.RdrName) of+      Just fb'@(GHC.L _ (GHC.FunBind{})) -> do+        balanceCommentsFB fb' second+      _ -> balanceComments' first second+ -- |Prior to moving an AST element, make sure any trailing comments belonging to -- it are attached to it, and not the following element. Of necessity this is a -- heuristic process, to be tuned later. Possibly a variant should be provided -- with a passed-in decision function.-balanceComments :: (Data a,Data b) => GHC.Located a -> GHC.Located b -> Transform ()-balanceComments first second = do+balanceComments' :: (Data a,Data b) => GHC.Located a -> GHC.Located b -> Transform ()+balanceComments' first second = do   let     k1 = mkAnnKey first     k2 = mkAnnKey second     moveComments p ans = ans'       where-        an1 = gfromJust "balanceComments k1" $ Map.lookup k1 ans-        an2 = gfromJust "balanceComments k2" $ Map.lookup k2 ans-        -- cs1b = annPriorComments     an1+        an1 = gfromJust "balanceComments' k1" $ Map.lookup k1 ans+        an2 = gfromJust "balanceComments' k2" $ Map.lookup k2 ans         cs1f = annFollowingComments an1         cs2b = annPriorComments an2         (move,stay) = break p cs2b@@ -394,13 +471,24 @@    modifyAnnsT (moveComments simpleBreak) +-- |Once 'balanceComments' has been called to move trailing comments to a+-- 'GHC.FunBind', these need to be pushed down from the top level to the last+-- 'GHC.Match' if that 'GHC.Match' needs to be manipulated.+balanceCommentsFB :: (Data b) => GHC.LHsBind GHC.RdrName -> GHC.Located b -> Transform ()+balanceCommentsFB (GHC.L _ (GHC.FunBind _ _ (GHC.MG matches _ _ _) _ _ _)) second = do+  -- logTr $ "balanceCommentsFB entered"+  balanceComments' (last matches) second+balanceCommentsFB f s = balanceComments' f s+ -- --------------------------------------------------------------------- + -- |After moving an AST element, make sure any comments that may belong -- with the following element in fact do. Of necessity this is a heuristic -- process, to be tuned later. Possibly a variant should be provided with a -- passed-in decision function.-balanceTrailingComments :: (Data a,Data b) => GHC.Located a -> GHC.Located b -> Transform [(Comment, DeltaPos)]+balanceTrailingComments :: (Monad m) => (Data a,Data b) => GHC.Located a -> GHC.Located b+                        -> TransformT m [(Comment, DeltaPos)] balanceTrailingComments first second = do   let     k1 = mkAnnKey first@@ -412,16 +500,10 @@         cs1f = annFollowingComments an1         (move,stay) = break p cs1f         an1' = an1 { annFollowingComments = stay }-        an2' = an2 -- { annPriorComments = move ++ cs2b }-        -- an1' = an1 { annFollowingComments = [] }-        -- an2' = an2 { annPriorComments = cs1f ++ cs2b }-        ans' = Map.insert k1 an1' $ Map.insert k2 an2' ans-        -- ans' = error $ "balanceTrailingComments:(k1,k2)=" ++ showGhc (k1,k2)-        -- ans' = error $ "balanceTrailingComments:(cs1b,cs1f,cs2b,annFollowingComments an2)=" ++ showGhc (cs1b,cs1f,cs2b,annFollowingComments an2)+        ans' = Map.insert k1 an1' $ Map.insert k2 an2 ans      simpleBreak (_,DP (r,_c)) = r > 0 -  -- modifyAnnsT (modifyKeywordDeltas (moveComments simpleBreak))   ans <- getAnnsT   let (ans',mov) = moveComments simpleBreak ans   putAnnsT ans'@@ -429,6 +511,7 @@  -- --------------------------------------------------------------------- +-- ++AZ++ TODO: This needs to be renamed/reworked, based on what it actually gets used for -- |Move any 'annFollowingComments' values from the 'Annotation' associated to -- the first parameter to that of the second. moveTrailingComments :: (Data a,Data b)@@ -451,20 +534,21 @@  -- --------------------------------------------------------------------- +-- |Insert a declaration into an AST element having sub-declarations+-- (@HasDecls@) according to the given location function. insertAt :: (Data ast, HasDecls (GHC.Located ast))-              => (GHC.SrcSpan -> [GHC.SrcSpan] -> [GHC.SrcSpan])+              => (GHC.LHsDecl GHC.RdrName+                  -> [GHC.LHsDecl GHC.RdrName]+                  -> [GHC.LHsDecl GHC.RdrName])               -> GHC.Located ast               -> GHC.LHsDecl GHC.RdrName               -> Transform (GHC.Located ast)-insertAt f m decl = do-  let newKey = GHC.getLoc decl-      modKey = mkAnnKey m-      newValue a@Ann{..} = a { annSortKey = f newKey <$> annSortKey }-  oldDecls <- hsDecls m-  modifyAnnsT (Map.adjust newValue modKey)--  replaceDecls m (decl : oldDecls )+insertAt f t decl = do+  oldDecls <- hsDecls t+  replaceDecls t (f decl oldDecls) +-- |Insert a declaration at the beginning or end of the subdecls of the given+-- AST item insertAtStart, insertAtEnd :: (Data ast, HasDecls (GHC.Located ast))               => GHC.Located ast               -> GHC.LHsDecl GHC.RdrName@@ -473,31 +557,38 @@ insertAtStart = insertAt (:) insertAtEnd   = insertAt (\x xs -> xs ++ [x]) +-- |Insert a declaration at a specific location in the subdecls of the given+-- AST item insertAfter, insertBefore :: (Data ast, HasDecls (GHC.Located ast))                           => GHC.Located old                           -> GHC.Located ast                           -> GHC.LHsDecl GHC.RdrName                           -> Transform (GHC.Located ast)--- insertAfter (mkAnnKey -> k) = insertAt findAfter insertAfter (GHC.getLoc -> k) = insertAt findAfter   where     findAfter x xs =-      let (fs, b:bs) = span (/= k) xs+      let (fs, b:bs) = span (\(GHC.L l _) -> l /= k) xs       in fs ++ (b : x : bs) insertBefore (GHC.getLoc -> k) = insertAt findBefore   where     findBefore x xs =-      let (fs, bs) = span (/= k) xs+      let (fs, bs) = span (\(GHC.L l _) -> l /= k) xs       in fs ++ (x : bs) --- ---------------------------------------------------------------------+-- =====================================================================+-- start of HasDecls instances+-- ===================================================================== +-- |Provide a means to get and process the immediate child declartions of a+-- given AST element. class (Data t) => HasDecls t where+-- ++AZ++: TODO: add tests to confirm that hsDecls followed by replaceDecls is idempotent      -- | Return the 'GHC.HsDecl's that are directly enclosed in the     -- given syntax phrase. They are always returned in the wrapped 'GHC.HsDecl'-    -- form, even if orginating in local decls.-    hsDecls :: t -> Transform [GHC.LHsDecl GHC.RdrName]+    -- form, even if orginating in local decls. This is safe, as annotations+    -- never attach to the wrapper, only to the wrapped item.+    hsDecls :: (Monad m) => t -> TransformT m [GHC.LHsDecl GHC.RdrName]      -- | Replace the directly enclosed decl list by the given     --  decl list. Runs in the 'Transform' monad to be able to update list order@@ -518,7 +609,7 @@     --   where     --     nn = 2     -- @-    replaceDecls :: t -> [GHC.LHsDecl GHC.RdrName] -> Transform t+    replaceDecls :: (Monad m) => t -> [GHC.LHsDecl GHC.RdrName] -> TransformT m t  -- --------------------------------------------------------------------- @@ -526,40 +617,20 @@   hsDecls (GHC.L _ (GHC.HsModule _mn _exps _imps decls _ _)) = return decls   replaceDecls m@(GHC.L l (GHC.HsModule mn exps imps _decls deps haddocks)) decls     = do+        logTr "replaceDecls LHsModule"         modifyAnnsT (captureOrder m decls)         return (GHC.L l (GHC.HsModule mn exps imps decls deps haddocks))  -- --------------------------------------------------------------------- -instance HasDecls (GHC.MatchGroup GHC.RdrName (GHC.LHsExpr GHC.RdrName)) where-  hsDecls (GHC.MG matches _ _ _) = hsDecls matches--  replaceDecls (GHC.MG matches a r o) newDecls-    = do-        matches' <- replaceDecls matches newDecls-        return (GHC.MG matches' a r o)---- -----------------------------------------------------------------------instance HasDecls [GHC.LMatch GHC.RdrName (GHC.LHsExpr GHC.RdrName)] where-  hsDecls ms = do-    ds <- mapM hsDecls ms-    return (concat ds)--  replaceDecls [] _        = error "empty match list in replaceDecls [GHC.LMatch GHC.Name]"-  replaceDecls ms newDecls-    = do-        -- ++AZ++: TODO: this one looks dodgy-        m' <- replaceDecls (ghead "replaceDecls" ms) newDecls-        return (m':tail ms)---- ---------------------------------------------------------------------- instance HasDecls (GHC.LMatch GHC.RdrName (GHC.LHsExpr GHC.RdrName)) where-  hsDecls (GHC.L _ (GHC.Match _ _ _ grhs)) = hsDecls grhs+  hsDecls d@(GHC.L _ (GHC.Match _ _ _ (GHC.GRHSs _ lb))) = do+    decls <- hsDeclsValBinds lb+    orderedDecls d decls    replaceDecls m@(GHC.L l (GHC.Match mf p t (GHC.GRHSs rhs binds))) []     = do+        logTr "replaceDecls LMatch"         let           noWhere (G GHC.AnnWhere,_) = False           noWhere _                  = True@@ -569,18 +640,19 @@               Nothing -> error "wtf"               Just ann -> Map.insert (mkAnnKey m) ann1 mkds                 where-                  ann1 = ann { annsDP = filter noWhere (annsDP ann) +                  ann1 = ann { annsDP = filter noWhere (annsDP ann)                                  }         modifyAnnsT removeWhere -        binds' <- replaceDecls binds []+        binds' <- replaceDeclsValbinds binds []         return (GHC.L l (GHC.Match mf p t (GHC.GRHSs rhs binds')))    replaceDecls m@(GHC.L l (GHC.Match mf p t (GHC.GRHSs rhs binds))) newBinds     = do+        logTr "replaceDecls LMatch"         -- Need to throw in a fresh where clause if the binds were empty,         -- in the annotations.-        newBinds2 <- case binds of+        case binds of           GHC.EmptyLocalBinds -> do             let               addWhere mkds =@@ -591,172 +663,345 @@                       ann1 = ann { annsDP = annsDP ann ++ [(G GHC.AnnWhere,DP (1,2))]                                  }             modifyAnnsT addWhere-            newBinds' <- mapM pushDeclAnnT newBinds-            modifyAnnsT (captureOrderAnnKey (mkAnnKey m) newBinds')-            modifyAnnsT (setPrecedingLinesDecl (ghead "LMatch.replaceDecls" newBinds') 1 4)-            return newBinds'+            modifyAnnsT (setPrecedingLines (ghead "LMatch.replaceDecls" newBinds) 1 4) -          _ -> do-            -- ++AZ++ TODO: move the duplicate code out of the case statement-            newBinds' <- mapM pushDeclAnnT newBinds-            modifyAnnsT (captureOrderAnnKey (mkAnnKey m) newBinds')-            return newBinds'+            -- only move the comment if the original where clause was empty.+            toMove <- balanceTrailingComments m m+            insertCommentBefore (mkAnnKey m) toMove (matchApiAnn GHC.AnnWhere)+          _ -> return () -        binds' <- replaceDecls binds newBinds2+        modifyAnnsT (captureOrderAnnKey (mkAnnKey m) newBinds)+        binds' <- replaceDeclsValbinds binds newBinds+        -- logDataWithAnnsTr "Match.replaceDecls:binds'" binds'         return (GHC.L l (GHC.Match mf p t (GHC.GRHSs rhs binds')))  -- --------------------------------------------------------------------- -instance HasDecls (GHC.GRHSs GHC.RdrName (GHC.LHsExpr GHC.RdrName)) where-  hsDecls (GHC.GRHSs _ lb) = hsDecls lb+instance HasDecls (GHC.LHsExpr GHC.RdrName) where+  hsDecls ls@(GHC.L _ (GHC.HsLet decls _ex)) = do+    ds <- hsDeclsValBinds decls+    orderedDecls ls ds+  hsDecls _                               = return [] -  replaceDecls (GHC.GRHSs rhss b) new+  replaceDecls e@(GHC.L l (GHC.HsLet decls ex)) newDecls     = do-        b' <- replaceDecls b new-        return (GHC.GRHSs rhss b')+        logTr "replaceDecls HsLet"+        modifyAnnsT (captureOrder e newDecls)+        decls' <- replaceDeclsValbinds decls newDecls+        return (GHC.L l (GHC.HsLet decls' ex))+  replaceDecls (GHC.L l (GHC.HsPar e)) newDecls+    = do+        logTr "replaceDecls HsPar"+        e' <- replaceDecls e newDecls+        return (GHC.L l (GHC.HsPar e'))+  replaceDecls old _new = error $ "replaceDecls (GHC.LHsExpr GHC.RdrName) undefined for:" ++ showGhc old  -- --------------------------------------------------------------------- -instance HasDecls (GHC.HsLocalBinds GHC.RdrName) where-  hsDecls lb = case lb of-    GHC.HsValBinds (GHC.ValBindsIn bs sigs) -> do-      bds <- mapM wrapDeclT (GHC.bagToList bs)-      sds <- mapM wrapSigT sigs-      -- ++AZ++ TODO: return in annotated order-      return (bds ++ sds)-    GHC.HsValBinds (GHC.ValBindsOut _ _) -> error $ "hsDecls.ValbindsOut not valid"-    GHC.HsIPBinds _     -> return []-    GHC.EmptyLocalBinds -> return []+-- | Extract the immediate declarations for a 'GHC.PatBind' wrapped in a 'GHC.ValD'. This+-- cannot be a member of 'HasDecls' because a 'GHC.FunBind' is not idempotent+-- for 'hsDecls' \/ 'replaceDecls'. 'hsDeclsPatBindD' \/ 'replaceDeclsPatBindD' is+-- idempotent.+hsDeclsPatBindD :: (Monad m) => GHC.LHsDecl GHC.RdrName -> TransformT m [GHC.LHsDecl GHC.RdrName]+hsDeclsPatBindD (GHC.L l (GHC.ValD d)) = hsDeclsPatBind (GHC.L l d)+hsDeclsPatBindD x = error $ "hsDeclsPatBindD called for:" ++ showGhc x -  replaceDecls (GHC.HsValBinds _b) new-    = do-        let decs = GHC.listToBag $ concatMap decl2Bind new-        let sigs = concatMap decl2Sig new-        return (GHC.HsValBinds (GHC.ValBindsIn decs sigs))+-- | Extract the immediate declarations for a 'GHC.PatBind'. This+-- cannot be a member of 'HasDecls' because a 'GHC.FunBind' is not idempotent+-- for 'hsDecls' \/ 'replaceDecls'. 'hsDeclsPatBind' \/ 'replaceDeclsPatBind' is+-- idempotent.+hsDeclsPatBind :: (Monad m) => GHC.LHsBind GHC.RdrName -> TransformT m [GHC.LHsDecl GHC.RdrName]+hsDeclsPatBind d@(GHC.L _ (GHC.PatBind _ (GHC.GRHSs _grhs lb) _ _ _)) = do+  decls <- hsDeclsValBinds lb+  orderedDecls d decls+hsDeclsPatBind x = error $ "hsDeclsPatBind called for:" ++ showGhc x -  replaceDecls (GHC.HsIPBinds _b) _new    = error "undefined replaceDecls HsIPBinds"+-- ------------------------------------- -  replaceDecls (GHC.EmptyLocalBinds) new+-- | Replace the immediate declarations for a 'GHC.PatBind' wrapped in a 'GHC.ValD'. This+-- cannot be a member of 'HasDecls' because a 'GHC.FunBind' is not idempotent+-- for 'hsDecls' \/ 'replaceDecls'. 'hsDeclsPatBindD' \/ 'replaceDeclsPatBindD' is+-- idempotent.+replaceDeclsPatBindD :: (Monad m) => GHC.LHsDecl GHC.RdrName -> [GHC.LHsDecl GHC.RdrName]+                     -> TransformT m (GHC.LHsDecl GHC.RdrName)+replaceDeclsPatBindD (GHC.L l (GHC.ValD d)) newDecls = do+  (GHC.L _ d') <- replaceDeclsPatBind (GHC.L l d) newDecls+  return (GHC.L l (GHC.ValD d'))+replaceDeclsPatBindD x _ = error $ "replaceDeclsPatBindD called for:" ++ showGhc x++-- | Replace the immediate declarations for a 'GHC.PatBind'. This+-- cannot be a member of 'HasDecls' because a 'GHC.FunBind' is not idempotent+-- for 'hsDecls' \/ 'replaceDecls'. 'hsDeclsPatBind' \/ 'replaceDeclsPatBind' is+-- idempotent.+replaceDeclsPatBind :: (Monad m) => GHC.LHsBind GHC.RdrName -> [GHC.LHsDecl GHC.RdrName]+                    -> TransformT m (GHC.LHsBind GHC.RdrName)+replaceDeclsPatBind p@(GHC.L l (GHC.PatBind a (GHC.GRHSs rhss binds) b c d)) newDecls     = do-        let newBinds = map decl2Bind new-            newSigs  = map decl2Sig  new-        ans <- getAnnsT-        logTr $ "replaceDecls:newBinds=" ++ showAnnData ans 0 newBinds-        let decs = GHC.listToBag $ concat newBinds-        let sigs = concat newSigs-        return (GHC.HsValBinds (GHC.ValBindsIn decs sigs))+        logTr "replaceDecls PatBind"+        -- Need to throw in a fresh where clause if the binds were empty,+        -- in the annotations.+        case binds of+          GHC.EmptyLocalBinds -> do+            let+              addWhere mkds =+                case Map.lookup (mkAnnKey p) mkds of+                  Nothing -> error "wtf"+                  Just ann -> Map.insert (mkAnnKey p) ann1 mkds+                    where+                      ann1 = ann { annsDP = annsDP ann ++ [(G GHC.AnnWhere,DP (1,2))]+                                 }+            modifyAnnsT addWhere+            modifyAnnsT (setPrecedingLines (ghead "LMatch.replaceDecls" newDecls) 1 4) +          _ -> return ()++        modifyAnnsT (captureOrderAnnKey (mkAnnKey p) newDecls)+        binds' <- replaceDeclsValbinds binds newDecls+        return (GHC.L l (GHC.PatBind a (GHC.GRHSs rhss binds') b c d))+replaceDeclsPatBind x _ = error $ "replaceDeclsPatBind called for:" ++ showGhc x+ -- --------------------------------------------------------------------- -instance HasDecls (GHC.LHsExpr GHC.RdrName) where-  hsDecls (GHC.L _ (GHC.HsLet decls _ex)) = hsDecls decls-  hsDecls _                               = return []+instance HasDecls (GHC.LStmt GHC.RdrName (GHC.LHsExpr GHC.RdrName)) where+  hsDecls ls@(GHC.L _ (GHC.LetStmt lb))       = do+    decls <- hsDeclsValBinds lb+    orderedDecls ls decls+  hsDecls (GHC.L _ (GHC.LastStmt e _))        = hsDecls e+  hsDecls (GHC.L _ (GHC.BindStmt _pat e _ _)) = hsDecls e+  hsDecls (GHC.L _ (GHC.BodyStmt e _ _ _))    = hsDecls e+  hsDecls _                                   = return [] -  replaceDecls (GHC.L l (GHC.HsLet decls ex)) newDecls+  replaceDecls s@(GHC.L l (GHC.LetStmt lb)) newDecls     = do-        decls' <- replaceDecls decls newDecls-        return (GHC.L l (GHC.HsLet decls' ex))-  replaceDecls old _new = error $ "replaceDecls (GHC.LHsExpr GHC.RdrName) undefined for:" ++ showGhc old+        modifyAnnsT (captureOrder s newDecls)+        lb' <- replaceDeclsValbinds lb newDecls+        return (GHC.L l (GHC.LetStmt lb'))+  replaceDecls (GHC.L l (GHC.LastStmt e se)) newDecls+    = do+        e' <- replaceDecls e newDecls+        return (GHC.L l (GHC.LastStmt e' se))+  replaceDecls (GHC.L l (GHC.BindStmt pat e a b)) newDecls+    = do+      e' <- replaceDecls e newDecls+      return (GHC.L l (GHC.BindStmt pat e' a b))+  replaceDecls (GHC.L l (GHC.BodyStmt e a b c)) newDecls+    = do+      e' <- replaceDecls e newDecls+      return (GHC.L l (GHC.BodyStmt e' a b c))+  replaceDecls x _newDecls = return x +-- =====================================================================+-- end of HasDecls instances+-- =====================================================================+ -- --------------------------------------------------------------------- -instance HasDecls (GHC.LHsBinds GHC.RdrName) where-  hsDecls binds = hsDecls $ GHC.bagToList binds-  replaceDecls old _new = error $ "replaceDecls (GHC.LHsBinds name) undefined for:" ++ (showGhc old)+-- |Do a transformation on an AST fragment by providing a function to process+-- the general case and one specific for a 'GHC.LHsBind'. This is required+-- because a 'GHC.FunBind' may have multiple 'GHC.Match' items, so we cannot+-- gurantee that 'replaceDecls' after 'hsDecls' is idempotent.+hasDeclsSybTransform :: (SYB.Data t2, SYB.Typeable t2,Monad m)+       => (forall t. HasDecls t => t -> m t)+             -- ^Worker function for the general case+       -> (GHC.LHsBind GHC.RdrName -> m (GHC.LHsBind GHC.RdrName))+             -- ^Worker function for FunBind/PatBind+       -> t2 -- ^Item to be updated+       -> m t2+hasDeclsSybTransform workerHasDecls workerBind t = trf t+  where+    trf = SYB.mkM   parsedSource+         `SYB.extM` lmatch+         `SYB.extM` lexpr+         `SYB.extM` lstmt+         `SYB.extM` lhsbind+         `SYB.extM` lvald +    parsedSource (p::GHC.ParsedSource) = workerHasDecls p++    lmatch (lm::GHC.LMatch GHC.RdrName (GHC.LHsExpr GHC.RdrName))+      = workerHasDecls lm++    lexpr (le::GHC.LHsExpr GHC.RdrName)+      = workerHasDecls le++    lstmt (d::GHC.LStmt GHC.RdrName (GHC.LHsExpr GHC.RdrName))+      = workerHasDecls d++    lhsbind (b@(GHC.L _ GHC.FunBind{}):: GHC.LHsBind GHC.RdrName)+      = workerBind b+    lhsbind b@(GHC.L _ GHC.PatBind{})+      = workerBind b+    lhsbind x = return x++    lvald (GHC.L l (GHC.ValD d)) = do+      (GHC.L _ d') <- lhsbind (GHC.L l d)+      return (GHC.L l (GHC.ValD d'))+    lvald x = return x+ -- --------------------------------------------------------------------- -instance HasDecls [GHC.LHsBind GHC.RdrName] where-  hsDecls bs = mapM wrapDeclT bs+-- |A 'GHC.FunBind' wraps up one or more 'GHC.Match' items. 'hsDecls' cannot+-- return anything for these as there is not meaningful 'replaceDecls' for it.+-- This function provides a version of 'hsDecls' that returns the 'GHC.FunBind'+-- decls too, where they are needed for analysis only.+hsDeclsGeneric :: (SYB.Data t,SYB.Typeable t) => t -> Transform [GHC.LHsDecl GHC.RdrName]+hsDeclsGeneric t = q t+  where+    q = return []+        `SYB.mkQ`  parsedSource+        `SYB.extQ` lmatch+        `SYB.extQ` lexpr+        `SYB.extQ` lstmt+        `SYB.extQ` lhsbind+        `SYB.extQ` lhsbindd+        `SYB.extQ` localbinds -  replaceDecls _bs newDecls-    = do-        return $ concatMap decl2Bind newDecls+    parsedSource (p::GHC.ParsedSource) = hsDecls p +    lmatch (lm::GHC.LMatch GHC.RdrName (GHC.LHsExpr GHC.RdrName)) = hsDecls lm++    lexpr (le::GHC.LHsExpr GHC.RdrName) = hsDecls le++    lstmt (d::GHC.LStmt GHC.RdrName (GHC.LHsExpr GHC.RdrName)) = hsDecls d++    -- ---------------------------------++    lhsbind :: GHC.LHsBind GHC.RdrName -> Transform [GHC.LHsDecl GHC.RdrName]+    lhsbind (GHC.L _ (GHC.FunBind _ _ (GHC.MG matches _ _ _) _ _ _)) = do+        dss <- mapM hsDecls matches+        return (concat dss)+    lhsbind p@(GHC.L _ (GHC.PatBind{})) = do+      hsDeclsPatBind p+    lhsbind _ = return []++    -- ---------------------------------++    lhsbindd (GHC.L l (GHC.ValD d)) = lhsbind (GHC.L l d)+    lhsbindd _ = return []++    -- ---------------------------------++    localbinds :: GHC.HsLocalBinds GHC.RdrName -> Transform [GHC.LHsDecl GHC.RdrName]+    localbinds d = hsDeclsValBinds d+ -- --------------------------------------------------------------------- -instance HasDecls (GHC.LHsBind GHC.RdrName) where-  hsDecls (GHC.L _ (GHC.FunBind _ _ matches _ _ _)) = hsDecls matches-  hsDecls (GHC.L _ (GHC.PatBind _ rhs _ _ _))       = hsDecls rhs-  hsDecls (GHC.L _ (GHC.VarBind _ rhs _))           = hsDecls rhs-  hsDecls (GHC.L _ (GHC.AbsBinds _ _ _ _ binds))    = hsDecls binds-  hsDecls (GHC.L _ (GHC.PatSynBind _))      = error "hsDecls: PatSynBind to implement"+-- |Look up the annotated order and sort the decls accordingly+orderedDecls :: (Data a,Monad m) => GHC.Located a -> [GHC.LHsDecl GHC.RdrName] -> TransformT m [GHC.LHsDecl GHC.RdrName]+orderedDecls parent decls = do+  ans <- getAnnsT+  case getAnnotationEP parent ans of+    Nothing -> error $ "orderedDecls:no annotation for:" ++ showAnnData emptyAnns 0 parent+    Just ann -> case annSortKey ann of+      Nothing -> do+        return decls+      Just keys -> do+        let ds = map (\s -> (GHC.getLoc s,s)) decls+            ordered = orderByKey ds keys+        return ordered +-- --------------------------------------------------------------------- -  replaceDecls (GHC.L l fn@(GHC.FunBind a b (GHC.MG matches f g h) c d e)) newDecls-    = do-        matches' <- replaceDecls matches newDecls-        case matches' of-          [] -> return () -- Should be impossible-          ms -> do-            case (GHC.grhssLocalBinds $ GHC.m_grhss $ GHC.unLoc $ last matches) of-              GHC.EmptyLocalBinds -> do-                -- only move the comment if the original where clause was empty.-                toMove <- balanceTrailingComments (GHC.L l (GHC.ValD fn)) (last matches')-                insertCommentBefore (mkAnnKey $ last ms) toMove (matchApiAnn GHC.AnnWhere)-              lbs -> do-                decs <- hsDecls lbs-                balanceComments (last decs) (GHC.L l (GHC.ValD fn))-        return (GHC.L l (GHC.FunBind a b (GHC.MG matches' f g h) c d e))+-- | Utility function for extracting decls from 'GHC.HsLocalBinds'. Use with+-- care, as this does not necessarily return the declarations in order, the+-- ordering should be done by the calling function from the 'GHC.HsLocalBinds'+-- context in the AST.+hsDeclsValBinds :: (Monad m) => GHC.HsLocalBinds GHC.RdrName -> TransformT m [GHC.LHsDecl GHC.RdrName]+hsDeclsValBinds lb = case lb of+    GHC.HsValBinds (GHC.ValBindsIn bs sigs) -> do+      let+        bds = map wrapDecl (GHC.bagToList bs)+        sds = map wrapSig sigs+      return (bds ++ sds)+    GHC.HsValBinds (GHC.ValBindsOut _ _) -> error $ "hsDecls.ValbindsOut not valid"+    GHC.HsIPBinds _     -> return []+    GHC.EmptyLocalBinds -> return [] -  replaceDecls (GHC.L l (GHC.PatBind a rhs b c d)) newDecls-    = do-        rhs' <- replaceDecls rhs newDecls-        return (GHC.L l (GHC.PatBind a rhs' b c d))-  replaceDecls (GHC.L l (GHC.VarBind a rhs b)) newDecls+-- | Utility function for returning decls to 'GHC.HsLocalBinds'. Use with+-- care, as this does not manage the declaration order, the+-- ordering should be done by the calling function from the 'GHC.HsLocalBinds'+-- context in the AST.+replaceDeclsValbinds :: (Monad m)+                     => GHC.HsLocalBinds GHC.RdrName -> [GHC.LHsDecl GHC.RdrName]+                     -> TransformT m (GHC.HsLocalBinds GHC.RdrName)+replaceDeclsValbinds _ [] = do+  return (GHC.EmptyLocalBinds)+replaceDeclsValbinds (GHC.HsValBinds _b) new     = do-        rhs' <- replaceDecls rhs newDecls-        return (GHC.L l (GHC.VarBind a rhs' b))-  replaceDecls (GHC.L l (GHC.AbsBinds a b c d binds)) newDecls+        logTr "replaceDecls HsLocalBinds"+        let decs = GHC.listToBag $ concatMap decl2Bind new+        let sigs = concatMap decl2Sig new+        return (GHC.HsValBinds (GHC.ValBindsIn decs sigs))+replaceDeclsValbinds (GHC.HsIPBinds _b) _new    = error "undefined replaceDecls HsIPBinds"+replaceDeclsValbinds (GHC.EmptyLocalBinds) new     = do-        binds' <- replaceDecls binds newDecls-        return (GHC.L l (GHC.AbsBinds a b c d binds'))-  replaceDecls (GHC.L _ (GHC.PatSynBind _)) _ = error "replaceDecls: PatSynBind to implement"+        logTr "replaceDecls HsLocalBinds"+        let newBinds = map decl2Bind new+            newSigs  = map decl2Sig  new+        let decs = GHC.listToBag $ concat newBinds+        let sigs = concat newSigs+        return (GHC.HsValBinds (GHC.ValBindsIn decs sigs))  -- --------------------------------------------------------------------- -instance HasDecls (GHC.Stmt GHC.RdrName (GHC.LHsExpr GHC.RdrName)) where-  hsDecls (GHC.LetStmt lb)          = hsDecls lb-  hsDecls (GHC.LastStmt e _)        = hsDecls e-  hsDecls (GHC.BindStmt _pat e _ _) = hsDecls e-  hsDecls (GHC.BodyStmt e _ _ _)    = hsDecls e-  hsDecls _                         = return []+type Decl  = GHC.LHsDecl GHC.RdrName+type Match = GHC.LMatch GHC.RdrName (GHC.LHsExpr GHC.RdrName) -  replaceDecls (GHC.LetStmt lb) newDecls-    = do-      lb' <- replaceDecls lb newDecls-      return (GHC.LetStmt lb')-  replaceDecls (GHC.LastStmt e se) newDecls-    = do-        e' <- replaceDecls e newDecls-        return (GHC.LastStmt e' se)-  replaceDecls (GHC.BindStmt pat e a b) newDecls-    = do-      e' <- replaceDecls e newDecls-      return (GHC.BindStmt pat e' a b)-  replaceDecls (GHC.BodyStmt e a b c) newDecls-    = do-      e' <- replaceDecls e newDecls-      return (GHC.BodyStmt e' a b c)-  replaceDecls x newDecls = return x+-- |Modify a 'GHC.LHsBind' wrapped in a 'GHC.ValD'. For a 'GHC.PatBind' the+-- declarations are extracted and returned after modification. For a+-- 'GHC.FunBind' the supplied 'GHC.SrcSpan' is used to identify the specific+-- 'GHC.Match' to be transformed, for when there are multiple of them.+modifyValD :: forall m t. (HasTransform m)+                => GHC.SrcSpan+                -> Decl+                -> (Match -> [Decl] -> m ([Decl], Maybe t))+                -> m (Decl,Maybe t)+modifyValD p pb@(GHC.L ss (GHC.ValD (GHC.PatBind {} ))) f =+  if ss == p+     then do+       ds <- liftT $ hsDeclsPatBindD pb+       (ds',r) <- f (error "modifyValD.PatBind should not touch Match") ds+       pb' <- liftT $ replaceDeclsPatBindD pb ds'+       return (pb',r)+     else return (pb,Nothing)+modifyValD p ast f = do+  (ast',r) <- runStateT (SYB.everywhereM (SYB.mkM doModLocal) ast) Nothing+  return (ast',r)+  where+    doModLocal :: Match -> StateT (Maybe t) m Match+    doModLocal  (match@(GHC.L ss _) :: Match) = do+         let+         if ss == p+           then do+             ds <- lift $ liftT $ hsDecls match+             (ds',r) <- lift $ f match ds+             put r+             match' <- lift $ liftT $ replaceDecls match ds'+             return match'+           else return match  -- --------------------------------------------------------------------- -instance HasDecls (GHC.LHsDecl GHC.RdrName) where-  hsDecls (GHC.L l (GHC.ValD d)) = hsDecls (GHC.L l d)-  -- hsDecls (GHC.L l (GHC.SigD d)) = hsDecls (GHC.L l d)-  hsDecls _                      = return []+-- |Used to integrate a @Transform@ into other Monad stacks+class (Monad m) => (HasTransform m) where+  liftT :: Transform a -> m a -  replaceDecls (GHC.L l (GHC.ValD d)) newDecls = do-    (GHC.L l1 d1) <- replaceDecls (GHC.L l d) newDecls-    return (GHC.L l1 (GHC.ValD d1))-  -- replaceDecls (GHC.L l (GHC.SigD d)) newDecls = do-  --   (GHC.L l1 d1) <- replaceDecls (GHC.L l d) newDecls-  --   return (GHC.L l1 (GHC.SigD d1))-  replaceDecls _d _  = error $ "LHsDecl.replaceDecls:not implemented"+instance HasTransform (TransformT Identity) where+  liftT = id  -- --------------------------------------------------------------------- +-- | Apply a transformation to the decls contained in @t@+modifyDeclsT :: (HasDecls t,HasTransform m)+             => ([GHC.LHsDecl GHC.RdrName] -> m [GHC.LHsDecl GHC.RdrName])+             -> t -> m t+modifyDeclsT action t = do+  decls <- liftT $ hsDecls t+  decls' <- action decls+  liftT $ replaceDecls t decls'++-- ---------------------------------------------------------------------+ matchApiAnn :: GHC.AnnKeywordId -> (KeywordId,DeltaPos) -> Bool matchApiAnn mkw (kw,_)   = case kw of@@ -767,8 +1012,8 @@ -- We comments extracted from annPriorComments or annFollowingComments, which -- need to move to just before the item identified by the predicate, if it -- fires, else at the end of the annotations.-insertCommentBefore :: AnnKey -> [(Comment, DeltaPos)]-                    -> ((KeywordId, DeltaPos) -> Bool) -> Transform ()+insertCommentBefore :: (Monad m) => AnnKey -> [(Comment, DeltaPos)]+                    -> ((KeywordId, DeltaPos) -> Bool) -> TransformT m () insertCommentBefore key toMove p = do   let     doInsert ans =@@ -777,7 +1022,6 @@         Just ann -> Map.insert key ann' ans           where             (before,after) = break p (annsDP ann)-            -- ann' = error $ "insertCommentBefore:" ++ showGhc (before,after)             ann' = ann { annsDP = before ++ (map comment2dp toMove) ++ after}    modifyAnnsT doInsert
src/Language/Haskell/GHC/ExactPrint/Types.hs view
@@ -1,6 +1,9 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-} module Language.Haskell.GHC.ExactPrint.Types   ( -- * Core Types    Anns@@ -21,10 +24,11 @@   , annGetConstr   -- * Internal Types   , LayoutStartCol(..)+  , declFun    ) where -import Data.Data (Data, Typeable, toConstr)+import Data.Data (Data, Typeable, toConstr,cast)  import qualified DynFlags       as GHC import qualified GHC@@ -43,7 +47,9 @@     , commentIdentifier :: !GHC.SrcSpan -- ^ Needed to uniquely identify two comments with the same contents     , commentOrigin     :: !(Maybe GHC.AnnKeywordId) -- ^ We sometimes turn syntax into comments in order to process them properly.     }-  deriving (Eq,Show,Typeable,Data, Ord)+  deriving (Eq,Typeable,Data,Ord)+instance Show Comment where+  show (Comment cs ss o) = "(Comment " ++ show cs ++ " " ++ showGhc ss ++ " " ++ show o ++ ")"  instance GHC.Outputable Comment where   ppr x = GHC.text (show x)@@ -71,6 +77,7 @@  data Annotation = Ann   {+    -- The first three fields relate to interfacing up into the AST     annEntryDelta      :: !DeltaPos     -- ^ Offset used to get to the start of the SrcSpan, from whatever the prior     -- output was, including all annPriorComments (field below).@@ -83,6 +90,8 @@     -- ^ Comments coming after the last output for the element subject to this     -- Annotation. These will only be added by AST transformations, and care     -- must be taken not to disturb layout of following elements.++  -- The next three fields relate to interacing down into the AST   , annsDP             :: ![(KeywordId, DeltaPos)]     -- ^ Annotations associated with this element.   , annSortKey         :: !(Maybe [GHC.SrcSpan])@@ -126,9 +135,15 @@ instance Show AnnKey where   show (AnnKey ss cn) = "AnnKey " ++ showGhc ss ++ " " ++ show cn -mkAnnKey :: (Data a) => GHC.Located a -> AnnKey-mkAnnKey (GHC.L l a) = AnnKey l (annGetConstr a)+mkAnnKeyPrim :: (Data a) => GHC.Located a -> AnnKey+mkAnnKeyPrim (GHC.L l a) = AnnKey l (annGetConstr a) +-- |Make an unwrapped @AnnKey@ for the @LHsDecl@ case, a normal one otherwise.+mkAnnKey :: (Data a) => GHC.Located a -> AnnKey+mkAnnKey ld =+  case cast ld :: Maybe (GHC.LHsDecl GHC.RdrName) of+    Just d -> declFun mkAnnKeyPrim d+    Nothing -> mkAnnKeyPrim ld  -- Holds the name of a constructor data AnnConName = CN { unConName :: String }@@ -178,6 +193,27 @@   ppr a     = GHC.text (show a)  -- ---------------------------------------------------------------------++declFun :: (forall a . Data a => GHC.Located a -> b) -> GHC.LHsDecl GHC.RdrName -> b+declFun f (GHC.L l de) =+  case de of+      GHC.TyClD d       -> f (GHC.L l d)+      GHC.InstD d       -> f (GHC.L l d)+      GHC.DerivD d      -> f (GHC.L l d)+      GHC.ValD d        -> f (GHC.L l d)+      GHC.SigD d        -> f (GHC.L l d)+      GHC.DefD d        -> f (GHC.L l d)+      GHC.ForD d        -> f (GHC.L l d)+      GHC.WarningD d    -> f (GHC.L l d)+      GHC.AnnD d        -> f (GHC.L l d)+      GHC.RuleD d       -> f (GHC.L l d)+      GHC.VectD d       -> f (GHC.L l d)+      GHC.SpliceD d     -> f (GHC.L l d)+      GHC.DocD d        -> f (GHC.L l d)+      GHC.RoleAnnotD d  -> f (GHC.L l d)+#if __GLASGOW_HASKELL__ < 711+      GHC.QuasiQuoteD d -> f (GHC.L l d)+#endif   -- ---------------------------------------------------------------------
src/Language/Haskell/GHC/ExactPrint/Utils.hs view
@@ -1,5 +1,7 @@-{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE CPP #-} {-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-} module Language.Haskell.GHC.ExactPrint.Utils   (    -- * Manipulating Positons@@ -20,7 +22,7 @@   , comment2dp      -- * GHC Functions-  ,  srcSpanStartLine+  , srcSpanStartLine   , srcSpanEndLine   , srcSpanStartColumn   , srcSpanEndColumn@@ -33,12 +35,13 @@   -- * Manipulating Annotations   , getAnnotationEP   , annTrueEntryDelta+  , annCommentEntryDelta+  , annLeadingCommentEntryDelta    -- * General Utility   , orderByKey  -   -- * For tests   , debug   , debugM@@ -135,9 +138,10 @@     fl = l + dl     fc = if dl == 0 then c  + dc                     else co + dc+ -- | Add together two @DeltaPos@ taking into account newlines ----- > DP (0, 1) `addDP` DP (0, 2) == DP (0,3)+-- > DP (0, 1) `addDP` DP (0, 2) == DP (0, 3) -- > DP (0, 9) `addDP` DP (1, 5) == DP (1, 5) -- > DP (1, 4) `addDP` DP (1, 3) == DP (2, 3) addDP :: DeltaPos -> DeltaPos -> DeltaPos@@ -145,6 +149,33 @@   if c >= 1 then DP (a+c, d)             else DP (a, b + d) +-- | "Subtract" two @DeltaPos@ from each other, in the sense of calculating the+-- remaining delta for the second after the first has been applied.+-- invariant : if c = a `addDP` b+--             then a `stepDP` c == b+--+-- Cases where first DP is <= than second+-- > DP (0, 1) `addDP` DP (0, 2) == DP (0, 1)+-- > DP (1, 1) `addDP` DP (2, 0) == DP (1, 0)+-- > DP (1, 3) `addDP` DP (1, 4) == DP (0, 1)+-- > DP (1, 4) `addDP` DP (1, 4) == DP (1, 4)+--+-- Cases where first DP is > than second+-- > DP (0,  3) `addDP` DP (0, 2) == DP (0,1)  -- advance one at least+-- > DP (3,  3) `addDP` DP (2, 4) == DP (1, 4) -- go one line forward and to expected col+-- > DP (3,  3) `addDP` DP (0, 4) == DP (0, 1) -- maintain col delta at least+-- > DP (1, 21) `addDP` DP (1, 4) == DP (1, 4) -- go one line forward and to expected col+stepDP :: DeltaPos -> DeltaPos -> DeltaPos+stepDP (DP (a,b)) (DP (c,d))+  | (a,b) == (c,d) = DP (a,b)+  | a == c = if b < d then DP (0,d - b)+                      else if d == 0+                             then DP (1,0)+                             -- else DP (0,1)+                             else DP (c,d)+  | a < c = DP (c - a,d)+  | otherwise = DP (1,d)+ -- ---------------------------------------------------------------------  ss2pos :: GHC.SrcSpan -> Pos@@ -242,6 +273,23 @@   foldr addDP (DP (0,0)) (map (\(a, b) -> addDP b (dpFromString $ commentContents a)) annPriorComments )     `addDP` annEntryDelta +-- | Take an annotation and a required "true entry" and calculate an equivalent+-- one relative to the last comment in the annPriorComments.+annCommentEntryDelta :: Annotation -> DeltaPos -> DeltaPos+annCommentEntryDelta Ann{annPriorComments} trueDP = dp+  where+    commentDP =+      foldr addDP (DP (0,0)) (map (\(a, b) -> addDP b (dpFromString $ commentContents a)) annPriorComments )+    dp = stepDP commentDP trueDP++-- | Return the DP of the first item that generates output, either a comment or the entry DP+annLeadingCommentEntryDelta :: Annotation -> DeltaPos+annLeadingCommentEntryDelta Ann{annPriorComments,annEntryDelta} = dp+  where+    dp = case annPriorComments of+      [] -> annEntryDelta+      ((_,ed):_) -> ed+ -- | Calculates the distance from the start of a string to the end of -- a string. dpFromString ::  String -> DeltaPos@@ -333,13 +381,23 @@                       srcSpan s                       ++ indent (n + 1) ++                       show (getAnnotationEP (GHC.L s a) anns)+                      -- ++ case showWrappedDeclAnns (GHC.L s a) of+                      --   Nothing -> ""+                      --   Just annStr  -> indent (n + 1) ++ annStr                     Nothing -> "nnnnnnnn"                   ++ showAnnData anns (n+1) a                   ++ ")" --- ----------------------------------------------------------------------+{-+        showWrappedDeclAnns :: (Data a) => GHC.Located a -> Maybe String+        showWrappedDeclAnns t = everything mappend (Nothing `mkQ` showDecl) t+          where+            showDecl :: GHC.LHsDecl GHC.RdrName -> Maybe String+            showDecl d = Just $ declFun doShowAnn  d +        doShowAnn :: (Data a) => GHC.Located a -> String+        doShowAnn a =  show (getAnnotationEP a anns)+-}  -- ---------------------------------------------------------------------  showSDoc_ :: GHC.SDoc -> String
tests/Test.hs view
@@ -39,6 +39,14 @@      then exitFailure      else return () -- exitSuccess +transform :: IO ()+transform = hSilence [stderr] $ do+  cnts <- fst <$> runTestText (putTextToHandle stdout True) (TestList transformTests)+  putStrLn $ show cnts+  if errors cnts > 0 || failures cnts > 0+     then exitFailure+     else return () -- exitSuccess+ -- ---------------------------------------------------------------------  tests :: Test@@ -234,6 +242,7 @@   , mkParserTest "T10196.hs"   , mkParserTest "StringGap.hs"   , mkParserTest "RedundantDo.hs"+  , mkParserTest "TypeSignature.hs"   ]    ++ transformTests@@ -463,16 +472,31 @@     -- , manipulateAstTestWFname "WhereIn3.hs"                 "WhereIn3"     -- , manipulateAstTestWFnameMod changeWhereIn3a "WhereIn3a.hs" "WhereIn3a"     -- , manipulateAstTestWFname "Imports.hs"              "Imports"-    , manipulateAstTestWFname "T10196.hs"               "T10196"+    -- , manipulateAstTestWFname "T10196.hs"               "T10196"     , manipulateAstTestWFnameMod addLocaLDecl1 "AddLocalDecl1.hs" "AddLocaLDecl1"-    , manipulateAstTestWFnameMod addLocaLDecl2 "AddLocalDecl2.hs" "AddLocaLDecl2"-    , manipulateAstTestWFnameMod addLocaLDecl3 "AddLocalDecl3.hs" "AddLocaLDecl3"-    , manipulateAstTestWFnameMod rmDecl1       "RmDecl1.hs"       "RmDecl1"+    -- , manipulateAstTestWFnameMod addLocaLDecl2 "AddLocalDecl2.hs" "AddLocaLDecl2"+    -- , manipulateAstTestWFnameMod addLocaLDecl3 "AddLocalDecl3.hs" "AddLocaLDecl3"+    -- , manipulateAstTestWFnameMod addLocaLDecl4 "AddLocalDecl4.hs" "AddLocaLDecl4"+    -- , manipulateAstTestWFnameMod addLocaLDecl5 "AddLocalDecl5.hs" "AddLocaLDecl5"+    -- , manipulateAstTestWFnameMod addLocaLDecl6 "AddLocalDecl6.hs" "AddLocaLDecl6"+    -- , manipulateAstTestWFnameMod rmDecl1       "RmDecl1.hs"       "RmDecl1"     -- , manipulateAstTestWFname "RmDecl2.hs"                        "RmDecl2"-    , manipulateAstTestWFnameMod rmDecl2       "RmDecl2.hs"       "RmDecl2"-    , manipulateAstTestWFnameMod rmDecl3       "RmDecl3.hs"       "RmDecl3"-    , manipulateAstTestWFnameMod rmTypeSig1    "RmTypeSig1.hs"    "RmTypeSig1"-    , manipulateAstTestWFname "StringGap.hs"                      "StringGap"+    -- , manipulateAstTestWFnameMod rmDecl2       "RmDecl2.hs"       "RmDecl2"+    -- , manipulateAstTestWFnameMod rmDecl3       "RmDecl3.hs"       "RmDecl3"+    -- , manipulateAstTestWFnameMod rmDecl4       "RmDecl4.hs"       "RmDecl4"+    -- , manipulateAstTestWFnameMod rmDecl5       "RmDecl5.hs"       "RmDecl5"+    -- , manipulateAstTestWFname "RmDecl5.hs"                        "RmDecl5"+    -- , manipulateAstTestWFnameMod rmDecl6       "RmDecl6.hs"       "RmDecl6"+    -- , manipulateAstTestWFnameMod rmDecl7       "RmDecl7.hs"       "RmDecl7"+    -- , manipulateAstTestWFname "TypeSignature.hs"                  "TypeSignature"+    -- , manipulateAstTestWFnameMod rmTypeSig1    "RmTypeSig1.hs"    "RmTypeSig1"+    -- , manipulateAstTestWFnameMod rmTypeSig2    "RmTypeSig2.hs"    "RmTypeSig2"+    -- , manipulateAstTestWFname "StringGap.hs"                      "StringGap"+    -- , manipulateAstTestWFnameMod addHiding1    "AddHiding1.hs"    "AddHiding1"+    -- , manipulateAstTestWFnameMod addHiding2    "AddHiding2.hs"    "AddHiding2"+    -- , manipulateAstTestWFnameMod cloneDecl1    "CloneDecl1.hs"    "CloneDecl1"+    -- , manipulateAstTestWFname "SimpleDo.hs"                      "Main"+    -- , manipulateAstTestWFnameMod changeRename2    "Rename2.hs"  "Main"     {-     , manipulateAstTestWFname "Lhs.lhs"                  "Main"     , manipulateAstTestWFname "Foo.hs"                   "Main"
tests/Test/Common.hs view
@@ -155,7 +155,7 @@ runRoundTrip !anns !parsedOrig cs =   let     !relAnns = relativiseApiAnnsWithComments cs parsedOrig anns-    !printed = exactPrintWithAnns parsedOrig relAnns+    !printed = exactPrint parsedOrig relAnns   in (printed,  relAnns)  -- ---------------------------------------------------------------------`
tests/Test/Transform.hs view
@@ -18,11 +18,13 @@ import qualified FastString     as GHC  import qualified Data.Generics as SYB+-- import qualified GHC.SYB.Utils as SYB  import Control.Monad import System.FilePath import System.IO import qualified Data.Map as Map+-- import Data.List import Data.Maybe  import System.IO.Silently@@ -46,6 +48,7 @@   , mkTestModChange changeLayoutLet3  "LayoutLet3.hs"  "LayoutLet3"   , mkTestModChange changeLayoutLet3  "LayoutLet4.hs"  "LayoutLet4"   , mkTestModChange changeRename1     "Rename1.hs"     "Main"+  , mkTestModChange changeRename2     "Rename2.hs"     "Main"   , mkTestModChange changeLayoutIn1   "LayoutIn1.hs"   "LayoutIn1"   , mkTestModChange changeLayoutIn3   "LayoutIn3.hs"   "LayoutIn3"   , mkTestModChange changeLayoutIn3   "LayoutIn3a.hs"  "LayoutIn3a"@@ -115,7 +118,7 @@                              { annEntryDelta     = DP (1,0) }         modifyAnnsT addWhere         let decls = [s,d]-        logTr $ "(m,decls)=" ++ show (mkAnnKey m,map mkAnnKey decls)+        -- logTr $ "(m,decls)=" ++ show (mkAnnKey m,map mkAnnKey decls)         modifyAnnsT (captureOrderAnnKey newAnnKey decls)         return (GHC.L lm (GHC.Match mln pats typ (GHC.GRHSs rhs                         (GHC.HsValBinds@@ -149,11 +152,9 @@                 let a2 = setPrecedingLines s1 2 0 a1                 return a2         putAnnsT a'-        let wrapDecl (GHC.L l' w) = GHC.L l' (GHC.ValD w)-            wrapSig (GHC.L l' w) = GHC.L l' (GHC.SigD w)         let oldDecls = GHC.sortLocated $ map wrapDecl (GHC.bagToList binds) ++ map wrapSig sigs         let decls = s:d:oldDecls-        logTr $ "(m,decls)=" ++ show (mkAnnKey m,map mkAnnKey decls)+        -- logTr $ "(m,decls)=" ++ show (mkAnnKey m,map mkAnnKey decls)         modifyAnnsT (captureOrder m decls)         return (GHC.L lm (GHC.Match mln pats typ (GHC.GRHSs rhs                         (GHC.HsValBinds@@ -323,6 +324,9 @@ changeRename1 :: Changer changeRename1 ans parsed = return (ans,rename "bar2" [((3,1),(3,4))] parsed) +changeRename2 :: Changer+changeRename2 ans parsed = return (ans,rename "joe" [((2,1),(2,5))] parsed)+ changeLayoutLet3 :: Changer changeLayoutLet3 ans parsed = return (ans,rename "xxxlonger" [((7,5),(7,8)),((9,14),(9,17))] parsed) @@ -448,7 +452,7 @@                    Just (change,_) -> change ann parsed    let-    printed = exactPrintWithAnns parsed' ann' -- `debug` ("ann=" ++ (show $ map (\(s,a) -> (ss2span s, a)) $ Map.toList ann))+    printed = exactPrint parsed' ann' -- `debug` ("ann=" ++ (show $ map (\(s,a) -> (ss2span s, a)) $ Map.toList ann))     outcome = if printed == contents                 then "Match\n"                 else "Fail\n"@@ -552,97 +556,173 @@     mkTestModChange addLocaLDecl1  "AddLocalDecl1.hs"  "AddLocalDecl1"   , mkTestModChange addLocaLDecl2  "AddLocalDecl2.hs"  "AddLocalDecl2"   , mkTestModChange addLocaLDecl3  "AddLocalDecl3.hs"  "AddLocalDecl3"+  , mkTestModChange addLocaLDecl4  "AddLocalDecl4.hs"  "AddLocalDecl4"+  , mkTestModChange addLocaLDecl5  "AddLocalDecl5.hs"  "AddLocalDecl5"+  , mkTestModChange addLocaLDecl6  "AddLocalDecl6.hs"  "AddLocalDecl6"    , mkTestModChange rmDecl1 "RmDecl1.hs" "RmDecl1"   , mkTestModChange rmDecl2 "RmDecl2.hs" "RmDecl2"   , mkTestModChange rmDecl3 "RmDecl3.hs" "RmDecl3"+  , mkTestModChange rmDecl4 "RmDecl4.hs" "RmDecl4"+  , mkTestModChange rmDecl5 "RmDecl5.hs" "RmDecl5"+  , mkTestModChange rmDecl6 "RmDecl6.hs" "RmDecl6"+  , mkTestModChange rmDecl7 "RmDecl7.hs" "RmDecl7"    , mkTestModChange rmTypeSig1 "RmTypeSig1.hs" "RmTypeSig1"+  , mkTestModChange rmTypeSig2 "RmTypeSig2.hs" "RmTypeSig2"++  , mkTestModChange addHiding1 "AddHiding1.hs" "AddHiding1"+  , mkTestModChange addHiding2 "AddHiding2.hs" "AddHiding2"++  , mkTestModChange cloneDecl1 "CloneDecl1.hs" "CloneDecl1"   ]  -- ---------------------------------------------------------------------  addLocaLDecl1 :: Changer addLocaLDecl1 ans lp = do-  Right (declAnns, newDecl@(GHC.L ld (GHC.ValD decl))) <- withDynFlags (\df -> parseDecl df "decl" "nn = 2")-  let declAnns' = setPrecedingLines (GHC.L ld decl) 1 0 declAnns+  Right (declAnns, newDecl) <- withDynFlags (\df -> parseDecl df "decl" "nn = 2")+  let declAnns' = setPrecedingLines newDecl 1 4 declAnns+      doAddLocal = do+        (d1:d2:_) <- hsDecls lp+        balanceComments d1 d2+        (d1',_) <- modifyValD (GHC.getLoc d1) d1 $ \_m d -> do+          return ((newDecl : d),Nothing)+        replaceDecls lp [d1', d2] +  let (lp',(ans',_),_w) = runTransform (mergeAnns ans declAnns') doAddLocal+  -- putStrLn $ "log:\n" ++ intercalate "\n" _w+  return (ans',lp')++-- ---------------------------------------------------------------------++addLocaLDecl2 :: Changer+addLocaLDecl2 ans lp = do+  Right (declAnns, newDecl) <- withDynFlags (\df -> parseDecl df "decl" "nn = 2")+  let       doAddLocal = do          tlDecs <- hsDecls lp          let parent = head tlDecs-         decls <- hsDecls parent          balanceComments parent (head $ tail tlDecs) -         modifyAnnsT (setPrecedingLines newDecl 1 4)+         (parent',_) <- modifyValD (GHC.getLoc parent) parent $ \_m decls -> do+           transferEntryDPT (head decls) newDecl+           setEntryDPT (head decls) (DP (1, 0))+           return ((newDecl:decls),Nothing) -         parent' <- replaceDecls parent (newDecl:decls)          replaceDecls lp (parent':tail tlDecs) -  let (lp',(ans',_),_w) = runTransform ans doAddLocal-  return (mergeAnnList [declAnns',ans'],lp')+  let (lp',(ans',_),_w) = runTransform (mergeAnns ans declAnns) doAddLocal+  -- putStrLn $ "log:\n" ++ intercalate "\n" _w+  return (ans',lp')  -- --------------------------------------------------------------------- -addLocaLDecl2 :: Changer-addLocaLDecl2 ans lp = do-  Right (declAnns, newDecl@(GHC.L ld (GHC.ValD decl))) <- withDynFlags (\df -> parseDecl df "decl" "nn = 2")-  let declAnns' = setPrecedingLines (GHC.L ld decl) 1 0 declAnns-+addLocaLDecl3 :: Changer+addLocaLDecl3 ans lp = do+  Right (declAnns, newDecl) <- withDynFlags (\df -> parseDecl df "decl" "nn = 2")+  let       doAddLocal = do+         -- logDataWithAnnsTr "parsed:" lp+         logDataWithAnnsTr "newDecl:" newDecl          tlDecs <- hsDecls lp          let parent = head tlDecs-         decls <- hsDecls parent          balanceComments parent (head $ tail tlDecs) -         DP (r,c) <- getEntryDPT (head decls)-         modifyAnnsT (setPrecedingLines newDecl r c)-         modifyAnnsT (setPrecedingLines (head decls) 1 0)+         (parent',_) <- modifyValD (GHC.getLoc parent) parent $ \m decls -> do+           setPrecedingLinesT newDecl 1 0+           moveTrailingComments m (last decls)+           return ((decls++[newDecl]),Nothing) -         parent' <- replaceDecls parent (newDecl:decls)          replaceDecls lp (parent':tail tlDecs) -  let (lp',(ans',_),_w) = runTransform ans doAddLocal-  return (mergeAnnList [declAnns',ans'],lp')+  let (lp',(ans',_),_w) = runTransform (mergeAnns ans declAnns) doAddLocal+  -- putStrLn $ "log\n" ++ intercalate "\n" _w+  return (ans',lp')  -- --------------------------------------------------------------------- -addLocaLDecl3 :: Changer-addLocaLDecl3 ans lp = do-  Right (declAnns, newDecl@(GHC.L ld (GHC.ValD decl))) <- withDynFlags (\df -> parseDecl df "decl" "nn = 2")-  let declAnns' = setPrecedingLines (GHC.L ld decl) 1 0 declAnns-+addLocaLDecl4 :: Changer+addLocaLDecl4 ans lp = do+  Right (declAnns, newDecl) <- withDynFlags (\df -> parseDecl df "decl" "nn = 2")+  Right (sigAnns, newSig)   <- withDynFlags (\df -> parseDecl df "sig"  "nn :: Int")+  -- putStrLn $ "addLocaLDecl4:lp=" ++ showGhc lp+  let       doAddLocal = do          tlDecs <- hsDecls lp          let parent = head tlDecs-         decls <- hsDecls parent-         balanceComments parent (head $ tail tlDecs) -         modifyAnnsT (setPrecedingLines newDecl 1 0)+         setPrecedingLinesT newSig  1 0+         setPrecedingLinesT newDecl 1 0 -         moveTrailingComments parent (last decls)-         parent' <- replaceDecls parent (decls++[newDecl])+         (parent',_) <- modifyValD (GHC.getLoc parent) parent $ \_m decls -> do+           return ((decls++[newSig,newDecl]),Nothing)+          replaceDecls lp (parent':tail tlDecs) +  let (lp',(ans',_),_w) = runTransform (mergeAnnList [ans,declAnns,sigAnns]) doAddLocal+  -- putStrLn $ "log\n" ++ intercalate "\n" _w+  return (ans',lp')++-- ---------------------------------------------------------------------++addLocaLDecl5 :: Changer+addLocaLDecl5 ans lp = do+  let+      doAddLocal = do+         [s1,d1,d2,d3] <- hsDecls lp++         transferEntryDPT d2 d3++         (d1',_) <- modifyValD (GHC.getLoc d1) d1 $ \_m _decls -> do+           return ([d2],Nothing)+         replaceDecls lp [s1,d1',d3]+   let (lp',(ans',_),_w) = runTransform ans doAddLocal-  return (mergeAnnList [declAnns',ans'],lp')+  -- putStrLn $ "log\n" ++ intercalate "\n" _w+  return (ans',lp')  -- --------------------------------------------------------------------- +addLocaLDecl6 :: Changer+addLocaLDecl6 ans lp = do+  Right (declAnns, newDecl) <- withDynFlags (\df -> parseDecl df "decl" "x = 3")+  let declAnns' = setPrecedingLines newDecl 1 4 declAnns+      doAddLocal = do+        [d1,d2] <- hsDecls lp+        balanceComments d1 d2++        let GHC.L _ (GHC.ValD (GHC.FunBind  _ _ (GHC.MG [m1,m2] _ _ _) _ _ _)) = d1+        balanceComments m1 m2++        (d1',_) <- modifyValD (GHC.getLoc m1) d1 $ \_m decls -> do+           return ((newDecl : decls),Nothing)+        replaceDecls lp [d1', d2]++  let (lp',(ans',_),_w) = runTransform (mergeAnns ans declAnns') doAddLocal+  -- putStrLn $ "log:\n" ++ intercalate "\n" _w+  return (ans',lp')+-- ---------------------------------------------------------------------+ rmDecl1 :: Changer rmDecl1 ans lp = do   let doRmDecl = do          tlDecs <- hsDecls lp          let (d1:s1:d2:ds) = tlDecs -         -- First delete the decl only+         -- First delete the decl (d2) only+         balanceComments s1 d2 -- ++AZ++          balanceComments d2 (head ds)          lp1 <- replaceDecls lp (d1:s1:ds)+         -- return lp1           -- Then delete the sig separately          tlDecs1 <- hsDecls lp1          let (d1':s1':ds') = tlDecs1+         -- transferEntryDPT s1' (head ds')  -- required in HaRe.          balanceComments d1' s1'          balanceComments s1' (head ds')+         transferEntryDPT s1' (head ds')  -- required in HaRe.          replaceDecls lp (d1':ds')    let (lp',(ans',_),_w) = runTransform ans doRmDecl@@ -655,35 +735,118 @@   let       doRmDecl = do         let+          go :: GHC.LHsExpr GHC.RdrName -> Transform (GHC.LHsExpr GHC.RdrName)+          go e@(GHC.L _ (GHC.HsLet{})) = do+            decs <- hsDecls e+            e' <- replaceDecls e (init decs)+            return e'+          go x = return x++        SYB.everywhereM (SYB.mkM go) lp++  let (lp',(ans',_),_w) = runTransform ans doRmDecl+  -- putStrLn $ "log:\n" ++ intercalate "\n" _w+  return (ans',lp')++-- ---------------------------------------------------------------------++rmDecl3 :: Changer+rmDecl3 ans lp = do+  let+      doRmDecl = do+         [d1,d2] <- hsDecls lp++         (d1',Just sd1) <- modifyValD (GHC.getLoc d1) d1 $ \_m [sd1] -> do+           setPrecedingLinesDeclT sd1 2 0+           return ([],Just sd1)++         replaceDecls lp [d1',sd1,d2]++  let (lp',(ans',_),_w) = runTransform ans doRmDecl+  -- putStrLn $ "log:\n" ++ intercalate "\n" _w+  return (ans',lp')++-- ---------------------------------------------------------------------++rmDecl4 :: Changer+rmDecl4 ans lp = do+  let+      doRmDecl = do+         [d1] <- hsDecls lp++         (d1',Just sd1) <- modifyValD (GHC.getLoc d1) d1 $ \_m [sd1,sd2] -> do+           -- [sd1,sd2] <- hsDecls d1+           transferEntryDPT sd1 sd2++           setPrecedingLinesDeclT sd1 2 0+           -- d1' <- replaceDecls d1 [sd2]+           return ([sd2],Just sd1)++         replaceDecls lp [d1',sd1]++  let (lp',(ans',_),_w) = runTransform ans doRmDecl+  return (ans',lp')++-- ---------------------------------------------------------------------++rmDecl5 :: Changer+rmDecl5 ans lp = do+  let+      doRmDecl = do+        let           go :: GHC.HsExpr GHC.RdrName -> Transform (GHC.HsExpr GHC.RdrName)           go (GHC.HsLet lb expr) = do-            decs <- hsDecls lb-            lb' <- replaceDecls lb (init decs)+            decs <- hsDeclsValBinds lb+            let dec = last decs+            transferEntryDPT (head decs) dec+            lb' <- replaceDeclsValbinds lb [dec]             return (GHC.HsLet lb' expr)           go x = return x          SYB.everywhereM (SYB.mkM go) lp    let (lp',(ans',_),_w) = runTransform ans doRmDecl+  -- putStrLn $ "log:" ++ intercalate "\n" _w   return (ans',lp')  -- --------------------------------------------------------------------- -rmDecl3 :: Changer-rmDecl3 ans lp = do+rmDecl6 :: Changer+rmDecl6 ans lp = do   let       doRmDecl = do+         [d1] <- hsDecls lp++         (d1',_) <- modifyValD (GHC.getLoc d1) d1 $ \_m subDecs -> do+           let (ss1:_sd1:sd2:sds) = subDecs+           transferEntryDPT ss1 sd2++           return (sd2:sds,Nothing)++         replaceDecls lp [d1']++  let (lp',(ans',_),_w) = runTransform ans doRmDecl+  -- putStrLn $ "log:" ++ intercalate "\n" _w+  return (ans',lp')++-- ---------------------------------------------------------------------++rmDecl7 :: Changer+rmDecl7 ans lp = do+  let+      doRmDecl = do          tlDecs <- hsDecls lp-         let [d1] = tlDecs+         let [s1,d1,d2,d3] = tlDecs -         subDecs <- hsDecls d1-         let [sd1] = subDecs+         balanceComments d1 d2+         balanceComments d2 d3 -         modifyAnnsT (setPrecedingLinesDecl sd1 2 0)-         d1' <- replaceDecls d1 []-         replaceDecls lp [d1',sd1]+         transferEntryDPT d2 d3 +         replaceDecls lp [s1,d1,d3]+   let (lp',(ans',_),_w) = runTransform ans doRmDecl+  -- putStrLn $ "log:" ++ intercalate "\n" _w   return (ans',lp')  -- ---------------------------------------------------------------------@@ -698,6 +861,86 @@          replaceDecls lp (s1':d1:d2)    let (lp',(ans',_),_w) = runTransform ans doRmDecl+  return (ans',lp')++-- ---------------------------------------------------------------------++rmTypeSig2 :: Changer+rmTypeSig2 ans lp = do+  let doRmDecl = do+         tlDecs <- hsDecls lp+         let [d1] = tlDecs++         (d1',_) <- modifyValD (GHC.getLoc d1) d1 $ \_m [s,d] -> do+           transferEntryDPT s d+           return ([d],Nothing)+         replaceDecls lp [d1']++  let (lp',(ans',_),_w) = runTransform ans doRmDecl+  -- putStrLn $ "log:" ++ intercalate "\n" _w+  return (ans',lp')++-- ---------------------------------------------------------------------++addHiding1 :: Changer+addHiding1 ans (GHC.L l p) = do+  let doTransform = do+        l0 <- uniqueSrcSpanT+        l1 <- uniqueSrcSpanT+        l2 <- uniqueSrcSpanT+        let+          [GHC.L li imp1,imp2] = GHC.hsmodImports p+          n1 = GHC.L l1 (GHC.mkVarUnqual (GHC.mkFastString "n1"))+          n2 = GHC.L l2 (GHC.mkVarUnqual (GHC.mkFastString "n2"))+          v1 = GHC.L l1 (GHC.IEVar n1)+          v2 = GHC.L l2 (GHC.IEVar n2)+          impHiding = GHC.L l0 [v1,v2]+          imp1' = imp1 { GHC.ideclHiding = Just (True,impHiding)}+          p' = p { GHC.hsmodImports = [GHC.L li imp1',imp2]}+        addSimpleAnnT impHiding (DP (0,1)) [((G GHC.AnnHiding),DP (0,0)),((G GHC.AnnOpenP),DP (0,1)),((G GHC.AnnCloseP),DP (0,0))]+        addSimpleAnnT n1        (DP (0,0)) [((G GHC.AnnVal),DP (0,0)),((G GHC.AnnComma),DP (0,0))]+        addSimpleAnnT n2        (DP (0,0)) [((G GHC.AnnVal),DP (0,0))]+        return (GHC.L l p')++  let (lp',(ans',_),_w) = runTransform ans doTransform+  return (ans',lp')++-- ---------------------------------------------------------------------++addHiding2 :: Changer+addHiding2 ans (GHC.L l p) = do+  let doTransform = do+        l1 <- uniqueSrcSpanT+        l2 <- uniqueSrcSpanT+        let+          [GHC.L li imp1] = GHC.hsmodImports p+          Just (_,GHC.L lh ns) = GHC.ideclHiding imp1+          (GHC.L _ (GHC.IEVar ln)) = last ns+          n1 = GHC.L l1 (GHC.mkVarUnqual (GHC.mkFastString "n1"))+          n2 = GHC.L l2 (GHC.mkVarUnqual (GHC.mkFastString "n2"))+          v1 = GHC.L l1 (GHC.IEVar n1)+          v2 = GHC.L l2 (GHC.IEVar n2)+          imp1' = imp1 { GHC.ideclHiding = Just (True,GHC.L lh (ns ++ [v1,v2]))}+          p' = p { GHC.hsmodImports = [GHC.L li imp1']}+        addSimpleAnnT n1        (DP (0,0)) [((G GHC.AnnVal),DP (0,0)),((G GHC.AnnComma),DP (0,0))]+        addSimpleAnnT n2        (DP (0,0)) [((G GHC.AnnVal),DP (0,0))]+        addTrailingCommaT ln+        return (GHC.L l p')++  let (lp',(ans',_),_w) = runTransform ans doTransform+  return (ans',lp')++-- ---------------------------------------------------------------------++cloneDecl1 :: Changer+cloneDecl1 ans lp = do+  let doChange = do+         tlDecs <- hsDecls lp+         let (d1:d2:ds) = tlDecs+         d2' <- fst <$> cloneT d2+         replaceDecls lp (d1:d2:d2':ds)++  let (lp',(ans',_),_w) = runTransform ans doChange   return (ans',lp')  -- ---------------------------------------------------------------------
+ tests/examples/AddHiding1.hs view
@@ -0,0 +1,7 @@+module AddHiding1 where++import Data.Maybe++import Data.Maybe hiding (n1,n2)++f = 1
+ tests/examples/AddHiding1.hs.expected view
@@ -0,0 +1,7 @@+module AddHiding1 where++import Data.Maybe hiding (n1,n2)++import Data.Maybe hiding (n1,n2)++f = 1
+ tests/examples/AddHiding2.hs view
@@ -0,0 +1,5 @@+module AddHiding2 where++import Data.Maybe hiding (f1,f2)++f = 1
+ tests/examples/AddHiding2.hs.expected view
@@ -0,0 +1,5 @@+module AddHiding2 where++import Data.Maybe hiding (f1,f2,n1,n2)++f = 1
+ tests/examples/AddLocalDecl4.hs view
@@ -0,0 +1,3 @@+module AddLocalDecl4 where++toplevel x = c * x
+ tests/examples/AddLocalDecl4.hs.expected view
@@ -0,0 +1,6 @@+module AddLocalDecl4 where++toplevel x = c * x+  where+    nn :: Int+    nn = 2
+ tests/examples/AddLocalDecl5.hs view
@@ -0,0 +1,8 @@+module AddLocalDecl5 where++toplevel :: Integer -> Integer+toplevel x = c * x++-- c,d :: Integer+c = 7+d = 9
+ tests/examples/AddLocalDecl5.hs.expected view
@@ -0,0 +1,9 @@+module AddLocalDecl5 where++toplevel :: Integer -> Integer+toplevel x = c * x+  where+    -- c,d :: Integer+    c = 7++d = 9
+ tests/examples/AddLocalDecl6.hs view
@@ -0,0 +1,9 @@+module AddLocalDecl6 where++foo [] = 1 -- comment 0+foo xs = 2 -- comment 1++bar [] = 1 -- comment 2+  where+    x = 3+bar xs = 2 -- comment 3
+ tests/examples/AddLocalDecl6.hs.expected view
@@ -0,0 +1,11 @@+module AddLocalDecl6 where++foo [] = 1 -- comment 0+  where+    x = 3+foo xs = 2 -- comment 1++bar [] = 1 -- comment 2+  where+    x = 3+bar xs = 2 -- comment 3
+ tests/examples/Base.hs view
@@ -0,0 +1,26 @@+{-# LANGUAGE BangPatterns, CPP, RankNTypes, MagicHash, UnboxedTuples, MultiParamTypeClasses, FlexibleInstances, FlexibleContexts, DeriveDataTypeable, UnliftedFFITypes #-}+#if __GLASGOW_HASKELL__ >= 708+{-# LANGUAGE RoleAnnotations #-}+#endif+{-# OPTIONS_HADDOCK hide #-}++-- Flat unboxed arrays: instances++instance IArray UArray Bool where+    {-# INLINE bounds #-}+    bounds (UArray l u _ _) = (l,u)+    {-# INLINE numElements #-}+    numElements (UArray _ _ n _) = n+    {-# INLINE unsafeArray #-}+    unsafeArray lu ies = runST (unsafeArrayUArray lu ies False)+    {-# INLINE unsafeAt #-}+    unsafeAt (UArray _ _ _ arr#) (I# i#) =+        ((indexWordArray# arr# (bOOL_INDEX i#) `and#` bOOL_BIT i#)+        `neWord#` int2Word# 0#)++    {-# INLINE unsafeReplace #-}+    unsafeReplace arr ies = runST (unsafeReplaceUArray arr ies)+    {-# INLINE unsafeAccum #-}+    unsafeAccum f arr ies = runST (unsafeAccumUArray f arr ies)+    {-# INLINE unsafeAccumArray #-}+    unsafeAccumArray f initialValue lu ies = runST (unsafeAccumArrayUArray f initialValue lu ies)
+ tests/examples/CloneDecl1.hs view
@@ -0,0 +1,10 @@+module CloneDecl1 where++z = 3++foo a b =+  let+    x = a + b + z+    y = a * b - z+  in+    x + y
+ tests/examples/CloneDecl1.hs.expected view
@@ -0,0 +1,17 @@+module CloneDecl1 where++z = 3++foo a b =+  let+    x = a + b + z+    y = a * b - z+  in+    x + y++foo a b =+  let+    x = a + b + z+    y = a * b - z+  in+    x + y
+ tests/examples/Error.hs view
@@ -0,0 +1,110 @@++module GameData.Data where+#include "Utils.cpp"+import qualified Data.List as L+import qualified Data.List.Zipper as LZ+import Gamgine.Control (applyIf)+import qualified Gamgine.Zipper as GZ+import qualified GameData.Level as LV+import qualified GameData.Entity as E+IMPORT_LENS_AS_LE+++data Data = Data {+   levels :: LZ.Zipper LV.Level+   }++LENS(levels)++instance E.ApplyToEntity Data where+   eMap f = LE.modL currentLevelL (E.eMap f)+   eFilter p = LE.modL currentLevelL (E.eFilter p)+++currentLevelL    = currentLevelLens+currentLevelLens = LE.lens getCurrentLevel setCurrentLevel+   where+      getCurrentLevel       = LZ.cursor . levels+      setCurrentLevel level = LE.modL levelsL $ LZ.replace level+++newData :: [LV.Level] -> Data+newData = Data . LZ.fromList+++allLevels :: Data -> [LV.Level]+allLevels = LZ.toList . levels+++atLastLevel :: Data -> Bool+atLastLevel = GZ.atLast . levels+++atFirstLevel :: Data -> Bool+atFirstLevel = GZ.atFirst . levels+++levelFinished :: Data -> Bool+levelFinished = LV.allStarsCollected . LE.getL currentLevelL+++gameFinished :: Data -> Bool+gameFinished d = levelFinished d && atLastLevel d+++toNextLevel :: Data -> Data+toNextLevel d@Data {levels = lvs}+   | LZ.emptyp lvs || GZ.atLast lvs = d+   | otherwise =+      let lvs      = levels d+          (c', n') = LV.changeLevels (GZ.current lvs) (GZ.next lvs)+          in d {levels = LZ.replace n' . LZ.right . LZ.replace c' $ lvs}+++toPreviousLevel :: Data -> Data+toPreviousLevel d@Data {levels = lvs}+   | LZ.emptyp lvs || GZ.atFirst lvs = d+   | otherwise =+      let (c', p') = LV.changeLevels (GZ.current lvs) (GZ.previous lvs)+          in d {levels = LZ.replace p' . LZ.left . LZ.replace c' $ lvs}+++data AddLevel = BeforeCurrent | AfterCurrent | AfterLast++addEmptyLevel :: AddLevel -> Data -> Data+addEmptyLevel BeforeCurrent d@Data {levels = lvs} =+   let (c', nlv') = LV.changeLevels (GZ.current lvs) LV.newEmptyLevel+       in d {levels = LZ.insert nlv' . LZ.replace c' $ lvs}++addEmptyLevel AfterCurrent d@Data {levels = lvs} =+   let (c', nlv') = LV.changeLevels (GZ.current lvs) LV.newEmptyLevel+       in d {levels = LZ.insert nlv' . LZ.right . LZ.replace c' $ lvs}++addEmptyLevel AfterLast d@Data {levels = lvs} =+   let (c', nlv') = LV.changeLevels (GZ.current lvs) LV.newEmptyLevel+       in d {levels = LZ.insert nlv' . LZ.end . LZ.replace c' $ lvs}+++data MoveLevel = Forward | Backward++moveCurrentLevel :: MoveLevel -> Data -> Data+moveCurrentLevel Forward d@Data {levels = lvs}+   | LZ.beginp lvs = d+   | otherwise     =+      let (p, c) = (GZ.previous lvs, GZ.current lvs)+          in d {levels = LZ.replace c . LZ.left . LZ.replace p $ lvs}++moveCurrentLevel Backward d@Data {levels = lvs}+   | GZ.atLast lvs = d+   | otherwise     =+      let (c, n) = (GZ.current lvs, GZ.next lvs)+          in d {levels = LZ.replace c . LZ.right . LZ.replace n $ lvs}+++removeCurrentLevel :: Data -> Data+removeCurrentLevel d@Data {levels = lvs}+   | GZ.atFirst lvs && GZ.atLast lvs =+      let (_, nlv') = LV.changeLevels (GZ.current lvs) LV.newEmptyLevel+          in d {levels = LZ.replace nlv' lvs}++   | otherwise = d {levels = applyIf LZ.endp LZ.left . LZ.delete $ lvs}
+ tests/examples/Join.hs view
@@ -0,0 +1,7 @@++forkOS_entry :: StablePtr (IO ()) -> IO ()+forkOS_entry stableAction = do+        action <- deRefStablePtr stableAction+        action++
+ tests/examples/Lambda.hs view
@@ -0,0 +1,2 @@++i = \x -> x
+ tests/examples/NormaliseLayout.hs view
@@ -0,0 +1,5 @@+module Main where++foo x = baz+  where foo = 2+        two = 4 where bax = 4
+ tests/examples/NormaliseLayout.hs.expected view
@@ -0,0 +1,1 @@+module Main where
+ tests/examples/Rename2.hs view
@@ -0,0 +1,4 @@++foo' x = case (odd x) of+  True -> "Odd"+  False -> "Even"
+ tests/examples/Rename2.hs.expected view
@@ -0,0 +1,4 @@++joe x = case (odd x) of+  True -> "Odd"+  False -> "Even"
tests/examples/RmDecl3.hs view
@@ -5,4 +5,5 @@   where     zz = 1 +foo = 3 -- EOF
tests/examples/RmDecl3.hs.expected view
@@ -5,4 +5,5 @@  zz = 1 +foo = 3 -- EOF
+ tests/examples/RmDecl4.hs view
@@ -0,0 +1,9 @@+module RmDecl4 where++-- Remove first declaration from a where clause, last should still be indented+ff y = y + zz + xx+  where+    zz = 1+    xx = 2++-- EOF
+ tests/examples/RmDecl4.hs.expected view
@@ -0,0 +1,10 @@+module RmDecl4 where++-- Remove first declaration from a where clause, last should still be indented+ff y = y + zz + xx+  where+    xx = 2++zz = 1++-- EOF
+ tests/examples/RmDecl5.hs view
@@ -0,0 +1,6 @@+module RmDecl5 where++sumSquares x y = let sq 0=0+                     sq z=z^pow+                     pow=2+                 in sq x + sq y
+ tests/examples/RmDecl5.hs.expected view
@@ -0,0 +1,4 @@+module RmDecl5 where++sumSquares x y = let pow=2+                 in sq x + sq y
+ tests/examples/RmDecl6.hs view
@@ -0,0 +1,11 @@+module RmDecl6 where++foo a = baz+  where+    baz :: Int+    baz = x  + a++    x = 1++    y :: Int -> Int -> Int+    y a b = undefined
+ tests/examples/RmDecl6.hs.expected view
@@ -0,0 +1,8 @@+module RmDecl6 where++foo a = baz+  where+    x = 1++    y :: Int -> Int -> Int+    y a b = undefined
+ tests/examples/RmDecl7.hs view
@@ -0,0 +1,8 @@+module RmDecl7 where++toplevel :: Integer -> Integer+toplevel x = c * x++-- c,d :: Integer+c = 7+d = 9
+ tests/examples/RmDecl7.hs.expected view
@@ -0,0 +1,6 @@+module RmDecl7 where++toplevel :: Integer -> Integer+toplevel x = c * x++d = 9
+ tests/examples/RmTypeSig2.hs view
@@ -0,0 +1,7 @@+module RmTypeSig2 where++-- Pattern bind+tup@(h,t) = (1,ff)+  where+    ff :: Int+    ff = 15
+ tests/examples/RmTypeSig2.hs.expected view
@@ -0,0 +1,6 @@+module RmTypeSig2 where++-- Pattern bind+tup@(h,t) = (1,ff)+  where+    ff = 15
+ tests/examples/SegFault.hs view
@@ -0,0 +1,133 @@+{-# INCLUDE "Parrot_hsc.h" #-}+{-# LINE 1 "Parrot.hsc" #-}+{-# OPTIONS_GHC -fglasgow-exts -cpp -fno-full-laziness -fno-cse #-}+{-# LINE 2 "Parrot.hsc" #-}++{-# LINE 3 "Parrot.hsc" #-}++module Pugs.Embed.Parrot where+import Data.IORef+import System.Cmd+import System.Process+import System.Directory+import System.IO+import System.IO.Unsafe+import Data.Maybe+import Control.Monad+import Pugs.Compat (getEnv, _PUGS_HAVE_POSIX)+import Pugs.Internals (encodeUTF8)++findExecutable' :: String -> IO (Maybe FilePath)+findExecutable' cmd = do+    dir <- getEnv "PARROT_PATH"+    if isJust dir then (do+        rv  <- findExecutableInDirectory (fromJust dir) cmd+        if isJust rv then return rv else findExecutable'') else do+    findExecutable''+    where+    findExecutable'' = do+        rv  <- findExecutable cmd+        if isJust rv then return rv else do+        cwd <- getCurrentDirectory+        rv  <- findExecutableInDirectory cwd cmd+        if isJust rv then return rv else do+        return Nothing++findExecutableInDirectory :: FilePath -> FilePath -> IO (Maybe FilePath)+findExecutableInDirectory dir cmd = do+    let file | _PUGS_HAVE_POSIX = dir ++ ('/':cmd)+             | otherwise        = dir ++ ('\\':cmd) ++ ".exe"+    ok <- doesFileExist file+    return $ if ok then (Just file) else Nothing++findParrot :: IO FilePath+findParrot = do+    rv <- findExecutable' "parrot"+    case rv of+        Nothing     -> fail "Cannot find the parrot executable in PATH"+        Just cmd    -> return cmd++evalParrotFile :: FilePath -> IO ()+evalParrotFile file = do+    cmd <- findParrot+    -- parrot -j is fatal on systems where jit is not supported,+    -- so we use the next fastest CGP core.+    args <- getEnv "PUGS_PARROT_OPTS"+    let args' | isJust args && fromJust args /= "" = fromJust args+              | otherwise                          = "-f"+    rawSystem cmd [args', file]+    return ()++evalParrot :: String -> IO ()+evalParrot str = do+    tmp         <- getTemporaryDirectory+    (file, fh)  <- openTempFile tmp "pugs.pir"+    hPutStr fh str+    hClose fh+    evalParrotFile file+    removeFile file++evalPGE :: FilePath -> String -> String -> [(String, String)] -> IO String+evalPGE path match rule subrules = do+    (inp, out, err, pid) <- initPGE path+    (`mapM` subrules) $ \(name, rule) -> do+        let nameStr = escape name+            ruleStr = escape rule+        hPutStrLn inp $ unwords+            ["add_rule", show (length nameStr), show (length ruleStr)]+        hPutStrLn inp nameStr+        hPutStrLn inp ruleStr+    let matchStr = escape match+        ruleStr  = escape rule+    hPutStrLn inp $ unwords+        ["match", show (length matchStr), show (length ruleStr)]+    hPutStrLn inp $ matchStr+    hPutStrLn inp $ ruleStr+    hFlush inp+    rv <- hGetLine out+    case rv of+        ('O':'K':' ':sizeStr) -> do+            size <- readIO sizeStr+            rv   <- sequence (replicate size (hGetChar out))+            ln   <- hGetLine out+            return $ rv ++ ln+        _ -> do+            errMsg  <- hGetContents err+            rv      <- waitForProcess pid+            writeIORef _ParrotInterp Nothing+            let msg | null errMsg = show rv+                    | otherwise   = errMsg+            fail $ "*** Running external 'parrot' failed:\n" ++ msg+    where+    escape = escape . encodeUTF8+    _escape "" = ""+    _escape ('\\':xs) = "\\\\" ++ _escape xs+    _escape ('\n':xs) = "\\n" ++ _escape xs+    _escape (x:xs) = (x:_escape xs)++initPGE :: FilePath -> IO ParrotInterp+initPGE path = do+    rv <- readIORef _ParrotInterp+    case rv of+        Just interp@(_, _, _, pid) -> do+            gone <- getProcessExitCode pid+            if isNothing gone then return interp else do+            writeIORef _ParrotInterp Nothing+            initPGE path+        Nothing -> do+            cmd <- findParrot+            interp <- runInteractiveProcess cmd ["run_pge.pir"] (Just path) Nothing+            writeIORef _ParrotInterp (Just interp)+            return interp++type ParrotInterp = (Handle, Handle, Handle, ProcessHandle)++{-# NOINLINE _ParrotInterp #-}+_ParrotInterp :: IORef (Maybe ParrotInterp)+_ParrotInterp = unsafePerformIO $ newIORef Nothing++_DoCompile :: Maybe (IORef (String -> FilePath -> String -> IO String))+_DoCompile = Nothing+++{-# LINE 387 "Parrot.hsc" #-}
+ tests/examples/SegFault2.hs view
@@ -0,0 +1,202 @@+{-# LANGUAGE CPP #-}++module UHC.Light.Compiler.CHR.Constraint+( Constraint (..)+, mkReduction+, cnstrReducablePart+, UnresolvedTrace (..)+, cnstrMpSingletonL, cnstrMpFromList+, ConstraintToInfoTraceMp+, cnstrTraceMpSingleton, cnstrTraceMpLiftTrace, cnstrTraceMpElimTrace, cnstrTraceMpFromList+, ConstraintToInfoMap+, emptyCnstrMp+, cnstrMpUnion, cnstrMpUnions+, cnstrRequiresSolve )+where+import UHC.Light.Compiler.Base.Common+import UHC.Light.Compiler.Ty+import UHC.Light.Compiler.CHR+import UHC.Light.Compiler.CHR.Key+import UHC.Light.Compiler.Base.TreeTrie+import UHC.Light.Compiler.Substitutable+import UHC.Util.Pretty as PP+import UHC.Util.Utils+import qualified Data.Set as Set+import qualified Data.Map as Map+import UHC.Light.Compiler.VarMp+import Control.Monad+import UHC.Util.Binary+import UHC.Util.Serialize+import Data.Typeable+import Data.Generics (Data)+import UHC.Light.Compiler.Opts.Base+++++{-# LINE 37 "src/ehc/CHR/Constraint.chs" #-}+-- | A Constraint is abstracted over the exact predicate, but differentiates on the role: to prove, can be assumed, and side effect of reduction+data Constraint p info+  = Prove           { cnstrPred :: !p }             -- proof obligation+  | Assume          { cnstrPred :: !p }             -- assumed constraint+  | Reduction                                       -- 'side effect', residual info used by (e.g.) codegeneration+                    { cnstrPred :: !p               -- the pred to which reduction was done+                    , cnstrInfo :: !info            -- additional reduction specific info w.r.t. codegeneration+                    , cnstrFromPreds :: ![p]        -- the preds from which reduction was done+                    , cnstrVarMp :: VarMp           -- additional bindings for type (etc.) variables, i.e. improving substitution+                    }+  deriving (Eq, Ord, Show)++{-# LINE 53 "src/ehc/CHR/Constraint.chs" #-}+mkReduction :: p -> info -> [p] -> Constraint p info+mkReduction p i ps+  = Reduction p i ps+              varlookupEmpty++{-# LINE 62 "src/ehc/CHR/Constraint.chs" #-}+#if __GLASGOW_HASKELL__ >= 708+deriving instance Typeable  Constraint+#else+deriving instance Typeable2 Constraint+#endif+deriving instance (Data x, Data y) => Data (Constraint x y)++{-# LINE 71 "src/ehc/CHR/Constraint.chs" #-}+-- | Dissection of Constraint, including reconstruction function+cnstrReducablePart :: Constraint p info -> Maybe (String,p,p->Constraint p info)+cnstrReducablePart (Prove  p) = Just ("Prf",p,Prove)+cnstrReducablePart (Assume p) = Just ("Ass",p,Assume)+cnstrReducablePart _          = Nothing++{-# LINE 84 "src/ehc/CHR/Constraint.chs" #-}+instance (CHRMatchable env p s) => CHRMatchable env (Constraint p info) s where+  chrMatchTo env s c1 c2+    = do { (_,p1,_) <- cnstrReducablePart c1+         ; (_,p2,_) <- cnstrReducablePart c2+         ; chrMatchTo env s p1 p2+         }++{-# LINE 93 "src/ehc/CHR/Constraint.chs" #-}+instance TTKeyable p => TTKeyable (Constraint p info) where+  toTTKey' o c -- = maybe [] (\(s,p,_) -> ttkAdd (TT1K_One $ Key_Str s) [toTTKey' o p]) $ cnstrReducablePart c+    = case cnstrReducablePart c of+        Just (s,p,_) -> ttkAdd' (TT1K_One $ Key_Str s) cs+                     where (_,cs) = toTTKeyParentChildren' o p+        _            -> panic "TTKeyable (Constraint p info).toTTKey'" -- ttkEmpty++{-# LINE 102 "src/ehc/CHR/Constraint.chs" #-}+instance (VarExtractable p v,VarExtractable info v) => VarExtractable (Constraint p info) v where+  varFreeSet c+    = case cnstrReducablePart c of+        Just (_,p,_) -> varFreeSet p+        _            -> Set.empty++instance (VarUpdatable p s,VarUpdatable info s) => VarUpdatable (Constraint p info) s where+  varUpd s      (Prove     p       ) = Prove      (varUpd s p)+  varUpd s      (Assume    p       ) = Assume     (varUpd s p)+  varUpd s      r@(Reduction {cnstrPred=p, cnstrInfo=i, cnstrFromPreds=ps})+                                     = r {cnstrPred=varUpd s p, cnstrInfo=varUpd s i, cnstrFromPreds=map (varUpd s) ps}++{-# LINE 120 "src/ehc/CHR/Constraint.chs" #-}+-- | The trace of an unresolved predicate+data UnresolvedTrace p info+  = UnresolvedTrace_None                                    -- no trace required when all is resolved+  | UnresolvedTrace_Red                                     -- ok reduction, with failure deeper down+      { utraceRedFrom       :: p+      , utraceInfoTo2From   :: info+      , utraceRedTo         :: [UnresolvedTrace p info]+      }+  | UnresolvedTrace_Fail                                    -- failed reduction+      { utraceRedFrom       :: p+      -- , utraceInfoTo2From    :: info+      , utraceRedTo         :: [UnresolvedTrace p info]+      }+  | UnresolvedTrace_Overlap                                 -- choice could not be made+      { utraceRedFrom       :: p+      , utraceRedChoices    :: [(info,[UnresolvedTrace p info])]+      }+  deriving Show++instance Eq p => Eq (UnresolvedTrace p info) where+  t1 == t2 = True -- utraceRedFrom t1 == utraceRedFrom t2++instance (PP p, PP info) => PP (UnresolvedTrace p info) where+  pp x = case x of+           UnresolvedTrace_None             -> PP.empty+           UnresolvedTrace_Red      p i us  -> p >|< ":" >#< i >-< indent 2 (vlist $ map pp us)+           UnresolvedTrace_Fail     p   us  -> p >|< ": FAIL" >-< indent 2 (vlist $ map pp us)+           UnresolvedTrace_Overlap  p uss   -> p >|< ": OVERLAP" >-< indent 2 (vlist $ map (\(i,u) -> i >-< indent 2 (vlist $ map pp u)) uss)++{-# LINE 155 "src/ehc/CHR/Constraint.chs" #-}+-- | Map from constraint to something+type ConstraintMp' p info x = Map.Map (Constraint p info) [x]++{-# LINE 160 "src/ehc/CHR/Constraint.chs" #-}+cnstrMpSingletonL :: Constraint p i -> [x] -> ConstraintMp' p i x+cnstrMpSingletonL c xs = Map.singleton c xs++cnstrMpSingleton :: Constraint p i -> x -> ConstraintMp' p i x+cnstrMpSingleton c x = cnstrMpSingletonL c [x]++cnstrMpFromList :: (Ord p, Ord i) => [(Constraint p i,x)] -> ConstraintMp' p i x+cnstrMpFromList l = Map.fromListWith (++) [ (c,[x]) | (c,x) <- l ]++cnstrMpMap :: (Ord p, Ord i) => (x -> y) -> ConstraintMp' p i x -> ConstraintMp' p i y+cnstrMpMap f = Map.map (map f)++{-# LINE 174 "src/ehc/CHR/Constraint.chs" #-}+-- | Map from constraint to info + trace+type ConstraintToInfoTraceMp p info = ConstraintMp' p info (info,[UnresolvedTrace p info])++{-# LINE 179 "src/ehc/CHR/Constraint.chs" #-}+cnstrTraceMpFromList :: (Ord p, Ord i) => [(Constraint p i,(i,[UnresolvedTrace p i]))] -> ConstraintToInfoTraceMp p i+cnstrTraceMpFromList = cnstrMpFromList++cnstrTraceMpSingleton :: Constraint p i -> i -> [UnresolvedTrace p i] -> ConstraintToInfoTraceMp p i+cnstrTraceMpSingleton c i ts = cnstrMpSingleton c (i,ts)++cnstrTraceMpElimTrace :: (Ord p, Ord i) => ConstraintToInfoTraceMp p i -> ConstraintToInfoMap p i+cnstrTraceMpElimTrace = cnstrMpMap fst++cnstrTraceMpLiftTrace :: (Ord p, Ord i) => ConstraintToInfoMap p i -> ConstraintToInfoTraceMp p i+cnstrTraceMpLiftTrace = cnstrMpMap (\x -> (x,[]))++{-# LINE 193 "src/ehc/CHR/Constraint.chs" #-}+-- | Map from constraint to info+type ConstraintToInfoMap     p info = ConstraintMp' p info info++{-# LINE 198 "src/ehc/CHR/Constraint.chs" #-}+emptyCnstrMp :: ConstraintMp' p info x+emptyCnstrMp = Map.empty++{-# LINE 208 "src/ehc/CHR/Constraint.chs" #-}+cnstrMpUnion :: (Ord p, Ord i) => ConstraintMp' p i x -> ConstraintMp' p i x -> ConstraintMp' p i x+cnstrMpUnion = Map.unionWith (++)++cnstrMpUnions :: (Ord p, Ord i) => [ConstraintMp' p i x] -> ConstraintMp' p i x+cnstrMpUnions = Map.unionsWith (++)++{-# LINE 220 "src/ehc/CHR/Constraint.chs" #-}+-- | Predicate for whether solving is required+cnstrRequiresSolve :: Constraint p info -> Bool+cnstrRequiresSolve (Reduction {}) = False+cnstrRequiresSolve _              = True++{-# LINE 231 "src/ehc/CHR/Constraint.chs" #-}+instance (PP p, PP info) => PP (Constraint p info) where+  pp (Prove     p     ) = "Prove"  >#< p+  pp (Assume    p     ) = "Assume" >#< p+  pp (Reduction {cnstrPred=p, cnstrInfo=i, cnstrFromPreds=ps})+                        = "Red"    >#< p >#< "<" >#< i >#< "<" >#< ppBracketsCommas ps++{-# LINE 243 "src/ehc/CHR/Constraint.chs" #-}+instance (Serialize p, Serialize i) => Serialize (Constraint p i) where+  sput (Prove     a      ) = sputWord8 0 >> sput a+  sput (Assume    a      ) = sputWord8 1 >> sput a+  sput (Reduction a b c d) = sputWord8 2 >> sput a >> sput b >> sput c >> sput d+  sget = do t <- sgetWord8+            case t of+              0 -> liftM  Prove     sget+              1 -> liftM  Assume    sget+              2 -> liftM4 Reduction sget sget sget sget+
+ tests/examples/SimpleDo.hs view
@@ -0,0 +1,4 @@++foo = do+  let    x = 1 -- a comment+  return x
+ tests/examples/TypeSignature.hs view
@@ -0,0 +1,12 @@+module TypeSignature where++{- Lifting baz to the top level should bring in xx and a as parameters,+   and update the signature to include these+-}+foo a = (baz xx a)+  where+    xx :: Int -> Int -> Int+    xx p1 p2 = p1 + p2++baz :: (Int -> Int -> Int) -> Int ->Int+baz xx a = xx 1 a