packages feed

haskell-tools-refactor 1.0.0.4 → 1.0.1.1

raw patch · 167 files changed

+3747/−42 lines, 167 filesdep +aesondep +eitherdep +haskell-tools-refactordep ~CabalPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: aeson, either, haskell-tools-refactor, old-time, polyparse, tasty, tasty-hunit, time

Dependency ranges changed: Cabal

API changes (from Hackage documentation)

+ Language.Haskell.Tools.Refactor.Monad: instance Exception.ExceptionMonad m => Exception.ExceptionMonad (Control.Monad.Trans.Maybe.MaybeT m)
+ Language.Haskell.Tools.Refactor.Prepare: loadModuleAST :: FilePath -> ModuleName -> Ghc TypedModule
+ Language.Haskell.Tools.Refactor.Prepare: type ModuleName = String
+ Language.Haskell.Tools.Refactor.Querying: LocationQuery :: String -> (RealSrcSpan -> ModuleDom -> [ModuleDom] -> QueryMonad Value) -> QueryChoice
+ Language.Haskell.Tools.Refactor.Querying: [locationQuery] :: QueryChoice -> RealSrcSpan -> ModuleDom -> [ModuleDom] -> QueryMonad Value
+ Language.Haskell.Tools.Refactor.Querying: [queryName] :: QueryChoice -> String
+ Language.Haskell.Tools.Refactor.Querying: data QueryChoice
+ Language.Haskell.Tools.Refactor.Querying: performQuery :: [QueryChoice] -> [String] -> Either FilePath ModuleDom -> [ModuleDom] -> Ghc (Either String Value)
+ Language.Haskell.Tools.Refactor.Querying: queryCommands :: [QueryChoice] -> [String]
+ Language.Haskell.Tools.Refactor.Querying: queryError :: String -> QueryMonad a
+ Language.Haskell.Tools.Refactor.Querying: type QueryMonad = ExceptT String Ghc
+ Language.Haskell.Tools.Refactor.Utils.Extensions: AllowAmbiguousTypes :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: AlternativeLayoutRule :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: AlternativeLayoutRuleTransitional :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: ApplicativeDo :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: Arrows :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: AutoDeriveTypeable :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: BangPatterns :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: BinaryLiterals :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: CApiFFI :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: ConstrainedClassMethods :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: ConstraintKinds :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: Cpp :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: DataKinds :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: DatatypeContexts :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: DefaultSignatures :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: DeriveAnyClass :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: DeriveDataTypeable :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: DeriveFoldable :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: DeriveFunctor :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: DeriveGeneric :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: DeriveLift :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: DeriveTraversable :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: DerivingStrategies :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: DisambiguateRecordFields :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: DoAndIfThenElse :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: DuplicateRecordFields :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: EmptyCase :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: EmptyDataDecls :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: ExistentialQuantification :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: ExplicitForAll :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: ExplicitNamespaces :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: ExtendedDefaultRules :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: FlexibleContexts :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: FlexibleInstances :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: ForeignFunctionInterface :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: FunctionalDependencies :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: GADTSyntax :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: GADTs :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: GHCForeignImportPrim :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: GeneralizedNewtypeDeriving :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: ImplicitParams :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: ImplicitPrelude :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: ImpredicativeTypes :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: IncoherentInstances :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: InstanceSigs :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: InterruptibleFFI :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: JavaScriptFFI :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: KindSignatures :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: LambdaCase :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: LiberalTypeSynonyms :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: MagicHash :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: MonadComprehensions :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: MonadFailDesugaring :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: MonoLocalBinds :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: MonoPatBinds :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: MonomorphismRestriction :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: MultiParamTypeClasses :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: MultiWayIf :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: NPlusKPatterns :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: NamedWildCards :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: NegativeLiterals :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: NondecreasingIndentation :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: NullaryTypeClasses :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: NumDecimals :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: OverlappingInstances :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: OverloadedLabels :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: OverloadedLists :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: OverloadedStrings :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: PackageImports :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: ParallelArrays :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: ParallelListComp :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: PartialTypeSignatures :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: PatternGuards :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: PatternSynonyms :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: PolyKinds :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: PostfixOperators :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: QuasiQuotes :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: RankNTypes :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: RebindableSyntax :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: RecordPuns :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: RecordWildCards :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: RecursiveDo :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: RelaxedLayout :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: RelaxedPolyRec :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: RoleAnnotations :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: ScopedTypeVariables :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: StandaloneDeriving :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: StaticPointers :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: Strict :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: StrictData :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: TemplateHaskell :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: TemplateHaskellQuotes :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: TraditionalRecordSyntax :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: TransformListComp :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: TupleSections :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: TypeApplications :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: TypeFamilies :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: TypeFamilyDependencies :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: TypeInType :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: TypeOperators :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: TypeSynonymInstances :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: UnboxedSums :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: UnboxedTuples :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: UndecidableInstances :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: UndecidableSuperClasses :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: UnicodeSyntax :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: UnliftedFFITypes :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: ViewPatterns :: Extension
+ Language.Haskell.Tools.Refactor.Utils.Extensions: canonExt :: String -> String
+ Language.Haskell.Tools.Refactor.Utils.Extensions: data Extension :: *
+ Language.Haskell.Tools.Refactor.Utils.Extensions: replaceDeprecated :: Extension -> Extension
+ Language.Haskell.Tools.Refactor.Utils.Maybe: MaybeT :: m Maybe a -> MaybeT a
+ Language.Haskell.Tools.Refactor.Utils.Maybe: [runMaybeT] :: MaybeT a -> m Maybe a
+ Language.Haskell.Tools.Refactor.Utils.Maybe: liftMaybe :: (Monad m) => Maybe a -> MaybeT m a
+ Language.Haskell.Tools.Refactor.Utils.Maybe: maybeT :: Monad m => b -> (a -> b) -> MaybeT m a -> m b
+ Language.Haskell.Tools.Refactor.Utils.Maybe: maybeTM :: Monad m => m b -> (a -> m b) -> MaybeT m a -> m b
+ Language.Haskell.Tools.Refactor.Utils.Maybe: newtype MaybeT (m :: * -> *) a :: (* -> *) -> * -> *
+ Language.Haskell.Tools.Refactor.Utils.NameLookup: declHeadSemName :: GhcMonad m => DeclHead -> MaybeT m Name
+ Language.Haskell.Tools.Refactor.Utils.NameLookup: instHeadSemName :: GhcMonad m => InstanceHead -> MaybeT m Name
+ Language.Haskell.Tools.Refactor.Utils.NameLookup: opSemName :: GhcMonad m => Operator -> MaybeT m Name
+ Language.Haskell.Tools.Refactor.Utils.Type: appTypeMatches :: [ClsInst] -> Type -> [Type] -> Maybe (TCvSubst, Type)
+ Language.Haskell.Tools.Refactor.Utils.Type: literalType :: Literal -> Ghc Type
+ Language.Haskell.Tools.Refactor.Utils.Type: typeExpr :: Expr -> Ghc Type
+ Language.Haskell.Tools.Refactor.Utils.TypeLookup: hasConstraintKind :: Type -> Bool
+ Language.Haskell.Tools.Refactor.Utils.TypeLookup: isNewtype :: GhcMonad m => Type -> m Bool
+ Language.Haskell.Tools.Refactor.Utils.TypeLookup: isNewtypeTyCon :: TyThing -> Bool
+ Language.Haskell.Tools.Refactor.Utils.TypeLookup: isVanillaDataConNameM :: (HasNameInfo' n, GhcMonad m) => n -> MaybeT m Bool
+ Language.Haskell.Tools.Refactor.Utils.TypeLookup: lookupClassFromDeclHead :: GhcMonad m => DeclHead -> MaybeT m Class
+ Language.Haskell.Tools.Refactor.Utils.TypeLookup: lookupClassFromInstance :: GhcMonad m => InstanceHead -> MaybeT m Class
+ Language.Haskell.Tools.Refactor.Utils.TypeLookup: lookupClassWith :: GhcMonad m => (a -> MaybeT m Name) -> a -> MaybeT m Class
+ Language.Haskell.Tools.Refactor.Utils.TypeLookup: lookupSynDef :: TyThing -> Maybe TyCon
+ Language.Haskell.Tools.Refactor.Utils.TypeLookup: lookupType :: GhcMonad m => Type -> MaybeT m TyThing
+ Language.Haskell.Tools.Refactor.Utils.TypeLookup: lookupTypeFromGlobalName :: (HasNameInfo' n, GhcMonad m) => n -> MaybeT m Type
+ Language.Haskell.Tools.Refactor.Utils.TypeLookup: lookupTypeFromId :: (HasIdInfo' id, GhcMonad m) => id -> MaybeT m Type
+ Language.Haskell.Tools.Refactor.Utils.TypeLookup: lookupTypeSynRhs :: (HasNameInfo' n, GhcMonad m) => n -> MaybeT m Type
+ Language.Haskell.Tools.Refactor.Utils.TypeLookup: nameFromType :: Type -> Maybe Name
+ Language.Haskell.Tools.Refactor.Utils.TypeLookup: semanticsType :: GhcMonad m => Type -> MaybeT m Type
+ Language.Haskell.Tools.Refactor.Utils.TypeLookup: semanticsTypeSynRhs :: GhcMonad m => Type -> MaybeT m Type
+ Language.Haskell.Tools.Refactor.Utils.TypeLookup: tyconFromGHCType :: Type -> Maybe TyCon
+ Language.Haskell.Tools.Refactor.Utils.TypeLookup: tyconFromTyThing :: TyThing -> Maybe TyCon
+ Language.Haskell.Tools.Refactor.Utils.TypeLookup: typeFromTyThing :: TyThing -> Maybe Type
+ Language.Haskell.Tools.Refactor.Utils.TypeLookup: typeOrKindFromId :: HasIdInfo' id => id -> Type
- Language.Haskell.Tools.Refactor: type Domain d = (Typeable * d, Data d, (~) * SemanticInfo' d SameInfoDefaultCls NoSemanticInfo, Data SemanticInfo' d SameInfoNameCls, Data SemanticInfo' d SameInfoExprCls, Data SemanticInfo' d SameInfoImportCls, Data SemanticInfo' d SameInfoModuleCls, Data SemanticInfo' d SameInfoWildcardCls, Show SemanticInfo' d SameInfoNameCls, Show SemanticInfo' d SameInfoExprCls, Show SemanticInfo' d SameInfoImportCls, Show SemanticInfo' d SameInfoModuleCls, Show SemanticInfo' d SameInfoWildcardCls)
+ Language.Haskell.Tools.Refactor: type Domain d = (Typeable * d, Data d, (~) * SemanticInfo' d SemaInfoDefaultCls NoSemanticInfo, Data SemanticInfo' d SemaInfoNameCls, Data SemanticInfo' d SemaInfoLitCls, Data SemanticInfo' d SemaInfoExprCls, Data SemanticInfo' d SemaInfoImportCls, Data SemanticInfo' d SemaInfoModuleCls, Data SemanticInfo' d SemaInfoWildcardCls)
- Language.Haskell.Tools.Refactor.Prepare: loadModule :: String -> String -> Ghc ModSummary
+ Language.Haskell.Tools.Refactor.Prepare: loadModule :: FilePath -> ModuleName -> Ghc ModSummary
- Language.Haskell.Tools.Refactor.Prepare: toBootFileName :: FilePath -> String -> FilePath
+ Language.Haskell.Tools.Refactor.Prepare: toBootFileName :: FilePath -> ModuleName -> FilePath
- Language.Haskell.Tools.Refactor.Prepare: toFileName :: FilePath -> String -> FilePath
+ Language.Haskell.Tools.Refactor.Prepare: toFileName :: FilePath -> ModuleName -> FilePath
- Language.Haskell.Tools.Refactor.Prepare: tryRefactor :: (RealSrcSpan -> Refactoring) -> String -> String -> IO ()
+ Language.Haskell.Tools.Refactor.Prepare: tryRefactor :: (RealSrcSpan -> Refactoring) -> String -> ModuleName -> IO ()

Files

Language/Haskell/Tools/Refactor.hs view
@@ -5,17 +5,21 @@     , module Language.Haskell.Tools.AST.References
     , module Language.Haskell.Tools.AST.Helpers
     , module Language.Haskell.Tools.Refactor.Utils.Monadic
-  , module Language.Haskell.Tools.Refactor.Utils.Helpers
+    , module Language.Haskell.Tools.Refactor.Utils.Helpers
     , module Language.Haskell.Tools.Rewrite.ElementTypes
     , module Language.Haskell.Tools.Refactor.Prepare
     , module Language.Haskell.Tools.Refactor.Utils.Lists
     , module Language.Haskell.Tools.Refactor.Utils.BindingElem
     , module Language.Haskell.Tools.Refactor.Utils.Indentation
+    , module Language.Haskell.Tools.Refactor.Querying
     , module Language.Haskell.Tools.Refactor.Refactoring
     , module Language.Haskell.Tools.Refactor.Utils.Name
     , module Language.Haskell.Tools.Refactor.Representation
     , module Language.Haskell.Tools.Refactor.Monad
-  , Ann, HasSourceInfo(..), HasRange(..), annListElems, annListAnnot, annList, annJust, annMaybe, isAnnNothing, Domain, Dom, IdDom
+    , module Language.Haskell.Tools.Refactor.Utils.Type
+    , module Language.Haskell.Tools.Refactor.Utils.TypeLookup
+    , module Language.Haskell.Tools.Refactor.Utils.NameLookup
+    , Ann, HasSourceInfo(..), HasRange(..), annListElems, annListAnnot, annList, annJust, annMaybe, isAnnNothing, Domain, Dom, IdDom
     , shortShowSpan, shortShowSpanWithFile, SrcTemplateStage, SourceInfoTraversal(..)
     -- elements of source templates
     , sourceTemplateNodeRange, sourceTemplateNodeElems
@@ -31,20 +35,25 @@ import Language.Haskell.Tools.AST.Helpers
 import Language.Haskell.Tools.AST.References
 import Language.Haskell.Tools.AST.SemaInfoClasses
-import Language.Haskell.Tools.BackendGHC (SpliceInsertionProblem(..), ConvertionProblem(..))
-import Language.Haskell.Tools.PrettyPrint (PrettyPrintProblem(..))
 import Language.Haskell.Tools.PrettyPrint.Prepare
 import Language.Haskell.Tools.Refactor.Monad
-import Language.Haskell.Tools.Refactor.Prepare
+import Language.Haskell.Tools.Refactor.Prepare hiding (ModuleName)
 import Language.Haskell.Tools.Refactor.Refactoring
 import Language.Haskell.Tools.Refactor.Representation
 import Language.Haskell.Tools.Refactor.Utils.BindingElem
 import Language.Haskell.Tools.Refactor.Utils.Helpers
 import Language.Haskell.Tools.Refactor.Utils.Indentation
 import Language.Haskell.Tools.Refactor.Utils.Lists
+import Language.Haskell.Tools.Refactor.Utils.Maybe
 import Language.Haskell.Tools.Refactor.Utils.Monadic
 import Language.Haskell.Tools.Refactor.Utils.Name
+import Language.Haskell.Tools.Refactor.Utils.NameLookup
+import Language.Haskell.Tools.Refactor.Utils.Type
+import Language.Haskell.Tools.Refactor.Utils.TypeLookup
+import Language.Haskell.Tools.Refactor.Querying
 import Language.Haskell.Tools.Rewrite
 import Language.Haskell.Tools.Rewrite.ElementTypes
 
 import Language.Haskell.Tools.AST.Ann
+import Language.Haskell.Tools.BackendGHC (SpliceInsertionProblem(..), ConvertionProblem(..))
+import Language.Haskell.Tools.PrettyPrint (PrettyPrintProblem(..))
Language/Haskell/Tools/Refactor/Monad.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE FlexibleInstances, GeneralizedNewtypeDeriving #-}
+
 -- | Types and instances for monadic refactorings. The refactoring monad provides automatic
 -- importing, keeping important source fragments (such as preprocessor pragmas), and providing
 -- contextual information for refactorings.
@@ -11,6 +12,7 @@ import Control.Monad.Trans.Except (ExceptT(..), throwE, runExceptT)
 import Control.Monad.Trans.Reader (ReaderT(..))
 import Control.Monad.Trans.Writer (WriterT(..))
+import Control.Monad.Trans.Maybe  (MaybeT(..))
 import Control.Monad.Writer
 import DynFlags (HasDynFlags(..))
 import Exception (ExceptionMonad(..))
@@ -122,3 +124,7 @@ instance ExceptionMonad m => ExceptionMonad (ExceptT s m) where
   gcatch e c = ExceptT (runExceptT e `gcatch` (runExceptT . c))
   gmask m = ExceptT $ gmask (\f -> runExceptT $ m (ExceptT . f . runExceptT))
+
+instance (ExceptionMonad m) => ExceptionMonad (MaybeT m) where
+  gcatch action handler = MaybeT $ runMaybeT action `gcatch` (runMaybeT . handler)
+  gmask m = MaybeT $ gmask (\f -> runMaybeT $ m (\x -> MaybeT . f . runMaybeT $ x))
Language/Haskell/Tools/Refactor/Prepare.hs view
@@ -1,11 +1,11 @@-{-# LANGUAGE FlexibleContexts, LambdaCase, MultiWayIf, ScopedTypeVariables, TypeFamilies, TupleSections #-}
+{-# LANGUAGE FlexibleContexts, LambdaCase, MonoLocalBinds, ScopedTypeVariables #-}+
 -- | Defines utility methods that prepare Haskell modules for refactoring
 module Language.Haskell.Tools.Refactor.Prepare where
 
 import Control.Exception
 import Control.Monad
 import Control.Monad.IO.Class (MonadIO(..))
-import Data.IORef
 import Data.List ((\\), isSuffixOf)
 import Data.List.Split (splitOn)
 import Data.Maybe (Maybe(..), fromMaybe, fromJust)
@@ -16,15 +16,11 @@ import CmdLineParser (CmdLineP(..), processArgs)
 import DynFlags
 import FastString (mkFastString)
-import GHC hiding (loadModule)
+import GHC hiding (loadModule, ModuleName)
 import qualified GHC (loadModule)
 import GHC.Paths ( libdir )
 import GhcMonad
 import HscTypes
-import TcRnTypes
-import TcRnMonad
-import TcRnDriver
-import Linker (unload)
 import Outputable (Outputable(..), showSDocUnsafe)
 import Packages (initPackages)
 import SrcLoc
@@ -38,9 +34,12 @@ import Language.Haskell.Tools.Refactor.Representation
 import Language.Haskell.Tools.Refactor.Utils.Monadic (runRefactor)
 
+-- | Type synonym for module names.
+type ModuleName = String
 
+
 -- | A quick function to try the refactorings
-tryRefactor :: (RealSrcSpan -> Refactoring) -> String -> String -> IO ()
+tryRefactor :: (RealSrcSpan -> Refactoring) -> String -> ModuleName -> IO ()
 tryRefactor refact moduleName span
   = runGhc (Just libdir) $ do
       initGhcFlags
@@ -68,13 +67,13 @@   dynflags <- getSessionDynFlags
   let change = runCmdLine $ processArgs flagsAll lArgs
   let ((leftovers, errs, warnings), newDynFlags) = change dynflags
-  when (not (null warnings))
+  unless (null warnings)
     $ liftIO $ putStrLn $ showSDocUnsafe $ ppr warnings
-  when (not (null errs))
+  unless (null errs)
     $ liftIO $ putStrLn $ showSDocUnsafe $ ppr errs
   void $ setSessionDynFlags newDynFlags
   when (any ("-package-db" `isSuffixOf`) args) reloadPkgDb
-  return $ (map unLoc leftovers, snd . change)
+  return (map unLoc leftovers, snd . change)
 
 -- | Reloads the package database based on the session flags
 reloadPkgDb :: Ghc ()
@@ -94,14 +93,12 @@ initGhcFlags' :: Bool -> Bool -> Ghc ()
 initGhcFlags' needsCodeGen errorsSuppressed = do
   dflags <- getSessionDynFlags
-  env <- getSession
-  liftIO $ unload env [] -- clear linker state if ghc was used in the same process
   void $ setSessionDynFlags
     $ flip gopt_set Opt_KeepRawTokenStream
     $ flip gopt_set Opt_NoHsMain
     $ (if errorsSuppressed then flip gopt_set Opt_DeferTypeErrors
-                                  . flip gopt_set Opt_DeferTypedHoles	 
-                                  . flip gopt_set Opt_DeferOutOfScopeVariables 
+                                  . flip gopt_set Opt_DeferTypedHoles
+                                  . flip gopt_set Opt_DeferOutOfScopeVariables
                            else id)
     $ dflags { importPaths = []
              , hscTarget = if needsCodeGen then HscInterpreted else HscNothing
@@ -123,11 +120,11 @@   void $ setSessionDynFlags dynflags { importPaths = importPaths dynflags \\ workingDirs }
 
 -- | Translates module name and working directory into the name of the file where the given module should be defined
-toFileName :: FilePath -> String -> FilePath
+toFileName :: FilePath -> ModuleName -> FilePath
 toFileName workingDir mod = normalise $ workingDir </> map (\case '.' -> pathSeparator; c -> c) mod ++ ".hs"
 
 -- | Translates module name and working directory into the name of the file where the boot module should be defined
-toBootFileName :: FilePath -> String -> FilePath
+toBootFileName :: FilePath -> ModuleName -> FilePath
 toBootFileName workingDir mod = normalise $ workingDir </> map (\case '.' -> pathSeparator; c -> c) mod ++ ".hs-boot"
 
 -- | Get the source directory where the module is located.
@@ -150,8 +147,15 @@ getModSumName :: ModSummary -> String
 getModSumName = GHC.moduleNameString . moduleName . ms_mod
 
+-- | Load the AST of a module given by the working directory and module name.
+loadModuleAST :: FilePath -> ModuleName -> Ghc TypedModule
+loadModuleAST workingDir moduleName = do
+  useFlags ["-w"]
+  modSummary <- loadModule workingDir moduleName
+  parseTyped modSummary
+
 -- | Load the summary of a module given by the working directory and module name.
-loadModule :: String -> String -> Ghc ModSummary
+loadModule :: FilePath -> ModuleName -> Ghc ModSummary
 loadModule workingDir moduleName
   = do initGhcFlagsForTest
        useDirs [workingDir]
@@ -178,7 +182,7 @@   srcBuffer <- if hasCppExtension
                     then liftIO $ hGetStringBuffer (getModSumOrig ms)
                     else return (fromJust $ ms_hspp_buf $ pm_mod_summary p)
-  withTempSession (\e -> e { hsc_dflags = ms_hspp_opts ms }) 
+  withTempSession (\e -> e { hsc_dflags = ms_hspp_opts ms })
     $ (if hasCppExtension then prepareASTCpp else prepareAST) srcBuffer . placeComments (fst annots) (getNormalComments $ snd annots)
         <$> (addTypeInfos (typecheckedSource tc)
                =<< (do parseTrf <- runTrf (fst annots) (getPragmaComments $ snd annots) $ trfModule ms (pm_parsed_source p)
+ Language/Haskell/Tools/Refactor/Querying.hs view
@@ -0,0 +1,40 @@+module Language.Haskell.Tools.Refactor.Querying where
+
+import Control.Monad.Trans.Except (ExceptT, runExceptT, throwE)
+import Data.List ((++), map, find)
+import Data.Aeson (Value)
+
+import GHC (RealSrcSpan, Ghc)
+
+import Language.Haskell.Tools.AST ()
+import Language.Haskell.Tools.Refactor.Monad (ProjectRefactoring, Refactoring)
+import Language.Haskell.Tools.Refactor.Prepare (correctRefactorSpan, readSrcSpan)
+import Language.Haskell.Tools.Refactor.Representation (RefactorChange, ModuleDom)
+
+data QueryChoice = LocationQuery
+                     { queryName :: String
+                     , locationQuery :: RealSrcSpan -> ModuleDom -> [ModuleDom] -> QueryMonad Value
+                     }
+
+type QueryMonad = ExceptT String Ghc
+
+queryCommands :: [QueryChoice] -> [String]
+queryCommands = map queryName
+
+queryError :: String -> QueryMonad a
+queryError = throwE
+
+performQuery :: [QueryChoice] -- ^ The set of available queries
+                  -> [String] -- ^ The query command
+                  -> Either FilePath ModuleDom -- ^ The module in which the refactoring is performed
+                  -> [ModuleDom] -- ^ Other modules
+                  -> Ghc (Either String Value)
+performQuery queries (name:args) mod mods =
+  case (query, mod, args) of
+    (Just (LocationQuery _ query), Right mod, sp:_)
+      -> runExceptT $ query (correctRefactorSpan (snd mod) $ readSrcSpan sp) mod mods
+    (Just (LocationQuery _ query), _, _)
+      -> return $ Left $ "The query '" ++ name ++ "' needs one argument: a source range"
+    (Nothing, _, _)
+      -> return $ Left $ "Unknown command: " ++ name
+  where query = find ((== name) . queryName) queries
Language/Haskell/Tools/Refactor/Refactoring.hs view
@@ -4,6 +4,7 @@ 
 import Control.Monad.Trans.Except (runExceptT)
 import Data.List ((++), map, find)
+import Data.Aeson (Value)
 
 import GHC (RealSrcSpan, Ghc)
 
Language/Haskell/Tools/Refactor/Representation.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE FlexibleInstances, TemplateHaskell #-}
+
 -- | Representation of modules, their collections, refactoring changes and exceptions.
 module Language.Haskell.Tools.Refactor.Representation where
 
Language/Haskell/Tools/Refactor/Utils/AST.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE AllowAmbiguousTypes, LambdaCase #-}
+
 -- | Operations for changing the AST
 module Language.Haskell.Tools.Refactor.Utils.AST (removeChild, removeSeparator) where
 
Language/Haskell/Tools/Refactor/Utils/BindingElem.hs view
@@ -1,4 +1,5 @@-{-# LANGUAGE FlexibleContexts, TypeFamilies #-}
+{-# LANGUAGE FlexibleContexts, MonoLocalBinds #-}
+
 -- | Utilities for transformations that work on both top-level and local definitions
 module Language.Haskell.Tools.Refactor.Utils.BindingElem where
 
Language/Haskell/Tools/Refactor/Utils/Extensions.hs view
@@ -1,13 +1,16 @@  -- all extensions should be matched
 
-module Language.Haskell.Tools.Refactor.Utils.Extensions where
+module Language.Haskell.Tools.Refactor.Utils.Extensions
+  ( module Language.Haskell.Tools.Refactor.Utils.Extensions
+  , GHC.Extension(..)
+  ) where
 
 import Control.Reference ((^.), _1, _2, _3)
 import Language.Haskell.Extension (KnownExtension(..))
 import qualified Language.Haskell.TH.LanguageExtensions as GHC (Extension(..))
 
 
-
+-- | Expands an extension into all the extensions it implies (keeps original as well)
 expandExtension :: GHC.Extension -> [GHC.Extension]
 expandExtension ext = ext : implied
   where fst' = (^. _1) :: (a,b,c) -> a
@@ -16,6 +19,10 @@ 
         implied = map trd' . filter snd' . filter ((== ext) . fst') $ impliedXFlags
 
+-- | Replaces deprecated extensions with their new counterpart
+replaceDeprecated :: GHC.Extension -> GHC.Extension
+replaceDeprecated GHC.NullaryTypeClasses = GHC.MultiParamTypeClasses
+replaceDeprecated x = x
 
 turnOn  = True
 turnOff = False
@@ -52,6 +59,14 @@     , (GHC.TemplateHaskell,           turnOn,  GHC.TemplateHaskellQuotes)
     , (GHC.Strict,                    turnOn,  GHC.StrictData)
     ]
+
+-- | Canonicalize extensions
+canonExt :: String -> String
+canonExt "CPP" = "Cpp"
+canonExt "Rank2Types" = "RankNTypes"
+canonExt "NamedFieldPuns" = "RecordPuns"
+canonExt "GeneralisedNewtypeDeriving" = "GeneralizedNewtypeDeriving"
+canonExt e = e
 
 -- * Mapping of Cabal haskell extensions to their GHC counterpart
 
Language/Haskell/Tools/Refactor/Utils/Helpers.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE FlexibleContexts, LambdaCase, RankNTypes #-}
+
 -- | Helper functions for defining refactorings.
 module Language.Haskell.Tools.Refactor.Utils.Helpers where
 
Language/Haskell/Tools/Refactor/Utils/Lists.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE TypeApplications #-}
+
 -- | Defines operation on AST lists.
 -- AST lists carry source information so simple list modification is not enough.
 module Language.Haskell.Tools.Refactor.Utils.Lists where
+ Language/Haskell/Tools/Refactor/Utils/Maybe.hs view
@@ -0,0 +1,18 @@+module Language.Haskell.Tools.Refactor.Utils.Maybe
+ ( module Language.Haskell.Tools.Refactor.Utils.Maybe
+ , module Data.Maybe
+ , MaybeT(..)
+ ) where
+
+import Data.Maybe
+import Control.Monad
+import Control.Monad.Trans.Maybe (MaybeT(..))
+
+liftMaybe :: (Monad m) => Maybe a -> MaybeT m a
+liftMaybe = MaybeT . return
+
+maybeT :: Monad m => b -> (a -> b) -> MaybeT m a -> m b
+maybeT def f x = liftM (maybe def f) (runMaybeT x)
+
+maybeTM :: Monad m => m b -> (a -> m b) -> MaybeT m a -> m b
+maybeTM def f x = runMaybeT x >>= maybe def f
Language/Haskell/Tools/Refactor/Utils/Monadic.hs view
@@ -1,11 +1,12 @@-{-# LANGUAGE FlexibleContexts, FlexibleInstances, MultiWayIf, TypeApplications, TypeFamilies #-}
+{-# LANGUAGE FlexibleContexts, MonoLocalBinds, MultiWayIf, TypeApplications #-}
+
 -- | Basic utilities and types for defining refactorings.
 module Language.Haskell.Tools.Refactor.Utils.Monadic where
 
 import Control.Monad.Reader (Monad(..), ReaderT(..), MonadReader(..))
 import Control.Monad.State.Strict
+import Control.Monad.Writer
 import Control.Monad.Trans.Except (runExceptT)
-import Control.Monad.Writer (Monad(..), WriterT(..), MonadWriter(..))
 import Control.Reference hiding (element)
 import Data.Either
 import Data.Function (on)
@@ -146,7 +147,7 @@ referenceOperator = referenceName' mkQualOp'
 
 -- | Create a name that references the definition. Generates an import if the definition is not yet imported.
-referenceName' :: ([String] -> GHC.Name -> Ann nt IdDom SrcTemplateStage) -> GHC.Name 
+referenceName' :: ([String] -> GHC.Name -> Ann nt IdDom SrcTemplateStage) -> GHC.Name
                     -> LocalRefactor (Ann nt IdDom SrcTemplateStage)
 referenceName' makeName name
   | name `elem` registeredNamesFromPrelude || qualifiedName name `elem` otherNamesFromPrelude
@@ -165,7 +166,7 @@   where moduleParts = maybe [] (splitOn "." . GHC.moduleNameString . GHC.moduleName) . GHC.nameModule_maybe
 
 -- | Reference the name by the shortest suitable import
-referenceBy :: ([String] -> GHC.Name -> Ann nt IdDom SrcTemplateStage) -> GHC.Name 
+referenceBy :: ([String] -> GHC.Name -> Ann nt IdDom SrcTemplateStage) -> GHC.Name
                  -> [Ann UImportDecl IdDom SrcTemplateStage] -> Ann nt IdDom SrcTemplateStage
 referenceBy makeName name imps =
   let prefixes = map importQualifier imps
Language/Haskell/Tools/Refactor/Utils/Name.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE LambdaCase #-}
+
 -- | Defines utility operations on Haskell names such as checking if a given identifier is a
 -- correct name for a certain kind of Haskell construct.
 module Language.Haskell.Tools.Refactor.Utils.Name where
+ Language/Haskell/Tools/Refactor/Utils/NameLookup.hs view
@@ -0,0 +1,26 @@+module Language.Haskell.Tools.Refactor.Utils.NameLookup where
+
+import GHC (GhcMonad)
+import qualified GHC
+
+import Control.Reference ((^.))
+
+import Language.Haskell.Tools.AST
+import Language.Haskell.Tools.Rewrite
+import Language.Haskell.Tools.Refactor.Utils.Maybe
+
+
+opSemName :: GhcMonad m => Operator -> MaybeT m GHC.Name
+opSemName = liftMaybe . semanticsName . (^. operatorName)
+
+declHeadSemName :: GhcMonad m => DeclHead -> MaybeT m GHC.Name
+declHeadSemName (NameDeclHead n)       = liftMaybe . semanticsName $ n
+declHeadSemName (ParenDeclHead dh)     = declHeadSemName dh
+declHeadSemName (DeclHeadApp dh _)     = declHeadSemName dh
+declHeadSemName (InfixDeclHead _ op _) = opSemName op
+
+instHeadSemName :: GhcMonad m => InstanceHead -> MaybeT m GHC.Name
+instHeadSemName (InstanceHead n)         = liftMaybe . semanticsName $ n
+instHeadSemName (InfixInstanceHead _ op) = opSemName op
+instHeadSemName (ParenInstanceHead ih)   = instHeadSemName ih
+instHeadSemName (AppInstanceHead ih _)   = instHeadSemName ih
+ Language/Haskell/Tools/Refactor/Utils/Type.hs view
@@ -0,0 +1,205 @@+{-# LANGUAGE FlexibleContexts, MonoLocalBinds, RankNTypes, ScopedTypeVariables, TypeApplications #-}
+
+module Language.Haskell.Tools.Refactor.Utils.Type (typeExpr, appTypeMatches, literalType) where
+
+import Data.List
+import Control.Monad.State
+import Control.Reference
+
+import GHC
+import Module as GHC
+import InstEnv as GHC
+import Unify as GHC
+import Type as GHC
+import Name as GHC
+import Var as GHC
+import UniqSupply as GHC
+import Unique as GHC
+import TysWiredIn as GHC
+import TysPrim as GHC
+import PrelNames as GHC
+import ConLike as GHC
+import PatSyn as GHC
+import BasicTypes as GHC
+
+import Language.Haskell.Tools.Rewrite.ElementTypes as AST
+import Language.Haskell.Tools.Rewrite.Match as AST
+import Language.Haskell.Tools.AST as AST
+
+typeExpr :: Expr -> Ghc GHC.Type
+typeExpr e = do usupp <- liftIO $ mkSplitUniqSupply 'z'
+                evalStateT (typeExpr' e) (uniqsFromSupply usupp)
+
+typeExpr' :: Expr -> StateT [Unique] Ghc GHC.Type
+typeExpr' (Var n) = return $ idType $ semanticsId (n ^. simpleName)
+typeExpr' (Lit l) = literalType' l
+typeExpr' (InfixApp lhs op rhs) = do
+  lhsType <- typeExpr' lhs
+  rhsType <- typeExpr' rhs
+  let opType = idType $ semanticsId (op ^. operatorName)
+  let (opt, repack) = splitType' opType
+  case splitFunTys opt of
+    (lhsT:rhsT:rest, resTyp) -> do
+      let subst = tcUnifyTys (\_ -> BindMe) [lhsType, rhsType] [lhsT, rhsT]
+      return $ maybe id substTy subst $ repack (mkFunTys rest resTyp)
+    _ -> resultType
+typeExpr' (PrefixApp op rhs) = do
+  let opType = idType $ semanticsId (op ^. operatorName)
+  argType <- typeExpr' rhs
+  let (ft, repack) = splitType' opType
+  case splitFunTy_maybe ft of
+    Just (argTyp, resTyp) -> do
+      let subst = tcUnifyTy argType argTyp
+      return $ maybe id substTy subst $ repack resTyp
+    _ -> resultType
+typeExpr' (App f arg) = do
+  argType <- typeExpr' arg
+  funType <- typeExpr' f
+  let (ft, repack) = splitType' funType
+  case splitFunTy_maybe ft of
+    Just (argTyp, resTyp) -> do
+      let subst = tcUnifyTy argType argTyp
+      return $ maybe id substTy subst $ repack resTyp
+    Nothing -> return funType
+typeExpr' (Lambda args e) = do
+  (resType, recomp) <- splitType' <$> typeExpr' e
+  (argTypes, recomps) <- unzip <$> mapM (\_ -> splitType' <$> resultType) (args ^? annList)
+  return $ foldr (.) recomp recomps $ mkFunTys argTypes resType
+typeExpr' (Let _ e) = typeExpr' e
+typeExpr' (If _ then' _) = typeExpr' then'
+typeExpr' (MultiIf alts) =
+  case alts ^? annList & caseGuardExpr of e:_ -> typeExpr' e
+                                          _   -> resultType
+typeExpr' (Case _ alts) =
+  case alts ^? annList & altRhs & rhsCaseExpr of e:_ -> typeExpr' e
+                                                 _   -> resultType
+typeExpr' (Do stmts) =
+  case stmts ^? annList & stmtExpr of e:_ -> typeExpr' e
+                                      _   -> resultType
+typeExpr' (Tuple elems) = do
+  (elemTypes, pack) <- unzip . map splitType' <$> mapM typeExpr' (elems ^? annList)
+  return $ foldr (.) id pack $ mkTupleTy Boxed elemTypes
+typeExpr' (AST.UnboxedTuple elems) = do
+  (elemTypes, pack) <- unzip . map splitType' <$> mapM typeExpr' (elems ^? annList)
+  return $ foldr (.) id pack $ mkTupleTy Unboxed elemTypes
+-- typeExpr' (TupleSection elems) 
+--   = let (elems, holes) <- partition (\case Present _ -> True; Missing -> False) elems
+--      in do args <- mapM resultType holes
+-- 
+-- typeExpr' (UnboxedTupSec elems) = 
+typeExpr' (List elems) = do
+  case elems ^? annList of []  -> do (typ, pack) <- splitType' <$> resultType
+                                     return $ pack $ mkListTy typ
+                           e:_ -> do (typ, pack) <- splitType' <$> typeExpr' e
+                                     return $ pack $ mkListTy typ
+typeExpr' (ParArray elems) = do
+  case elems ^? annList of []  -> do (typ, pack) <- splitType' <$> resultType
+                                     return $ pack $ mkPArrTy typ
+                           e:_ -> do (typ, pack) <- splitType' <$> typeExpr' e
+                                     return $ pack $ mkPArrTy typ
+typeExpr' (Paren inner) = typeExpr' inner
+typeExpr' (LeftSection lhs op) = do
+  let opType = idType $ semanticsId (op ^. operatorName)
+  argType <- typeExpr' lhs
+  let (ft, repack) = splitType' opType
+  case splitFunTy_maybe ft of 
+    Just (argTyp, resTyp) -> do
+      let subst = tcUnifyTy argType argTyp
+      return $ maybe id substTy subst $ repack resTyp
+    _ -> resultType
+typeExpr' (RightSection op rhs) = do
+  let opType = idType $ semanticsId (op ^. operatorName)
+  argType <- typeExpr' rhs
+  let (ft, repack) = splitType' opType
+  case splitFunTys ft of 
+    (arg1:arg2:rest, resTyp) -> do 
+      let subst = tcUnifyTy arg2 argType
+      return $ maybe id substTy subst $ repack (mkFunTys (arg1:rest) resTyp)
+    _ -> resultType
+typeExpr' (AST.RecCon name _) 
+  = do def <- lift $ maybe (return Nothing) GHC.lookupName (semanticsName (name ^. simpleName))
+       case def of 
+         Just (AConLike (RealDataCon con)) -> return $ dataConSig con ^. _4
+         Just (AConLike (PatSynCon patSyn)) -> return $ patSynSig patSyn ^. _6
+         _ -> resultType
+typeExpr' (AST.RecUpdate e _) = typeExpr' e
+typeExpr' (AST.Enum from _ _) = mkListTy <$> typeExpr' from
+typeExpr' (AST.ParArrayEnum from _ _) = mkPArrTy <$> typeExpr' from
+typeExpr' (AST.ListComp e _) = mkListTy <$> typeExpr' e
+typeExpr' (AST.ParArrayComp e _) = mkPArrTy <$> typeExpr' e
+-- typeExpr' (AST.UTypeSig _ t) = -- TODO: evaluate type
+typeExpr' Hole = resultType
+typeExpr' _ = resultType
+
+literalType :: Literal -> Ghc GHC.Type
+literalType e = do usupp <- liftIO $ mkSplitUniqSupply 'z'
+                   evalStateT (literalType' e) (uniqsFromSupply usupp)
+
+literalType' :: Literal -> StateT [Unique] Ghc GHC.Type
+literalType' (StringLit {}) = return stringTy
+literalType' (CharLit {}) = return charTy
+literalType' (IntLit {}) = litType numClassName
+literalType' (FracLit {}) = litType fractionalClassName
+literalType' (PrimIntLit {}) = return $ intPrimTy
+literalType' (PrimWordLit {}) = return $ word32PrimTy
+literalType' (PrimFloatLit {}) = return $ floatX4PrimTy
+literalType' (PrimDoubleLit {}) = return $ doubleX2PrimTy
+literalType' (PrimCharLit {}) = return $ charPrimTy
+literalType' (PrimStringLit {}) = return $ addrPrimTy
+
+appTypeMatches :: [ClsInst] -> GHC.Type -> [GHC.Type] -> Maybe (TCvSubst, GHC.Type)
+appTypeMatches insts functionT argTs -- TODO: check instances
+  = let (funT, repackFun) = splitType functionT
+        (args, resT) = splitFunTys funT
+        argTypes = fst $ unzip $ map splitType argTs
+     in if length args >= length argTypes
+          then case tcUnifyTys (\_ -> BindMe) (take (length argTypes) args) argTypes of
+                 Just st -> let (t', check) = repackFun st insts (substTy st $ mkFunTys (drop (length argTypes) args) resT)
+                             in if check then Just (st, t')
+                                         else Nothing
+                 Nothing -> Nothing
+          else Nothing
+
+splitType' :: GHC.Type -> (GHC.Type, GHC.Type -> GHC.Type)
+splitType' t = case splitType t of (t', repack) -> (t', fst . repack emptyTCvSubst [])
+
+splitType :: GHC.Type -> (GHC.Type, TCvSubst -> [ClsInst] -> GHC.Type -> (GHC.Type, Bool))
+splitType typ =
+  let (foralls, typ') = splitForAllTys typ
+      (args, coreType) = splitFunTys typ'
+      (implicitArgs, realArgs) = partition isPredTy args
+      repack subst insts t = (mkInvForAllTys (filter (`elem` tvs) foralls) . mkFunTys keptConstraints $ t, check)
+        where
+          check = and $ map checkInst implicitArgs
+          checkInst t =
+            case splitTyConApp_maybe (substTy subst t) of
+              Just (tc, args) -> case tyConClass_maybe tc of 
+                                   Just cls -> case lookupInstEnv False instEnvs cls args of 
+                                                 ([],[],[]) -> False
+                                                 _          -> True
+                                   Nothing -> True
+              Nothing -> True
+          instEnvs = InstEnvs (extendInstEnvList emptyInstEnv insts) emptyInstEnv emptyModuleSet
+          keptConstraints = filter hasCommonTv implicitArgs
+          tvs = tyCoVarsOfTypeWellScoped t
+          hasCommonTv = not . null . intersect tvs . tyCoVarsOfTypeWellScoped
+   in (mkFunTys realArgs coreType, repack)
+
+resultType :: StateT [Unique] Ghc GHC.Type
+resultType = do 
+  name <- newName
+  let tv = mkTyVar name (mkTyConTy starKindTyCon)
+  return $ mkInvForAllTys [tv] (mkTyVarTy tv)
+
+litType :: GHC.Name -> StateT [Unique] Ghc GHC.Type
+litType constraint = do 
+  Just (ATyCon numTyCon) <- lift $ lookupName constraint
+  name <- newName
+  let tv = mkTyVar name (mkTyConTy starKindTyCon)
+  return $ mkInvForAllTys [tv] $ mkFunTy (mkTyConApp numTyCon [mkTyVarTy tv]) (mkTyVarTy tv)
+
+newName :: Monad m => StateT [Unique] m GHC.Name
+newName = do uniq <- gets head
+             modify tail
+             let occn  = mkOccName tvName "a"
+             return (mkInternalName uniq occn noSrcSpan)
+ Language/Haskell/Tools/Refactor/Utils/TypeLookup.hs view
@@ -0,0 +1,154 @@+{-# LANGUAGE FlexibleContexts, ScopedTypeVariables #-}
+
+module Language.Haskell.Tools.Refactor.Utils.TypeLookup where
+
+import qualified TyCoRep   as GHC (Type(..), TyThing(..))
+import qualified Kind      as GHC (isConstraintKind, typeKind)
+import qualified ConLike   as GHC (ConLike(..))
+import qualified DataCon   as GHC (dataConUserType, isVanillaDataCon)
+import qualified PatSyn    as GHC (patSynBuilder)
+import qualified Var       as GHC (varType)
+import qualified GHC       hiding (typeKind)
+import           GHC       (GhcMonad)
+
+import Language.Haskell.Tools.AST
+import Language.Haskell.Tools.Rewrite
+import Language.Haskell.Tools.Refactor.Utils.NameLookup
+import Language.Haskell.Tools.Refactor.Utils.Maybe
+
+
+hasConstraintKind :: GHC.Type -> Bool
+hasConstraintKind = GHC.isConstraintKind . GHC.typeKind
+
+
+-- | Looks up the Type of an entity with an Id of any locality.
+-- If the entity being scrutinised is a type variable, it fails.
+lookupTypeFromId :: (HasIdInfo' id, GhcMonad m) => id -> MaybeT m GHC.Type
+lookupTypeFromId idn
+  | GHC.isLocalId  . semanticsId $ idn = return . typeOrKindFromId $ idn
+  | GHC.isGlobalId . semanticsId $ idn = lookupTypeFromGlobalName idn
+  | otherwise = fail "Couldn't lookup name"
+
+-- | Looks up the Type or the Kind of an entity that has an Id.
+-- Note: In some cases we only get the Kind of the Id (e.g. for type constructors)
+typeOrKindFromId :: HasIdInfo' id => id -> GHC.Type
+typeOrKindFromId idn = GHC.varType . semanticsId $ idn
+
+-- | Extracts a Type from a TyThing when possible.
+typeFromTyThing :: GHC.TyThing -> Maybe GHC.Type
+typeFromTyThing (GHC.AnId     idn)  = Just . GHC.varType $ idn
+typeFromTyThing (GHC.ATyCon   tc)   = GHC.synTyConRhs_maybe tc
+typeFromTyThing (GHC.ACoAxiom _)    = fail "CoAxioms are not supported for type lookup"
+typeFromTyThing (GHC.AConLike con)  = handleCon con
+  where handleCon (GHC.RealDataCon dc) = Just . GHC.dataConUserType $ dc
+        handleCon (GHC.PatSynCon   pc) = do
+          (idn,_) <- GHC.patSynBuilder pc
+          return . GHC.varType $ idn
+
+-- | Looks up a GHC Type from a Haskell Tools Name (given the name is global)
+-- For an identifier, it returns its type.
+-- For a data constructor, it returns its type.
+-- For a pattern synonym, it returns its builder's type.
+-- For a type synonym constructor, it returns its right-hand side.
+-- For a coaxiom, it fails.
+lookupTypeFromGlobalName :: (HasNameInfo' n, GhcMonad m) => n -> MaybeT m GHC.Type
+lookupTypeFromGlobalName name = do
+  sname <- liftMaybe . semanticsName $ name
+  tt    <- MaybeT    . GHC.lookupName $ sname
+  liftMaybe . typeFromTyThing $ tt
+
+
+-- | Looks up the right-hand side (GHC representation)
+-- of a Haskell Tools Name corresponding to a type synonym
+lookupTypeSynRhs :: (HasNameInfo' n, GhcMonad m) => n -> MaybeT m GHC.Type
+lookupTypeSynRhs name = do
+  sname <- liftMaybe . semanticsName $ name
+  tt    <- MaybeT    . GHC.lookupName $ sname
+  tc    <- liftMaybe . tyconFromTyThing $ tt
+  liftMaybe . GHC.synTyConRhs_maybe $ tc
+
+-- NOTE: Returns Nothing if it is not a type synonym
+lookupSynDef :: GHC.TyThing -> Maybe GHC.TyCon
+lookupSynDef syn = do
+  tycon <- tyconFromTyThing syn
+  rhs   <- GHC.synTyConRhs_maybe tycon
+  tyconFromGHCType rhs
+
+tyconFromTyThing :: GHC.TyThing -> Maybe GHC.TyCon
+tyconFromTyThing (GHC.ATyCon tycon) = Just tycon
+tyconFromTyThing _ = Nothing
+
+-- won't bother
+tyconFromGHCType :: GHC.Type -> Maybe GHC.TyCon
+tyconFromGHCType (GHC.AppTy t1 _) = tyconFromGHCType t1
+tyconFromGHCType (GHC.TyConApp tycon _) = Just tycon
+tyconFromGHCType _ = Nothing
+
+
+-- NOTE: Returns false if the type is certainly not a newtype
+--       Returns true if it is a newtype or it could not have been looked up
+isNewtype :: GhcMonad m => Type -> m Bool
+isNewtype t = do
+  tycon <- runMaybeT . lookupType $ t
+  return $! maybe True isNewtypeTyCon tycon
+
+
+
+lookupType :: GhcMonad m => Type -> MaybeT m GHC.TyThing
+lookupType t = do
+  name  <- liftMaybe . nameFromType $ t
+  sname <- liftMaybe . semanticsName   $ name
+  MaybeT . GHC.lookupName $ sname
+
+-- | Looks up a GHC.Class from something that has a type class constructor in it
+-- Fails if the argument does not contain a class type constructor
+lookupClassWith :: GhcMonad m => (a -> MaybeT m GHC.Name) -> a -> MaybeT m GHC.Class
+lookupClassWith getName x = do
+  sname   <- getName x
+  tything <- MaybeT . GHC.lookupName $ sname
+  case tything of
+    GHC.ATyCon tc | GHC.isClassTyCon tc -> liftMaybe . GHC.tyConClass_maybe $ tc
+    _ -> fail "TypeLookup.lookupClassWith: Argument does not contain a class type constructor"
+
+lookupClassFromInstance :: GhcMonad m => InstanceHead -> MaybeT m GHC.Class
+lookupClassFromInstance = lookupClassWith instHeadSemName
+
+lookupClassFromDeclHead :: GhcMonad m => DeclHead -> MaybeT m GHC.Class
+lookupClassFromDeclHead = lookupClassWith declHeadSemName
+
+-- | Looks up the right-hand side (GHC representation)
+-- of a Haskell Tools Type corresponding to a type synonym
+semanticsTypeSynRhs :: GhcMonad m => Type -> MaybeT m GHC.Type
+semanticsTypeSynRhs ty = (liftMaybe . nameFromType $ ty) >>= lookupTypeSynRhs
+
+-- | Converts a global Haskell Tools type to a GHC type
+semanticsType :: GhcMonad m => Type -> MaybeT m GHC.Type
+semanticsType ty = (liftMaybe . nameFromType $ ty) >>= lookupTypeFromGlobalName
+
+-- | Extracts the name of a type
+-- In case of a type application, it finds the type being applied
+nameFromType :: Type -> Maybe Name
+nameFromType (TypeApp f _)    = nameFromType f
+nameFromType (ParenType x)    = nameFromType x
+nameFromType (KindedType t _) = nameFromType t
+nameFromType (BangType t)     = nameFromType t
+nameFromType (LazyType t)     = nameFromType t
+nameFromType (UnpackType t)   = nameFromType t
+nameFromType (NoUnpackType t) = nameFromType t
+nameFromType (VarType x)      = Just x
+nameFromType _                = Nothing
+
+isNewtypeTyCon :: GHC.TyThing -> Bool
+isNewtypeTyCon (GHC.ATyCon tycon) = GHC.isNewTyCon tycon
+isNewtypeTyCon _ = False
+
+-- | Decides whether a given name is a standard Haskell98 data constructor.
+-- Fails if not given a proper name.
+isVanillaDataConNameM :: (HasNameInfo' n, GhcMonad m) => n -> MaybeT m Bool
+isVanillaDataConNameM name = do
+  sname <- liftMaybe . semanticsName  $ name
+  tt    <- MaybeT    . GHC.lookupName $ sname
+  dc    <- liftMaybe . extractDataCon $ tt
+  return . GHC.isVanillaDataCon $ dc
+  where extractDataCon (GHC.AConLike (GHC.RealDataCon dc)) = Just dc
+        extractDataCon  _                                  = Nothing
+ examples/CPP/ConditionalCode.hs view
@@ -0,0 +1,8 @@+{-# LANGUAGE CPP #-}
+module CPP.ConditionalCode where
+
+#if __GLASGOW_HASKELL__ >= 800
+version = "GHC 8"
+#else
+version = "not GHC 8"
+#endif
+ examples/CPP/JustEnabled.hs view
@@ -0,0 +1,2 @@+{-# LANGUAGE CPP #-}
+module CPP.JustEnabled where
+ examples/CommentHandling/BlockComments.hs view
@@ -0,0 +1,10 @@+module CommentHandling.BlockComments where
+
+{-| 1 -}
+{- 2 -}
+import Control.Monad {- 3 -}
+{-^ 4 -}
+{-| 5 -}
+{- 6 -}
+import Control.Monad as Monad {- 7 -}
+{-^ 8 -}
+ examples/CommentHandling/CommentTypes.hs view
@@ -0,0 +1,10 @@+module CommentHandling.CommentTypes where
+
+-- | 1
+-- 2
+import Control.Monad -- 3
+-- ^ 4
+-- | 5
+-- 6
+import Control.Monad as Monad -- 7
+-- ^ 8
+ examples/CommentHandling/Crosslinking.hs view
@@ -0,0 +1,6 @@+module CommentHandling.Crosslinking where
+
+import Control.Monad
+-- | forward
+-- ^ back
+import Control.Monad as Monad
+ examples/CommentHandling/FunctionArgs.hs view
@@ -0,0 +1,6 @@+module CommentHandling.FunctionArgs where
+
+f :: Int -- something
+  -> {-| result -} Int
+  -> Int  -- ^ other thing
+f = undefined
+ examples/CppHs/Language/Preprocessor/Cpphs.hs view
@@ -0,0 +1,34 @@+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Language.Preprocessor.Cpphs
+-- Copyright   :  2000-2006 Malcolm Wallace
+-- Licence     :  LGPL
+--
+-- Maintainer  :  Malcolm Wallace <Malcolm.Wallace@cs.york.ac.uk>
+-- Stability   :  experimental
+-- Portability :  All
+--
+-- Include the interface that is exported
+-----------------------------------------------------------------------------
+
+module Language.Preprocessor.Cpphs
+  ( runCpphs, runCpphsPass1, runCpphsPass2, runCpphsReturningSymTab
+  , cppIfdef, tokenise, WordStyle(..)
+  , macroPass, macroPassReturningSymTab
+  , CpphsOptions(..), BoolOptions(..)
+  , parseOptions, defaultCpphsOptions, defaultBoolOptions
+  , module Language.Preprocessor.Cpphs.Position
+  ) where
+
+import Language.Preprocessor.Cpphs.CppIfdef(cppIfdef)
+import Language.Preprocessor.Cpphs.MacroPass(macroPass
+                                            ,macroPassReturningSymTab)
+import Language.Preprocessor.Cpphs.RunCpphs(runCpphs
+                                           ,runCpphsPass1
+                                           ,runCpphsPass2
+                                           ,runCpphsReturningSymTab)
+import Language.Preprocessor.Cpphs.Options
+       (CpphsOptions(..), BoolOptions(..), parseOptions
+       ,defaultCpphsOptions,defaultBoolOptions)
+import Language.Preprocessor.Cpphs.Position
+import Language.Preprocessor.Cpphs.Tokenise
+ examples/CppHs/Language/Preprocessor/Cpphs/CppIfdef.hs view
@@ -0,0 +1,416 @@+-----------------------------------------------------------------------------
+-- |
+-- Module      :  CppIfdef
+-- Copyright   :  1999-2004 Malcolm Wallace
+-- Licence     :  LGPL
+-- 
+-- Maintainer  :  Malcolm Wallace <Malcolm.Wallace@cs.york.ac.uk>
+-- Stability   :  experimental
+-- Portability :  All
+
+-- Perform a cpp.first-pass, gathering \#define's and evaluating \#ifdef's.
+-- and \#include's.
+-----------------------------------------------------------------------------
+
+module Language.Preprocessor.Cpphs.CppIfdef
+  ( cppIfdef    -- :: FilePath -> [(String,String)] -> [String] -> Options
+                --      -> String -> IO [(Posn,String)]
+  ) where
+
+
+import Text.Parse
+import Language.Preprocessor.Cpphs.SymTab
+import Language.Preprocessor.Cpphs.Position  (Posn,newfile,newline,newlines
+                                             ,cppline,cpp2hask,newpos)
+import Language.Preprocessor.Cpphs.ReadFirst (readFirst)
+import Language.Preprocessor.Cpphs.Tokenise  (linesCpp,reslash)
+import Language.Preprocessor.Cpphs.Options   (BoolOptions(..))
+import Language.Preprocessor.Cpphs.HashDefine(HashDefine(..),parseHashDefine
+                                             ,expandMacro)
+import Language.Preprocessor.Cpphs.MacroPass (preDefine,defineMacro)
+import Data.Char        (isDigit,isSpace,isAlphaNum)
+import Data.List        (intercalate,isPrefixOf)
+import Numeric          (readHex,readOct,readDec)
+import System.IO.Unsafe (unsafeInterleaveIO)
+import System.IO        (hPutStrLn,stderr)
+import Control.Monad    (when)
+
+-- | Run a first pass of cpp, evaluating \#ifdef's and processing \#include's,
+--   whilst taking account of \#define's and \#undef's as we encounter them.
+cppIfdef :: FilePath            -- ^ File for error reports
+        -> [(String,String)]    -- ^ Pre-defined symbols and their values
+        -> [String]             -- ^ Search path for \#includes
+        -> BoolOptions          -- ^ Options controlling output style
+        -> String               -- ^ The input file content
+        -> IO [(Posn,String)]   -- ^ The file after processing (in lines)
+cppIfdef fp syms search options =
+    cpp posn defs search options (Keep []) . initial . linesCpp
+  where
+    posn = newfile fp
+    defs = preDefine options syms
+    initial = if literate options then id else (cppline posn:)
+-- Previous versions had a very simple symbol table  mapping strings
+-- to strings.  Now the #ifdef pass uses a more elaborate table, in
+-- particular to deal with parameterised macros in conditionals.
+
+
+-- | Internal state for whether lines are being kept or dropped.
+--   In @Drop n b ps@, @n@ is the depth of nesting, @b@ is whether
+--   we have already succeeded in keeping some lines in a chain of
+--   @elif@'s, and @ps@ is the stack of positions of open @#if@ contexts,
+--   used for error messages in case EOF is reached too soon.
+data KeepState = Keep [Posn] | Drop Int Bool [Posn]
+
+-- | Return just the list of lines that the real cpp would decide to keep.
+cpp :: Posn -> SymTab HashDefine -> [String] -> BoolOptions -> KeepState
+       -> [String] -> IO [(Posn,String)]
+
+cpp _ _ _ _ (Keep ps) [] | not (null ps) = do
+    hPutStrLn stderr $ "Unmatched #if: positions of open context are:\n"++
+                       unlines (map show ps)
+    return []
+cpp _ _ _ _ _ [] = return []
+
+cpp p syms path options (Keep ps) (l@('#':x):xs) =
+    let ws = words x
+        cmd = if null ws then "" else head ws
+        line = tail ws
+        sym  = head (tail ws)
+        rest = tail (tail ws)
+        def = defineMacro options (sym++" "++ maybe "1" id (un rest))
+        un v = if null v then Nothing else Just (unwords v)
+        keepIf b = if b then Keep (p:ps) else Drop 1 False (p:ps)
+        skipn syms' retain ud xs' =
+            let n = 1 + length (filter (=='\n') l) in
+            (if macros options && retain then emitOne  (p,reslash l)
+                                         else emitMany (replicate n (p,""))) $
+            cpp (newlines n p) syms' path options ud xs'
+    in case cmd of
+        "define" -> skipn (insertST def syms) True (Keep ps) xs
+        "undef"  -> skipn (deleteST sym syms) True (Keep ps) xs
+        "ifndef" -> skipn syms False (keepIf (not (definedST sym syms))) xs
+        "ifdef"  -> skipn syms False (keepIf      (definedST sym syms)) xs
+        "if"     -> do b <- gatherDefined p syms (unwords line)
+                       skipn syms False (keepIf b) xs
+        "else"   -> skipn syms False (Drop 1 False ps) xs
+        "elif"   -> skipn syms False (Drop 1 True ps) xs
+        "endif"  | null ps ->
+                    do hPutStrLn stderr $ "Unmatched #endif at "++show p
+                       return []
+        "endif"  -> skipn syms False (Keep (tail ps)) xs
+        "pragma" -> skipn syms True  (Keep ps) xs
+        ('!':_)  -> skipn syms False (Keep ps) xs       -- \#!runhs scripts
+        "include"-> do (inc,content) <- readFirst (file syms (unwords line))
+                                                  p path
+                                                  (warnings options)
+                       cpp p syms path options (Keep ps)
+                             (("#line 1 "++show inc): linesCpp content
+                                                    ++ cppline (newline p): xs)
+        "warning"-> if warnings options then
+                      do hPutStrLn stderr (l++"\nin "++show p)
+                         skipn syms False (Keep ps) xs
+                    else skipn syms False (Keep ps) xs
+        "error"  -> error (l++"\nin "++show p)
+        "line"   | all isDigit sym
+                 -> (if locations options && hashline options then emitOne (p,l)
+                     else if locations options then emitOne (p,cpp2hask l)
+                     else id) $
+                    cpp (newpos (read sym) (un rest) p)
+                        syms path options (Keep ps) xs
+        n | all isDigit n && not (null n)
+                 -> (if locations options && hashline options then emitOne (p,l)
+                     else if locations options then emitOne (p,cpp2hask l)
+                     else id) $
+                    cpp (newpos (read n) (un (tail ws)) p)
+                        syms path options (Keep ps) xs
+          | otherwise
+                 -> do when (warnings options) $
+                           hPutStrLn stderr ("Warning: unknown directive #"++n
+                                             ++"\nin "++show p)
+                       emitOne (p,l) $
+                               cpp (newline p) syms path options (Keep ps) xs
+
+cpp p syms path options (Drop n b ps) (('#':x):xs) =
+    let ws = words x
+        cmd = if null ws then "" else head ws
+        delse    | n==1 && b = Drop 1 b ps
+                 | n==1      = Keep ps
+                 | otherwise = Drop n b ps
+        dend     | n==1      = Keep (tail ps)
+                 | otherwise = Drop (n-1) b (tail ps)
+        delif v  | n==1 && not b && v
+                             = Keep ps
+                 | otherwise = Drop n b ps
+        skipn ud xs' =
+                 let n' = 1 + length (filter (=='\n') x) in
+                 emitMany (replicate n' (p,"")) $
+                    cpp (newlines n' p) syms path options ud xs'
+    in
+    if      cmd == "ifndef" ||
+            cmd == "if"     ||
+            cmd == "ifdef" then    skipn (Drop (n+1) b (p:ps)) xs
+    else if cmd == "elif"  then do v <- gatherDefined p syms (unwords (tail ws))
+                                   skipn (delif v) xs
+    else if cmd == "else"  then    skipn  delse xs
+    else if cmd == "endif" then
+            if null ps then do hPutStrLn stderr $ "Unmatched #endif at "++show p
+                               return []
+                       else skipn  dend  xs
+    else skipn (Drop n b ps) xs
+        -- define, undef, include, error, warning, pragma, line
+
+cpp p syms path options (Keep ps) (x:xs) =
+    let p' = newline p in seq p' $
+    emitOne (p,x)  $  cpp p' syms path options (Keep ps) xs
+cpp p syms path options d@(Drop _ _ _) (_:xs) =
+    let p' = newline p in seq p' $
+    emitOne (p,"") $  cpp p' syms path options d xs
+
+
+-- | Auxiliary IO functions
+emitOne  ::  a  -> IO [a] -> IO [a]
+emitMany :: [a] -> IO [a] -> IO [a]
+emitOne  x  io = do ys <- unsafeInterleaveIO io
+                    return (x:ys)
+emitMany xs io = do ys <- unsafeInterleaveIO io
+                    return (xs++ys)
+
+
+----
+gatherDefined :: Posn -> SymTab HashDefine -> String -> IO Bool
+gatherDefined p st inp =
+  case runParser (preExpand st) inp of
+    (Left msg, _) -> error ("Cannot expand #if directive in file "++show p
+                           ++":\n    "++msg)
+    (Right s, xs) -> do
+--      hPutStrLn stderr $ "Expanded #if at "++show p++" is:\n  "++s
+        when (any (not . isSpace) xs) $
+             hPutStrLn stderr ("Warning: trailing characters after #if"
+                              ++" macro expansion in file "++show p++": "++xs)
+
+        case runParser parseBoolExp s of
+          (Left msg, _) -> error ("Cannot parse #if directive in file "++show p
+                                 ++":\n    "++msg)
+          (Right b, xs) -> do when (any (not . isSpace) xs && notComment xs) $
+                                   hPutStrLn stderr
+                                     ("Warning: trailing characters after #if"
+                                      ++" directive in file "++show p++": "++xs)
+                              return b
+
+notComment = not . ("//"`isPrefixOf`) . dropWhile isSpace
+
+
+-- | The preprocessor must expand all macros (recursively) before evaluating
+--   the conditional.
+preExpand :: SymTab HashDefine -> TextParser String
+preExpand st =
+  do  eof
+      return ""
+  <|>
+  do  a <- many1 (satisfy notIdent)
+      commit $ pure (a++) `apply` preExpand st
+  <|>
+  do  b <- expandSymOrCall st
+      commit $ pure (b++) `apply` preExpand st
+
+-- | Expansion of symbols.
+expandSymOrCall :: SymTab HashDefine -> TextParser String
+expandSymOrCall st =
+  do sym <- parseSym
+     if sym=="defined" then do arg <- skip parseSym; convert sym [arg]
+                            <|>
+                            do arg <- skip $ parenthesis (do x <- skip parseSym;
+                                                             skip (return x))
+                               convert sym [arg]
+                            <|> convert sym []
+      else
+      ( do  args <- parenthesis (commit $ fragment `sepBy` skip (isWord ","))
+            args' <- flip mapM args $ \arg->
+                         case runParser (preExpand st) arg of
+                             (Left msg, _) -> fail msg
+                             (Right s, _)  -> return s
+            convert sym args'
+        <|> convert sym []
+      )
+  where
+    fragment = many1 (satisfy (`notElem`",)"))
+    convert "defined" [arg] =
+      case lookupST arg st of
+        Nothing | all isDigit arg    -> return arg 
+        Nothing                      -> return "0"
+        Just (a@AntiDefined{})       -> return "0"
+        Just (a@SymbolReplacement{}) -> return "1"
+        Just (a@MacroExpansion{})    -> return "1"
+    convert sym args =
+      case lookupST sym st of
+        Nothing  -> if null args then return sym
+                    else return "0"
+                 -- else fail (disp sym args++" is not a defined macro")
+        Just (a@SymbolReplacement{}) -> do reparse (replacement a)
+                                           return ""
+        Just (a@MacroExpansion{})    -> do reparse (expandMacro a args False)
+                                           return ""
+        Just (a@AntiDefined{})       ->
+                    if null args then return sym
+                    else return "0"
+                 -- else fail (disp sym args++" explicitly undefined with -U")
+    disp sym args = let len = length args
+                        chars = map (:[]) ['a'..'z']
+                    in sym ++ if null args then ""
+                              else "("++intercalate "," (take len chars)++")"
+
+parseBoolExp :: TextParser Bool
+parseBoolExp =
+  do  a <- parseExp1
+      bs <- many (do skip (isWord "||")
+                     commit $ skip parseBoolExp)
+      return $ foldr (||) a bs
+
+parseExp1 :: TextParser Bool
+parseExp1 =
+  do  a <- parseExp0
+      bs <- many (do skip (isWord "&&")
+                     commit $ skip parseExp1)
+      return $ foldr (&&) a bs
+
+parseExp0 :: TextParser Bool
+parseExp0 =
+  do  skip (isWord "!")
+      a <- commit $ parseExp0
+      return (not a)
+  <|>
+  do  val1 <- parseArithExp1
+      op   <- parseCmpOp
+      val2 <- parseArithExp1
+      return (val1 `op` val2)
+  <|>
+  do  sym <- parseArithExp1
+      case sym of
+        0 -> return False
+        _ -> return True
+  <|>
+  do  parenthesis (commit parseBoolExp)
+
+parseArithExp1 :: TextParser Integer
+parseArithExp1 =
+  do  val1 <- parseArithExp0
+      ( do op   <- parseArithOp1
+           val2 <- parseArithExp1
+           return (val1 `op` val2)
+        <|> return val1 )
+  <|>
+  do  parenthesis parseArithExp1
+
+parseArithExp0 :: TextParser Integer
+parseArithExp0 =
+  do  val1 <- parseNumber
+      ( do op   <- parseArithOp0
+           val2 <- parseArithExp0
+           return (val1 `op` val2)
+        <|> return val1 )
+  <|>
+  do  parenthesis parseArithExp0
+
+parseNumber :: TextParser Integer
+parseNumber = fmap safeRead $ skip parseSym
+  where
+    safeRead s =
+      case s of
+        '0':'x':s' -> number readHex s'
+        '0':'o':s' -> number readOct s'
+        _          -> number readDec s
+    number rd s =
+      case rd s of
+        []        -> 0 :: Integer
+        ((n,_):_) -> n :: Integer
+
+parseCmpOp :: TextParser (Integer -> Integer -> Bool)
+parseCmpOp =
+  do  skip (isWord ">=")
+      return (>=)
+  <|>
+  do  skip (isWord ">")
+      return (>)
+  <|>
+  do  skip (isWord "<=")
+      return (<=)
+  <|>
+  do  skip (isWord "<")
+      return (<)
+  <|>
+  do  skip (isWord "==")
+      return (==)
+  <|>
+  do  skip (isWord "!=")
+      return (/=)
+
+parseArithOp1 :: TextParser (Integer -> Integer -> Integer)
+parseArithOp1 =
+  do  skip (isWord "+")
+      return (+)
+  <|>
+  do  skip (isWord "-")
+      return (-)
+
+parseArithOp0 :: TextParser (Integer -> Integer -> Integer)
+parseArithOp0 =
+  do  skip (isWord "*")
+      return (*)
+  <|>
+  do  skip (isWord "/")
+      return (div)
+  <|>
+  do  skip (isWord "%")
+      return (rem)
+
+-- | Return the expansion of the symbol (if there is one).
+parseSymOrCall :: SymTab HashDefine -> TextParser String
+parseSymOrCall st =
+  do  sym <- skip parseSym
+      args <- parenthesis (commit $ parseSymOrCall st `sepBy` skip (isWord ","))
+      return $ convert sym args
+  <|>
+  do  sym <- skip parseSym
+      return $ convert sym []
+  where
+    convert sym args =
+      case lookupST sym st of
+        Nothing  -> sym
+        Just (a@SymbolReplacement{}) -> recursivelyExpand st (replacement a)
+        Just (a@MacroExpansion{})    -> recursivelyExpand st (expandMacro a args False)
+        Just (a@AntiDefined{})       -> name a
+
+recursivelyExpand :: SymTab HashDefine -> String -> String
+recursivelyExpand st inp =
+  case runParser (parseSymOrCall st) inp of
+    (Left msg, _) -> inp
+    (Right s,  _) -> s
+
+parseSym :: TextParser String
+parseSym = many1 (satisfy (\c-> isAlphaNum c || c`elem`"'`_"))
+           `onFail`
+           do xs <- allAsString
+              fail $ "Expected an identifier, got \""++xs++"\""
+
+notIdent :: Char -> Bool
+notIdent c = not (isAlphaNum c || c`elem`"'`_")
+
+skip :: TextParser a -> TextParser a
+skip p = many (satisfy isSpace) >> p
+
+-- | The standard "parens" parser does not work for us here.  Define our own.
+parenthesis :: TextParser a -> TextParser a
+parenthesis p = do isWord "("
+                   x <- p
+                   isWord ")"
+                   return x
+
+-- | Determine filename in \#include
+file :: SymTab HashDefine -> String -> String
+file st name =
+    case name of
+      ('"':ns) -> init ns
+      ('<':ns) -> init ns
+      _ -> let ex = recursivelyExpand st name in
+           if ex == name then name else file st ex
+
+ examples/CppHs/Language/Preprocessor/Cpphs/HashDefine.hs view
@@ -0,0 +1,129 @@+-----------------------------------------------------------------------------
+-- |
+-- Module      :  HashDefine
+-- Copyright   :  2004 Malcolm Wallace
+-- Licence     :  LGPL
+--
+-- Maintainer  :  Malcolm Wallace <Malcolm.Wallace@cs.york.ac.uk>
+-- Stability   :  experimental
+-- Portability :  All
+--
+-- What structures are declared in a \#define.
+-----------------------------------------------------------------------------
+ 
+module Language.Preprocessor.Cpphs.HashDefine
+  ( HashDefine(..)
+  , ArgOrText(..)
+  , expandMacro
+  , parseHashDefine
+  , simplifyHashDefines
+  ) where
+
+import Data.Char (isSpace)
+import Data.List (intercalate)
+
+data HashDefine
+        = LineDrop
+                { name :: String }
+        | Pragma
+                { name :: String }
+        | AntiDefined
+                { name          :: String
+                , linebreaks    :: Int
+                }
+        | SymbolReplacement
+                { name          :: String
+                , replacement   :: String
+                , linebreaks    :: Int
+                }
+        | MacroExpansion
+                { name          :: String
+                , arguments     :: [String]
+                , expansion     :: [(ArgOrText,String)]
+                , linebreaks    :: Int
+                }
+    deriving (Eq,Show)
+
+-- | 'smart' constructor to avoid warnings from ghc (undefined fields)
+symbolReplacement :: HashDefine
+symbolReplacement =
+    SymbolReplacement
+         { name=undefined, replacement=undefined, linebreaks=undefined }
+
+-- | Macro expansion text is divided into sections, each of which is classified
+--   as one of three kinds: a formal argument (Arg), plain text (Text),
+--   or a stringised formal argument (Str).
+data ArgOrText = Arg | Text | Str deriving (Eq,Show)
+
+-- | Expand an instance of a macro.
+--   Precondition: got a match on the macro name.
+expandMacro :: HashDefine -> [String] -> Bool -> String
+expandMacro macro parameters layout =
+    let env = zip (arguments macro) parameters
+        replace (Arg,s)  = maybe ("")      id (lookup s env)
+        replace (Str,s)  = maybe (str "") str (lookup s env)
+        replace (Text,s) = if layout then s else filter (/='\n') s
+        str s = '"':s++"\""
+        checkArity | length (arguments macro) == 1 && length parameters <= 1
+                   || length (arguments macro) == length parameters = id
+                   | otherwise = error ("macro "++name macro++" expected "++
+                                        show (length (arguments macro))++
+                                        " arguments, but was given "++
+                                        show (length parameters))
+    in
+    checkArity $ concatMap replace (expansion macro)
+
+-- | Parse a \#define, or \#undef, ignoring other \# directives
+parseHashDefine :: Bool -> [String] -> Maybe HashDefine
+parseHashDefine ansi def = (command . skip) def
+  where
+    skip xss@(x:xs) | all isSpace x = skip xs
+                    | otherwise     = xss
+    skip    []      = []
+    command ("line":xs)   = Just (LineDrop ("#line"++concat xs))
+    command ("pragma":xs) = Just (Pragma ("#pragma"++concat xs))
+    command ("define":xs) = Just (((define . skip) xs) { linebreaks=count def })
+    command ("undef":xs)  = Just (((undef  . skip) xs))
+    command _             = Nothing
+    undef  (sym:_)   = AntiDefined { name=sym, linebreaks=0 }
+    define (sym:xs)  = case {-skip-} xs of
+                           ("(":ys) -> (macroHead sym [] . skip) ys
+                           ys   -> symbolReplacement
+                                     { name=sym
+                                     , replacement = concatMap snd
+                                             (classifyRhs [] (chop (skip ys))) }
+    macroHead sym args (",":xs) = (macroHead sym args . skip) xs
+    macroHead sym args (")":xs) = MacroExpansion
+                                    { name =sym , arguments = reverse args
+                                    , expansion = classifyRhs args (skip xs)
+                                    , linebreaks = undefined }
+    macroHead sym args (var:xs) = (macroHead sym (var:args) . skip) xs
+    macroHead sym args []       = error ("incomplete macro definition:\n"
+                                        ++"  #define "++sym++"("
+                                        ++intercalate "," args)
+    classifyRhs args ("#":x:xs)
+                          | ansi &&
+                            x `elem` args    = (Str,x): classifyRhs args xs
+    classifyRhs args ("##":xs)
+                          | ansi             = classifyRhs args xs
+    classifyRhs args (s:"##":s':xs)
+                          | ansi && all isSpace s && all isSpace s'
+                                             = classifyRhs args xs
+    classifyRhs args (word:xs)
+                          | word `elem` args = (Arg,word): classifyRhs args xs
+                          | otherwise        = (Text,word): classifyRhs args xs
+    classifyRhs _    []                      = []
+    count = length . filter (=='\n') . concat
+    chop  = reverse . dropWhile (all isSpace) . reverse
+
+-- | Pretty-print hash defines to a simpler format, as key-value pairs.
+simplifyHashDefines :: [HashDefine] -> [(String,String)]
+simplifyHashDefines = concatMap simp
+  where
+    simp hd@LineDrop{}    = []
+    simp hd@Pragma{}      = []
+    simp hd@AntiDefined{} = []
+    simp hd@SymbolReplacement{} = [(name hd, replacement hd)]
+    simp hd@MacroExpansion{}    = [(name hd++"("++intercalate "," (arguments hd)
+                                           ++")"
+                                   ,concatMap snd (expansion hd))]
+ examples/CppHs/Language/Preprocessor/Cpphs/MacroPass.hs view
@@ -0,0 +1,184 @@+-----------------------------------------------------------------------------
+-- |
+-- Module      :  MacroPass
+-- Copyright   :  2004 Malcolm Wallace
+-- Licence     :  LGPL
+--
+-- Maintainer  :  Malcolm Wallace <Malcolm.Wallace@cs.york.ac.uk>
+-- Stability   :  experimental
+-- Portability :  All
+--
+-- Perform a cpp.second-pass, accumulating \#define's and \#undef's,
+-- whilst doing symbol replacement and macro expansion.
+-----------------------------------------------------------------------------
+
+module Language.Preprocessor.Cpphs.MacroPass
+  ( macroPass
+  , preDefine
+  , defineMacro
+  , macroPassReturningSymTab
+  ) where
+
+import Language.Preprocessor.Cpphs.HashDefine (HashDefine(..), expandMacro
+                                              , simplifyHashDefines)
+import Language.Preprocessor.Cpphs.Tokenise   (tokenise, WordStyle(..)
+                                              , parseMacroCall)
+import Language.Preprocessor.Cpphs.SymTab     (SymTab, lookupST, insertST
+                                              , emptyST, flattenST)
+import Language.Preprocessor.Cpphs.Position   (Posn, newfile, filename, lineno)
+import Language.Preprocessor.Cpphs.Options    (BoolOptions(..))
+import System.IO.Unsafe (unsafeInterleaveIO)
+import Control.Monad    ((=<<))
+import System.Time       (getClockTime, toCalendarTime, formatCalendarTime)
+import System.Locale     (defaultTimeLocale)
+
+noPos :: Posn
+noPos = newfile "preDefined"
+
+-- | Walk through the document, replacing calls of macros with the expanded RHS.
+macroPass :: [(String,String)]  -- ^ Pre-defined symbols and their values
+          -> BoolOptions        -- ^ Options that alter processing style
+          -> [(Posn,String)]    -- ^ The input file content
+          -> IO String          -- ^ The file after processing
+macroPass syms options =
+    fmap (safetail              -- to remove extra "\n" inserted below
+         . concat
+         . onlyRights)
+    . macroProcess (pragma options) (layout options) (lang options)
+                   (preDefine options syms)
+    . tokenise (stripEol options) (stripC89 options)
+               (ansi options) (lang options)
+    . ((noPos,""):)     -- ensure recognition of "\n#" at start of file
+  where
+    safetail [] = []
+    safetail (_:xs) = xs
+
+-- | auxiliary
+onlyRights :: [Either a b] -> [b]
+onlyRights = concatMap (\x->case x of Right t-> [t]; Left _-> [];)
+
+-- | Walk through the document, replacing calls of macros with the expanded RHS.
+--   Additionally returns the active symbol table after processing.
+macroPassReturningSymTab
+          :: [(String,String)]  -- ^ Pre-defined symbols and their values
+          -> BoolOptions        -- ^ Options that alter processing style
+          -> [(Posn,String)]    -- ^ The input file content
+          -> IO (String,[(String,String)])
+                                -- ^ The file and symbol table after processing
+macroPassReturningSymTab syms options =
+    fmap (mapFst (safetail              -- to remove extra "\n" inserted below
+                 . concat)
+         . walk)
+    . macroProcess (pragma options) (layout options) (lang options)
+                   (preDefine options syms)
+    . tokenise (stripEol options) (stripC89 options)
+               (ansi options) (lang options)
+    . ((noPos,""):)     -- ensure recognition of "\n#" at start of file
+  where
+    safetail [] = []
+    safetail (_:xs) = xs
+    walk (Right x: rest) = let (xs,   foo) = walk rest
+                           in  (x:xs, foo)
+    walk (Left  x: [])   =     ( [] , simplifyHashDefines (flattenST x) )
+    walk (Left  x: rest) = walk rest
+    mapFst f (a,b) = (f a, b)
+
+
+-- | Turn command-line definitions (from @-D@) into 'HashDefine's.
+preDefine :: BoolOptions -> [(String,String)] -> SymTab HashDefine
+preDefine options defines =
+    foldr (insertST . defineMacro options . (\ (s,d)-> s++" "++d))
+          emptyST defines
+
+-- | Turn a string representing a macro definition into a 'HashDefine'.
+defineMacro :: BoolOptions -> String -> (String,HashDefine)
+defineMacro opts s =
+    let (Cmd (Just hd):_) = tokenise True True (ansi opts) (lang opts)
+                                     [(noPos,"\n#define "++s++"\n")]
+    in (name hd, hd)
+
+
+-- | Trundle through the document, one word at a time, using the WordStyle
+--   classification introduced by 'tokenise' to decide whether to expand a
+--   word or macro.  Encountering a \#define or \#undef causes that symbol to
+--   be overwritten in the symbol table.  Any other remaining cpp directives
+--   are discarded and replaced with blanks, except for \#line markers.
+--   All valid identifiers are checked for the presence of a definition
+--   of that name in the symbol table, and if so, expanded appropriately.
+--   (Bool arguments are: keep pragmas?  retain layout?  haskell language?)
+--   The result lazily intersperses output text with symbol tables.  Lines
+--   are emitted as they are encountered.  A symbol table is emitted after
+--   each change to the defined symbols, and always at the end of processing.
+macroProcess :: Bool -> Bool -> Bool -> SymTab HashDefine -> [WordStyle]
+             -> IO [Either (SymTab HashDefine) String]
+macroProcess _ _ _ st        []          = return [Left st]
+macroProcess p y l st (Other x: ws)      = emit x    $ macroProcess p y l st ws
+macroProcess p y l st (Cmd Nothing: ws)  = emit "\n" $ macroProcess p y l st ws
+macroProcess p y l st (Cmd (Just (LineDrop x)): ws)
+                                         = emit "\n" $
+                                           emit x    $ macroProcess p y l st ws
+macroProcess pragma y l st (Cmd (Just (Pragma x)): ws)
+               | pragma    = emit "\n" $ emit x $ macroProcess pragma y l st ws
+               | otherwise = emit "\n" $          macroProcess pragma y l st ws
+macroProcess p layout lang st (Cmd (Just hd): ws) =
+    let n = 1 + linebreaks hd
+        newST = insertST (name hd, hd) st
+    in
+    emit (replicate n '\n') $
+    emitSymTab newST $
+    macroProcess p layout lang newST ws
+macroProcess pr layout lang st (Ident p x: ws) =
+    case x of
+      "__FILE__" -> emit (show (filename p))$ macroProcess pr layout lang st ws
+      "__LINE__" -> emit (show (lineno p))  $ macroProcess pr layout lang st ws
+      "__DATE__" -> do w <- return .
+                            formatCalendarTime defaultTimeLocale "\"%d %b %Y\""
+                            =<< toCalendarTime =<< getClockTime
+                       emit w $ macroProcess pr layout lang st ws
+      "__TIME__" -> do w <- return .
+                            formatCalendarTime defaultTimeLocale "\"%H:%M:%S\""
+                            =<< toCalendarTime =<< getClockTime
+                       emit w $ macroProcess pr layout lang st ws
+      _ ->
+        case lookupST x st of
+            Nothing -> emit x $ macroProcess pr layout lang st ws
+            Just hd ->
+                case hd of
+                    AntiDefined {name=n} -> emit n $
+                                            macroProcess pr layout lang st ws
+                    SymbolReplacement {replacement=r} ->
+                        let r' = if layout then r else filter (/='\n') r in
+                        -- one-level expansion only:
+                        -- emit r' $ macroProcess layout st ws
+                        -- multi-level expansion:
+                        macroProcess pr layout lang st
+                                     (tokenise True True False lang [(p,r')]
+                                      ++ ws)
+                    MacroExpansion {} ->
+                        case parseMacroCall p ws of
+                            Nothing -> emit x $
+                                       macroProcess pr layout lang st ws
+                            Just (args,ws') ->
+                                if length args /= length (arguments hd) then
+                                     emit x $ macroProcess pr layout lang st ws
+                                else do args' <- mapM (fmap (concat.onlyRights)
+                                                       . macroProcess pr layout
+                                                                        lang st)
+                                                      args
+                                        -- one-level expansion only:
+                                        -- emit (expandMacro hd args' layout) $
+                                        --         macroProcess layout st ws'
+                                        -- multi-level expansion:
+                                        macroProcess pr layout lang st
+                                            (tokenise True True False lang
+                                               [(p,expandMacro hd args' layout)]
+                                            ++ ws')
+
+-- | Useful helper function.
+emit :: a -> IO [Either b a] -> IO [Either b a]
+emit x io = do xs <- unsafeInterleaveIO io
+               return (Right x:xs)
+-- | Useful helper function.
+emitSymTab :: b -> IO [Either b a] -> IO [Either b a]
+emitSymTab x io = do xs <- unsafeInterleaveIO io
+                     return (Left x:xs)
+ examples/CppHs/Language/Preprocessor/Cpphs/Options.hs view
@@ -0,0 +1,156 @@+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Options
+-- Copyright   :  2006 Malcolm Wallace
+-- Licence     :  LGPL
+--
+-- Maintainer  :  Malcolm Wallace <Malcolm.Wallace@cs.york.ac.uk>
+-- Stability   :  experimental
+-- Portability :  All
+--
+-- This module deals with Cpphs options and parsing them
+-----------------------------------------------------------------------------
+
+module Language.Preprocessor.Cpphs.Options
+  ( CpphsOptions(..)
+  , BoolOptions(..)
+  , parseOptions
+  , defaultCpphsOptions
+  , defaultBoolOptions
+  , trailing
+  ) where
+
+import Data.Maybe
+import Data.List (isPrefixOf)
+
+-- | Cpphs options structure.
+data CpphsOptions = CpphsOptions 
+    { infiles   :: [FilePath]
+    , outfiles  :: [FilePath]
+    , defines   :: [(String,String)]
+    , includes  :: [String]
+    , preInclude:: [FilePath]   -- ^ Files to \#include before anything else
+    , boolopts  :: BoolOptions
+    } deriving (Show)
+
+-- | Default options.
+defaultCpphsOptions :: CpphsOptions
+defaultCpphsOptions = CpphsOptions { infiles = [], outfiles = []
+                                   , defines = [], includes = []
+                                   , preInclude = []
+                                   , boolopts = defaultBoolOptions }
+
+-- | Options representable as Booleans.
+data BoolOptions = BoolOptions
+    { macros    :: Bool  -- ^ Leave \#define and \#undef in output of ifdef?
+    , locations :: Bool  -- ^ Place \#line droppings in output?
+    , hashline  :: Bool  -- ^ Write \#line or {-\# LINE \#-} ?
+    , pragma    :: Bool  -- ^ Keep \#pragma in final output?
+    , stripEol  :: Bool  -- ^ Remove C eol (\/\/) comments everywhere?
+    , stripC89  :: Bool  -- ^ Remove C inline (\/**\/) comments everywhere?
+    , lang      :: Bool  -- ^ Lex input as Haskell code?
+    , ansi      :: Bool  -- ^ Permit stringise \# and catenate \#\# operators?
+    , layout    :: Bool  -- ^ Retain newlines in macro expansions?
+    , literate  :: Bool  -- ^ Remove literate markup?
+    , warnings  :: Bool  -- ^ Issue warnings?
+    } deriving (Show)
+
+-- | Default settings of boolean options.
+defaultBoolOptions :: BoolOptions
+defaultBoolOptions = BoolOptions { macros   = True,   locations = True
+                                 , hashline = True,   pragma    = False
+                                 , stripEol = False,  stripC89  = False
+                                 , lang     = True,   ansi      = False
+                                 , layout   = False,  literate  = False
+                                 , warnings = True }
+
+-- | Raw command-line options.  This is an internal intermediate data
+--   structure, used during option parsing only.
+data RawOption
+    = NoMacro
+    | NoLine
+    | LinePragma
+    | Pragma
+    | Text
+    | Strip
+    | StripEol
+    | Ansi
+    | Layout
+    | Unlit
+    | SuppressWarnings
+    | Macro (String,String)
+    | Path String
+    | PreInclude FilePath
+    | IgnoredForCompatibility
+      deriving (Eq, Show)
+
+flags :: [(String, RawOption)]
+flags = [ ("--nomacro", NoMacro)
+        , ("--noline",  NoLine)
+        , ("--linepragma", LinePragma)
+        , ("--pragma",  Pragma)
+        , ("--text",    Text)
+        , ("--strip",   Strip)
+        , ("--strip-eol",  StripEol)
+        , ("--hashes",  Ansi)
+        , ("--layout",  Layout)
+        , ("--unlit",   Unlit)
+        , ("--nowarn",  SuppressWarnings)
+        ]
+
+-- | Parse a single raw command-line option.  Parse failure is indicated by
+--   result Nothing.
+rawOption :: String -> Maybe RawOption
+rawOption x | isJust a = a
+    where a = lookup x flags
+rawOption ('-':'D':xs) = Just $ Macro (s, if null d then "1" else tail d)
+    where (s,d) = break (=='=') xs
+rawOption ('-':'U':xs) = Just $ IgnoredForCompatibility
+rawOption ('-':'I':xs) = Just $ Path $ trailing "/\\" xs
+rawOption xs | "--include="`isPrefixOf`xs
+            = Just $ PreInclude (drop 10 xs)
+rawOption _ = Nothing
+
+-- | Trim trailing elements of the second list that match any from
+--   the first list.  Typically used to remove trailing forward\/back
+--   slashes from a directory path.
+trailing :: (Eq a) => [a] -> [a] -> [a]
+trailing xs = reverse . dropWhile (`elem`xs) . reverse
+
+-- | Convert a list of RawOption to a BoolOptions structure.
+boolOpts :: [RawOption] -> BoolOptions
+boolOpts opts =
+  BoolOptions
+    { macros    = not (NoMacro `elem` opts)
+    , locations = not (NoLine  `elem` opts)
+    , hashline  = not (LinePragma `elem` opts)
+    , pragma    =      Pragma  `elem` opts
+    , stripEol  =      StripEol`elem` opts
+    , stripC89  =      StripEol`elem` opts || Strip `elem` opts
+    , lang      = not (Text    `elem` opts)
+    , ansi      =      Ansi    `elem` opts
+    , layout    =      Layout  `elem` opts
+    , literate  =      Unlit   `elem` opts
+    , warnings  = not (SuppressWarnings `elem` opts)
+    }
+
+-- | Parse all command-line options.
+parseOptions :: [String] -> Either String CpphsOptions
+parseOptions xs = f ([], [], []) xs
+  where
+    f (opts, ins, outs) (('-':'O':x):xs) = f (opts, ins, x:outs) xs
+    f (opts, ins, outs) (x@('-':_):xs) = case rawOption x of
+                                           Nothing -> Left x
+                                           Just a  -> f (a:opts, ins, outs) xs
+    f (opts, ins, outs) (x:xs) = f (opts, normalise x:ins, outs) xs
+    f (opts, ins, outs) []     =
+        Right CpphsOptions { infiles  = reverse ins
+                           , outfiles = reverse outs
+                           , defines  = [ x | Macro x <- reverse opts ]
+                           , includes = [ x | Path x  <- reverse opts ]
+                           , preInclude=[ x | PreInclude x <- reverse opts ]
+                           , boolopts = boolOpts opts
+                           }
+    normalise ('/':'/':filepath) = normalise ('/':filepath)
+    normalise (x:filepath)       = x:normalise filepath
+    normalise []                 = []
+ examples/CppHs/Language/Preprocessor/Cpphs/Position.hs view
@@ -0,0 +1,106 @@+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Position
+-- Copyright   :  2000-2004 Malcolm Wallace
+-- Licence     :  LGPL
+--
+-- Maintainer  :  Malcolm Wallace <Malcolm.Wallace@cs.york.ac.uk>
+-- Stability   :  experimental
+-- Portability :  All
+--
+-- Simple file position information, with recursive inclusion points.
+-----------------------------------------------------------------------------
+
+module Language.Preprocessor.Cpphs.Position
+  ( Posn(..)
+  , newfile
+  , addcol, newline, tab, newlines, newpos
+  , cppline, haskline, cpp2hask
+  , filename, lineno, directory
+  , cleanPath
+  ) where
+
+import Data.List (isPrefixOf)
+
+-- | Source positions contain a filename, line, column, and an
+--   inclusion point, which is itself another source position,
+--   recursively.
+data Posn = Pn String !Int !Int (Maybe Posn)
+        deriving (Eq)
+
+instance Show Posn where
+      showsPrec _ (Pn f l c i) = showString f .
+                                 showString "  at line " . shows l .
+                                 showString " col " . shows c .
+                                 ( case i of
+                                    Nothing -> id
+                                    Just p  -> showString "\n    used by  " .
+                                               shows p )
+
+-- | Constructor.  Argument is filename.
+newfile :: String -> Posn
+newfile name = Pn (cleanPath name) 1 1 Nothing
+
+-- | Increment column number by given quantity.
+addcol :: Int -> Posn -> Posn
+addcol n (Pn f r c i) = Pn f r (c+n) i
+
+-- | Increment row number, reset column to 1.
+newline :: Posn -> Posn
+--newline (Pn f r _ i) = Pn f (r+1) 1 i
+newline (Pn f r _ i) = let r' = r+1 in r' `seq` Pn f r' 1 i
+
+-- | Increment column number, tab stops are every 8 chars.
+tab     :: Posn -> Posn
+tab     (Pn f r c i) = Pn f r (((c`div`8)+1)*8) i
+
+-- | Increment row number by given quantity.
+newlines :: Int -> Posn -> Posn
+newlines n (Pn f r _ i) = Pn f (r+n) 1 i
+
+-- | Update position with a new row, and possible filename.
+newpos :: Int -> Maybe String -> Posn -> Posn
+newpos r Nothing  (Pn f _ c i) = Pn f r c i
+newpos r (Just ('"':f)) (Pn _ _ c i) = Pn (init f) r c i
+newpos r (Just f)       (Pn _ _ c i) = Pn f r c i
+
+-- | Project the line number.
+lineno    :: Posn -> Int
+-- | Project the filename.
+filename  :: Posn -> String
+-- | Project the directory of the filename.
+directory :: Posn -> FilePath
+
+lineno    (Pn _ r _ _) = r
+filename  (Pn f _ _ _) = f
+directory (Pn f _ _ _) = dirname f
+
+
+-- | cpp-style printing of file position
+cppline :: Posn -> String
+cppline (Pn f r _ _) = "#line "++show r++" "++show f
+
+-- | haskell-style printing of file position
+haskline :: Posn -> String
+haskline (Pn f r _ _) = "{-# LINE "++show r++" "++show f++" #-}"
+
+-- | Conversion from a cpp-style "#line" to haskell-style pragma.
+cpp2hask :: String -> String
+cpp2hask line | "#line" `isPrefixOf` line = "{-# LINE "
+                                            ++unwords (tail (words line))
+                                            ++" #-}"
+              | otherwise = line
+
+-- | Strip non-directory suffix from file name (analogous to the shell
+--   command of the same name).
+dirname :: String -> String
+dirname  = reverse . safetail . dropWhile (not.(`elem`"\\/")) . reverse
+  where safetail [] = []
+        safetail (_:x) = x
+
+-- | Sigh.  Mixing Windows filepaths with unix is bad.  Make sure there is a
+--   canonical path separator.
+cleanPath :: FilePath -> FilePath
+cleanPath [] = []
+cleanPath ('\\':cs) = '/': cleanPath cs
+cleanPath (c:cs)    = c:   cleanPath cs
+ examples/CppHs/Language/Preprocessor/Cpphs/ReadFirst.hs view
@@ -0,0 +1,55 @@+-----------------------------------------------------------------------------
+-- |
+-- Module      :  ReadFirst
+-- Copyright   :  2004 Malcolm Wallace
+-- Licence     :  LGPL
+-- 
+-- Maintainer  :  Malcolm Wallace <Malcolm.Wallace@cs.york.ac.uk>
+-- Stability   :  experimental
+-- Portability :  All
+--
+-- Read the first file that matches in a list of search paths.
+-----------------------------------------------------------------------------
+
+module Language.Preprocessor.Cpphs.ReadFirst
+  ( readFirst
+  ) where
+
+import System.IO        (hPutStrLn, stderr)
+import System.Directory (doesFileExist)
+import Data.List      (intersperse)
+import Control.Monad     (when)
+import Language.Preprocessor.Cpphs.Position  (Posn,directory,cleanPath)
+
+-- | Attempt to read the given file from any location within the search path.
+--   The first location found is returned, together with the file content.
+--   (The directory of the calling file is always searched first, then
+--    the current directory, finally any specified search path.)
+readFirst :: String             -- ^ filename
+        -> Posn                 -- ^ inclusion point
+        -> [String]             -- ^ search path
+        -> Bool                 -- ^ report warnings?
+        -> IO ( FilePath
+              , String
+              )                 -- ^ discovered filepath, and file contents
+
+readFirst name demand path warn =
+    case name of
+       '/':nm -> try nm   [""]
+       _      -> try name (cons dd (".":path))
+  where
+    dd = directory demand
+    cons x xs = if null x then xs else x:xs
+    try name [] = do
+        when warn $
+          hPutStrLn stderr ("Warning: Can't find file \""++name
+                           ++"\" in directories\n\t"
+                           ++concat (intersperse "\n\t" (cons dd (".":path)))
+                           ++"\n  Asked for by: "++show demand)
+        return ("missing file: "++name,"")
+    try name (p:ps) = do
+        let file = cleanPath p++'/':cleanPath name
+        ok <- doesFileExist file
+        if not ok then try name ps
+          else do content <- readFile file
+                  return (file,content)
+ examples/CppHs/Language/Preprocessor/Cpphs/RunCpphs.hs view
@@ -0,0 +1,82 @@+{-
+-- The main program for cpphs, a simple C pre-processor written in Haskell.
+
+-- Copyright (c) 2004 Malcolm Wallace
+-- This file is LGPL (relicensed from the GPL by Malcolm Wallace, October 2011).
+-}
+module Language.Preprocessor.Cpphs.RunCpphs ( runCpphs
+                                            , runCpphsPass1
+                                            , runCpphsPass2
+                                            , runCpphsReturningSymTab
+                                            ) where
+
+import Language.Preprocessor.Cpphs.CppIfdef (cppIfdef)
+import Language.Preprocessor.Cpphs.MacroPass(macroPass,macroPassReturningSymTab)
+import Language.Preprocessor.Cpphs.Options  (CpphsOptions(..), BoolOptions(..)
+                                            ,trailing)
+import Language.Preprocessor.Cpphs.Tokenise (deWordStyle, tokenise)
+import Language.Preprocessor.Cpphs.Position (cleanPath, Posn)
+import Language.Preprocessor.Unlit as Unlit (unlit)
+
+
+runCpphs :: CpphsOptions -> FilePath -> String -> IO String
+runCpphs options filename input = do
+  pass1 <- runCpphsPass1 options filename input
+  runCpphsPass2 (boolopts options) (defines options) filename pass1
+
+runCpphsPass1 :: CpphsOptions -> FilePath -> String -> IO [(Posn,String)]
+runCpphsPass1 options' filename input = do
+  let options= options'{ includes= map (trailing "\\/") (includes options') }
+  let bools  = boolopts options
+      preInc = case preInclude options of
+                 [] -> ""
+                 is -> concatMap (\f->"#include \""++f++"\"\n") is 
+                       ++ "#line 1 \""++cleanPath filename++"\"\n"
+
+  pass1 <- cppIfdef filename (defines options) (includes options) bools
+                    (preInc++input)
+  return pass1
+
+runCpphsPass2 :: BoolOptions -> [(String,String)] -> FilePath -> [(Posn,String)] -> IO String
+runCpphsPass2 bools defines filename pass1 = do
+  pass2 <- macroPass defines bools pass1
+  let result= if not (macros bools)
+              then if   stripC89 bools || stripEol bools
+                   then concatMap deWordStyle $
+                        tokenise (stripEol bools) (stripC89 bools)
+                                 (ansi bools) (lang bools) pass1
+                   else unlines (map snd pass1)
+              else pass2
+      pass3 = if literate bools then Unlit.unlit filename else id
+  return (pass3 result)
+
+runCpphsReturningSymTab :: CpphsOptions -> FilePath -> String
+             -> IO (String,[(String,String)])
+runCpphsReturningSymTab options' filename input = do
+  let options= options'{ includes= map (trailing "\\/") (includes options') }
+  let bools  = boolopts options
+      preInc = case preInclude options of
+                 [] -> ""
+                 is -> concatMap (\f->"#include \""++f++"\"\n") is 
+                       ++ "#line 1 \""++cleanPath filename++"\"\n"
+  (pass2,syms) <-
+      if macros bools then do
+          pass1 <- cppIfdef filename (defines options) (includes options)
+                            bools (preInc++input)
+          macroPassReturningSymTab (defines options) bools pass1
+      else do
+          pass1 <- cppIfdef filename (defines options) (includes options)
+                            bools{macros=True} (preInc++input)
+          (_,syms) <- macroPassReturningSymTab (defines options) bools pass1
+          pass1 <- cppIfdef filename (defines options) (includes options)
+                            bools (preInc++input)
+          let result = if   stripC89 bools || stripEol bools
+                       then concatMap deWordStyle $
+                            tokenise (stripEol bools) (stripC89 bools)
+                                     (ansi bools) (lang bools) pass1
+                       else init $ unlines (map snd pass1)
+          return (result,syms)
+
+  let pass3 = if literate bools then Unlit.unlit filename else id
+  return (pass3 pass2, syms)
+
+ examples/CppHs/Language/Preprocessor/Cpphs/SymTab.hs view
@@ -0,0 +1,92 @@+-----------------------------------------------------------------------------
+-- |
+-- Module      :  SymTab
+-- Copyright   :  2000-2004 Malcolm Wallace
+-- Licence     :  LGPL
+-- 
+-- Maintainer  :  Malcolm Wallace <Malcolm.Wallace@cs.york.ac.uk>
+-- Stability   :  Stable
+-- Portability :  All
+--
+-- Symbol Table, based on index trees using a hash on the key.
+--   Keys are always Strings.  Stored values can be any type.
+-----------------------------------------------------------------------------
+
+module Language.Preprocessor.Cpphs.SymTab
+  ( SymTab
+  , emptyST
+  , insertST
+  , deleteST
+  , lookupST
+  , definedST
+  , flattenST
+  , IndTree
+  ) where
+
+-- | Symbol Table.  Stored values are polymorphic, but the keys are
+--   always strings.
+type SymTab v = IndTree [(String,v)]
+
+emptyST   :: SymTab v
+insertST  :: (String,v) -> SymTab v -> SymTab v
+deleteST  :: String -> SymTab v -> SymTab v
+lookupST  :: String -> SymTab v -> Maybe v
+definedST :: String -> SymTab v -> Bool
+flattenST :: SymTab v -> [v]
+
+emptyST           = itgen maxHash []
+insertST (s,v) ss = itiap (hash s) ((s,v):)    ss id
+deleteST  s    ss = itiap (hash s) (filter ((/=s).fst)) ss id
+lookupST  s    ss = let vs = filter ((==s).fst) ((itind (hash s)) ss)
+                    in if null vs then Nothing
+                       else (Just . snd . head) vs
+definedST s    ss = let vs = filter ((==s).fst) ((itind (hash s)) ss)
+                    in (not . null) vs
+flattenST      ss = itfold (map snd) (++) ss
+
+
+----
+-- | Index Trees (storing indexes at nodes).
+
+data IndTree t = Leaf t | Fork Int (IndTree t) (IndTree t)
+     deriving Show
+
+itgen :: Int -> a -> IndTree a
+itgen 1 x = Leaf x
+itgen n x =
+  let n' = n `div` 2
+  in Fork n' (itgen n' x) (itgen (n-n') x)
+
+itiap :: --Eval a =>
+         Int -> (a->a) -> IndTree a -> (IndTree a -> b) -> b
+itiap _ f (Leaf x)       k = let fx = f x in {-seq fx-} (k (Leaf fx))
+itiap i f (Fork n lt rt) k =
+  if i<n then
+       itiap i f lt $ \lt' -> k (Fork n lt' rt)
+  else itiap (i-n) f rt $ \rt' -> k (Fork n lt rt')
+
+itind :: Int -> IndTree a -> a
+itind _ (Leaf x) = x
+itind i (Fork n lt rt) = if i<n then itind i lt else itind (i-n) rt
+
+itfold :: (a->b) -> (b->b->b) -> IndTree a -> b
+itfold leaf _fork (Leaf x) = leaf x
+itfold leaf  fork (Fork _ l r) = fork (itfold leaf fork l) (itfold leaf fork r)
+
+----
+-- Hash values
+
+maxHash :: Int -- should be prime
+maxHash = 101
+
+class Hashable a where
+    hashWithMax :: Int -> a -> Int
+    hash        :: a -> Int
+    hash = hashWithMax maxHash
+
+instance Enum a => Hashable [a] where
+    hashWithMax m = h 0
+        where h a []     = a
+              h a (c:cs) = h ((17*(fromEnum c)+19*a)`rem`m) cs
+
+----
+ examples/CppHs/Language/Preprocessor/Cpphs/Tokenise.hs view
@@ -0,0 +1,281 @@+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Tokenise
+-- Copyright   :  2004 Malcolm Wallace
+-- Licence     :  LGPL
+--
+-- Maintainer  :  Malcolm Wallace <Malcolm.Wallace@cs.york.ac.uk>
+-- Stability   :  experimental
+-- Portability :  All
+--
+-- The purpose of this module is to lex a source file (language
+-- unspecified) into tokens such that cpp can recognise a replaceable
+-- symbol or macro-use, and do the right thing.
+-----------------------------------------------------------------------------
+
+module Language.Preprocessor.Cpphs.Tokenise
+  ( linesCpp
+  , reslash
+  , tokenise
+  , WordStyle(..)
+  , deWordStyle
+  , parseMacroCall
+  ) where
+
+import Data.Char
+import Language.Preprocessor.Cpphs.HashDefine
+import Language.Preprocessor.Cpphs.Position
+
+-- | A Mode value describes whether to tokenise a la Haskell, or a la Cpp.
+--   The main difference is that in Cpp mode we should recognise line
+--   continuation characters.
+data Mode = Haskell | Cpp
+
+-- | linesCpp is, broadly speaking, Prelude.lines, except that
+--   on a line beginning with a \#, line continuation characters are
+--   recognised.  In a line continuation, the newline character is
+--   preserved, but the backslash is not.
+linesCpp :: String -> [String]
+linesCpp  []                 = []
+linesCpp (x:xs) | x=='#'     = tok Cpp     ['#'] xs
+                | otherwise  = tok Haskell [] (x:xs)
+  where
+    tok Cpp   acc ('\\':'\n':ys)   = tok Cpp ('\n':acc) ys
+    tok _     acc ('\n':'#':ys)    = reverse acc: tok Cpp ['#'] ys
+    tok _     acc ('\n':ys)        = reverse acc: tok Haskell [] ys
+    tok _     acc []               = reverse acc: []
+    tok mode  acc (y:ys)           = tok mode (y:acc) ys
+
+-- | Put back the line-continuation characters.
+reslash :: String -> String
+reslash ('\n':xs) = '\\':'\n':reslash xs
+reslash (x:xs)    = x: reslash xs
+reslash   []      = []
+
+----
+-- | Submodes are required to deal correctly with nesting of lexical
+--   structures.
+data SubMode = Any | Pred (Char->Bool) (Posn->String->WordStyle)
+             | String Char | LineComment | NestComment Int
+             | CComment | CLineComment
+
+-- | Each token is classified as one of Ident, Other, or Cmd:
+--   * Ident is a word that could potentially match a macro name.
+--   * Cmd is a complete cpp directive (\#define etc).
+--   * Other is anything else.
+data WordStyle = Ident Posn String | Other String | Cmd (Maybe HashDefine)
+  deriving (Eq,Show)
+other :: Posn -> String -> WordStyle
+other _ s = Other s
+
+deWordStyle :: WordStyle -> String
+deWordStyle (Ident _ i) = i
+deWordStyle (Other i)   = i
+deWordStyle (Cmd _)     = "\n"
+
+-- | tokenise is, broadly-speaking, Prelude.words, except that:
+--    * the input is already divided into lines
+--    * each word-like "token" is categorised as one of {Ident,Other,Cmd}
+--    * \#define's are parsed and returned out-of-band using the Cmd variant
+--    * All whitespace is preserved intact as tokens.
+--    * C-comments are converted to white-space (depending on first param)
+--    * Parens and commas are tokens in their own right.
+--    * Any cpp line continuations are respected.
+--   No errors can be raised.
+--   The inverse of tokenise is (concatMap deWordStyle).
+tokenise :: Bool -> Bool -> Bool -> Bool -> [(Posn,String)] -> [WordStyle]
+tokenise _        _             _    _     [] = []
+tokenise stripEol stripComments ansi lang ((pos,str):pos_strs) =
+    (if lang then haskell else plaintext) Any [] pos pos_strs str
+ where
+    -- rules to lex Haskell
+  haskell :: SubMode -> String -> Posn -> [(Posn,String)]
+             -> String -> [WordStyle]
+  haskell Any acc p ls ('\n':'#':xs)      = emit acc $  -- emit "\n" $
+                                            cpp Any haskell [] [] p ls xs
+    -- warning: non-maximal munch on comment
+  haskell Any acc p ls ('-':'-':xs)       = emit acc $
+                                            haskell LineComment "--" p ls xs
+  haskell Any acc p ls ('{':'-':xs)       = emit acc $
+                                            haskell (NestComment 0) "-{" p ls xs
+  haskell Any acc p ls ('/':'*':xs)
+                          | stripComments = emit acc $
+                                            haskell CComment "  " p ls xs
+  haskell Any acc p ls ('/':'/':xs)
+                          | stripEol      = emit acc $
+                                            haskell CLineComment "  " p ls xs
+  haskell Any acc p ls ('"':xs)           = emit acc $
+                                            haskell (String '"') ['"'] p ls xs
+  haskell Any acc p ls ('\'':'\'':xs)     = emit acc $ -- TH type quote
+                                            haskell Any "''" p ls xs
+  haskell Any acc p ls ('\'':xs@('\\':_)) = emit acc $ -- escaped char literal
+                                            haskell (String '\'') "'" p ls xs
+  haskell Any acc p ls ('\'':x:'\'':xs)   = emit acc $ -- character literal
+                                            emit ['\'', x, '\''] $
+                                            haskell Any [] p ls xs
+  haskell Any acc p ls ('\'':xs)          = emit acc $ -- TH name quote
+                                            haskell Any "'" p ls xs
+  haskell Any acc p ls (x:xs) | single x  = emit acc $ emit [x] $
+                                            haskell Any [] p ls xs
+  haskell Any acc p ls (x:xs) | space x   = emit acc $
+                                            haskell (Pred space other) [x]
+                                                                        p ls xs
+  haskell Any acc p ls (x:xs) | symbol x  = emit acc $
+                                            haskell (Pred symbol other) [x]
+                                                                        p ls xs
+ -- haskell Any [] p ls (x:xs) | ident0 x  = id $
+  haskell Any acc p ls (x:xs) | ident0 x  = emit acc $
+                                            haskell (Pred ident1 Ident) [x]
+                                                                        p ls xs
+  haskell Any acc p ls (x:xs)             = haskell Any (x:acc) p ls xs
+
+  haskell pre@(Pred pred ws) acc p ls (x:xs)
+                        | pred x    = haskell pre (x:acc) p ls xs
+  haskell (Pred _ ws) acc p ls xs   = ws p (reverse acc):
+                                      haskell Any [] p ls xs
+  haskell (String c) acc p ls ('\\':x:xs)
+                        | x=='\\'   = haskell (String c) ('\\':'\\':acc) p ls xs
+                        | x==c      = haskell (String c) (c:'\\':acc) p ls xs
+  haskell (String c) acc p ls (x:xs)
+                        | x==c      = emit (c:acc) $ haskell Any [] p ls xs
+                        | otherwise = haskell (String c) (x:acc) p ls xs
+  haskell LineComment acc p ls xs@('\n':_) = emit acc $ haskell Any [] p ls xs
+  haskell LineComment acc p ls (x:xs)      = haskell LineComment (x:acc) p ls xs
+  haskell (NestComment n) acc p ls ('{':'-':xs)
+                                    = haskell (NestComment (n+1))
+                                                            ("-{"++acc) p ls xs
+  haskell (NestComment 0) acc p ls ('-':'}':xs)
+                                    = emit ("}-"++acc) $ haskell Any [] p ls xs
+  haskell (NestComment n) acc p ls ('-':'}':xs)
+                                    = haskell (NestComment (n-1))
+                                                            ("}-"++acc) p ls xs
+  haskell (NestComment n) acc p ls (x:xs) = haskell (NestComment n) (x:acc)
+                                                                        p ls xs
+  haskell CComment acc p ls ('*':'/':xs)  = emit ("  "++acc) $
+                                            haskell Any [] p ls xs
+  haskell CComment acc p ls (x:xs)        = haskell CComment (white x:acc) p ls xs
+  haskell CLineComment acc p ls xs@('\n':_)= emit acc $ haskell Any [] p ls xs
+  haskell CLineComment acc p ls (_:xs)    = haskell CLineComment (' ':acc)
+                                                                       p ls xs
+  haskell mode acc _ ((p,l):ls) []        = haskell mode acc p ls ('\n':l)
+  haskell _    acc _ [] []                = emit acc $ []
+
+  -- rules to lex Cpp
+  cpp :: SubMode -> (SubMode -> String -> Posn -> [(Posn,String)]
+                     -> String -> [WordStyle])
+         -> String -> [String] -> Posn -> [(Posn,String)]
+         -> String -> [WordStyle]
+  cpp mode next word line pos remaining input =
+    lexcpp mode word line remaining input
+   where
+    lexcpp Any w l ls ('/':'*':xs)   = lexcpp (NestComment 0) "" (w*/*l) ls xs
+    lexcpp Any w l ls ('/':'/':xs)   = lexcpp LineComment "  " (w*/*l) ls xs
+    lexcpp Any w l ((p,l'):ls) ('\\':[])  = cpp Any next [] ("\n":w*/*l) p ls l'
+    lexcpp Any w l ls ('\\':'\n':xs) = lexcpp Any [] ("\n":w*/*l) ls xs
+    lexcpp Any w l ls xs@('\n':_)    = Cmd (parseHashDefine ansi
+                                                           (reverse (w*/*l))):
+                                       next Any [] pos ls xs
+ -- lexcpp Any w l ls ('"':xs)     = lexcpp (String '"') ['"'] (w*/*l) ls xs
+ -- lexcpp Any w l ls ('\'':xs)    = lexcpp (String '\'') "'"  (w*/*l) ls xs
+    lexcpp Any w l ls ('"':xs)       = lexcpp Any [] ("\"":(w*/*l)) ls xs
+    lexcpp Any w l ls ('\'':xs)      = lexcpp Any [] ("'": (w*/*l)) ls xs
+    lexcpp Any [] l ls (x:xs)
+                    | ident0 x  = lexcpp (Pred ident1 Ident) [x] l ls xs
+ -- lexcpp Any w l ls (x:xs) | ident0 x  = lexcpp (Pred ident1 Ident) [x] (w*/*l) ls xs
+    lexcpp Any w l ls (x:xs)
+                    | single x  = lexcpp Any [] ([x]:w*/*l) ls xs
+                    | space x   = lexcpp (Pred space other) [x] (w*/*l) ls xs
+                    | symbol x  = lexcpp (Pred symbol other) [x] (w*/*l) ls xs
+                    | otherwise = lexcpp Any (x:w) l ls xs
+    lexcpp pre@(Pred pred _) w l ls (x:xs)
+                    | pred x    = lexcpp pre (x:w) l ls xs
+    lexcpp (Pred _ _) w l ls xs = lexcpp Any [] (w*/*l) ls xs
+    lexcpp (String c) w l ls ('\\':x:xs)
+                    | x=='\\'   = lexcpp (String c) ('\\':'\\':w) l ls xs
+                    | x==c      = lexcpp (String c) (c:'\\':w) l ls xs
+    lexcpp (String c) w l ls (x:xs)
+                    | x==c      = lexcpp Any [] ((c:w)*/*l) ls xs
+                    | otherwise = lexcpp (String c) (x:w) l ls xs
+    lexcpp LineComment w l ((p,l'):ls) ('\\':[])
+                             = cpp LineComment next [] (('\n':w)*/*l) pos ls l'
+    lexcpp LineComment w l ls ('\\':'\n':xs)
+                                = lexcpp LineComment [] (('\n':w)*/*l) ls xs
+    lexcpp LineComment w l ls xs@('\n':_) = lexcpp Any w l ls xs
+    lexcpp LineComment w l ls (_:xs)      = lexcpp LineComment (' ':w) l ls xs
+    lexcpp (NestComment _) w l ls ('*':'/':xs)
+                                          = lexcpp Any [] (w*/*l) ls xs
+    lexcpp (NestComment n) w l ls (x:xs)  = lexcpp (NestComment n) (white x:w) l
+                                                                        ls xs
+    lexcpp mode w l ((p,l'):ls) []        = cpp mode next w l p ls ('\n':l')
+    lexcpp _    _ _ []          []        = []
+
+    -- rules to lex non-Haskell, non-cpp text
+  plaintext :: SubMode -> String -> Posn -> [(Posn,String)]
+            -> String -> [WordStyle]
+  plaintext Any acc p ls ('\n':'#':xs)  = emit acc $  -- emit "\n" $
+                                          cpp Any plaintext [] [] p ls xs
+  plaintext Any acc p ls ('/':'*':xs)
+                           | stripComments = emit acc $
+                                             plaintext CComment "  " p ls xs
+  plaintext Any acc p ls ('/':'/':xs)
+                                | stripEol = emit acc $
+                                             plaintext CLineComment "  " p ls xs
+  plaintext Any acc p ls (x:xs) | single x = emit acc $ emit [x] $
+                                             plaintext Any [] p ls xs
+  plaintext Any acc p ls (x:xs) | space x  = emit acc $
+                                             plaintext (Pred space other) [x]
+                                                                        p ls xs
+  plaintext Any acc p ls (x:xs) | ident0 x = emit acc $
+                                             plaintext (Pred ident1 Ident) [x]
+                                                                        p ls xs
+  plaintext Any acc p ls (x:xs)            = plaintext Any (x:acc) p ls xs
+  plaintext pre@(Pred pred ws) acc p ls (x:xs)
+                                | pred x   = plaintext pre (x:acc) p ls xs
+  plaintext (Pred _ ws) acc p ls xs        = ws p (reverse acc):
+                                             plaintext Any [] p ls xs
+  plaintext CComment acc p ls ('*':'/':xs) = emit ("  "++acc) $
+                                             plaintext Any [] p ls xs
+  plaintext CComment acc p ls (x:xs)       = plaintext CComment (white x:acc) p ls xs
+  plaintext CLineComment acc p ls xs@('\n':_)
+                                        = emit acc $ plaintext Any [] p ls xs
+  plaintext CLineComment acc p ls (_:xs)= plaintext CLineComment (' ':acc)
+                                                                       p ls xs
+  plaintext mode acc _ ((p,l):ls) []    = plaintext mode acc p ls ('\n':l)
+  plaintext _    acc _ [] []            = emit acc $ []
+
+  -- predicates for lexing Haskell.
+  ident0 x = isAlpha x    || x `elem` "_`"
+  ident1 x = isAlphaNum x || x `elem` "'_`"
+  symbol x = x `elem` ":!#$%&*+./<=>?@\\^|-~"
+  single x = x `elem` "(),[];{}"
+  space  x = x `elem` " \t"
+  -- conversion of comment text to whitespace
+  white '\n' = '\n'
+  white '\r' = '\r'
+  white _    = ' '
+  -- emit a token (if there is one) from the accumulator
+  emit ""  = id
+  emit xs  = (Other (reverse xs):)
+  -- add a reversed word to the accumulator
+  "" */* l = l
+  w */* l  = reverse w : l
+  -- help out broken Haskell compilers which need balanced numbers of C
+  -- comments in order to do import chasing :-)  ----->   */*
+
+
+-- | Parse a possible macro call, returning argument list and remaining input
+parseMacroCall :: Posn -> [WordStyle] -> Maybe ([[WordStyle]],[WordStyle])
+parseMacroCall p = call . skip
+  where
+    skip (Other x:xs) | all isSpace x = skip xs
+    skip xss                          = xss
+    call (Other "(":xs)   = (args (0::Int) [] [] . skip) xs
+    call _                = Nothing
+    args 0 w acc (   Other ")" :xs)  = Just (reverse (addone w acc), xs)
+    args 0 w acc (   Other "," :xs)  = args 0     []   (addone w acc) (skip xs)
+    args n w acc (x@(Other "("):xs)  = args (n+1) (x:w)         acc    xs
+    args n w acc (x@(Other ")"):xs)  = args (n-1) (x:w)         acc    xs
+    args n w acc (   Ident _ v :xs)  = args n     (Ident p v:w) acc    xs
+    args n w acc (x@(Other _)  :xs)  = args n     (x:w)         acc    xs
+    args _ _ _   _                   = Nothing
+    addone w acc = reverse (skip w): acc
+ examples/CppHs/Language/Preprocessor/Unlit.hs view
@@ -0,0 +1,72 @@+-- | Part of this code is from "Report on the Programming Language Haskell",
+--   version 1.2, appendix C.
+module Language.Preprocessor.Unlit (unlit) where
+
+import Data.Char
+import Data.List (isPrefixOf)
+
+data Classified = Program String | Blank | Comment
+                | Include Int String | Pre String
+
+classify :: [String] -> [Classified]
+classify []                = []
+classify (('\\':x):xs) | x == "begin{code}" = Blank : allProg xs
+   where allProg [] = []  -- Should give an error message,
+                          -- but I have no good position information.
+         allProg (('\\':x):xs) |  "end{code}"`isPrefixOf`x = Blank : classify xs
+         allProg (x:xs) = Program x:allProg xs
+classify (('>':x):xs)      = Program (' ':x) : classify xs
+classify (('#':x):xs)      = (case words x of
+                                (line:rest) | all isDigit line
+                                   -> Include (read line) (unwords rest)
+                                _  -> Pre x
+                             ) : classify xs
+--classify (x:xs) | "{-# LINE" `isPrefixOf` x = Program x: classify xs
+classify (x:xs) | all isSpace x = Blank:classify xs
+classify (x:xs)                 = Comment:classify xs
+
+unclassify :: Classified -> String
+unclassify (Program s) = s
+unclassify (Pre s)     = '#':s
+unclassify (Include i f) = '#':' ':show i ++ ' ':f
+unclassify Blank       = ""
+unclassify Comment     = ""
+
+-- | 'unlit' takes a filename (for error reports), and transforms the
+--   given string, to eliminate the literate comments from the program text.
+unlit :: FilePath -> String -> String
+unlit file lhs = (unlines
+                 . map unclassify
+                 . adjacent file (0::Int) Blank
+                 . classify) (inlines lhs)
+
+adjacent :: FilePath -> Int -> Classified -> [Classified] -> [Classified]
+adjacent file 0 _             (x              :xs) = x : adjacent file 1 x xs -- force evaluation of line number
+adjacent file n y@(Program _) (x@Comment      :xs) = error (message file n "program" "comment")
+adjacent file n y@(Program _) (x@(Include i f):xs) = x: adjacent f    i     y xs
+adjacent file n y@(Program _) (x@(Pre _)      :xs) = x: adjacent file (n+1) y xs
+adjacent file n y@Comment     (x@(Program _)  :xs) = error (message file n "comment" "program")
+adjacent file n y@Comment     (x@(Include i f):xs) = x: adjacent f    i     y xs
+adjacent file n y@Comment     (x@(Pre _)      :xs) = x: adjacent file (n+1) y xs
+adjacent file n y@Blank       (x@(Include i f):xs) = x: adjacent f    i     y xs
+adjacent file n y@Blank       (x@(Pre _)      :xs) = x: adjacent file (n+1) y xs
+adjacent file n _             (x@next         :xs) = x: adjacent file (n+1) x xs
+adjacent file n _             []                   = []
+
+message :: String -> Int -> String -> String -> String
+message "\"\"" n p c = "Line "++show n++": "++p++ " line before "++c++" line.\n"
+message []     n p c = "Line "++show n++": "++p++ " line before "++c++" line.\n"
+message file   n p c = "In file " ++ file ++ " at line "++show n++": "++p++ " line before "++c++" line.\n"
+
+
+-- Re-implementation of 'lines', for better efficiency (but decreased laziness).
+-- Also, importantly, accepts non-standard DOS and Mac line ending characters.
+inlines :: String -> [String]
+inlines s = lines' s id
+  where
+  lines' []             acc = [acc []]
+  lines' ('\^M':'\n':s) acc = acc [] : lines' s id      -- DOS
+  lines' ('\^M':s)      acc = acc [] : lines' s id      -- MacOS
+  lines' ('\n':s)       acc = acc [] : lines' s id      -- Unix
+  lines' (c:s)          acc = lines' s (acc . (c:))
+
+ examples/Decl/AmbiguousFields.hs view
@@ -0,0 +1,9 @@+{-# LANGUAGE DuplicateRecordFields #-}
+module Decl.AmbiguousFields where
+
+data A = A { x, y :: Int }
+data B = B { x, y :: Int }
+
+f :: A -> Int
+f = x
+
+ examples/Decl/AnnPragma.hs view
@@ -0,0 +1,8 @@+module Decl.AnnPragma where
+{-# ANN module (Just "Hello") #-}
+{-# ANN f (Just "Hello") #-}
+f :: Int -> Int
+f a = a + 1
+
+{-# ANN type A (Just "Hello") #-}
+data A = A
+ examples/Decl/ClassInfix.hs view
@@ -0,0 +1,10 @@+module Decl.ClassInfix where
+
+import Control.Applicative
+
+class Applicative f => MonoidApplicative f where
+   infixl 4 +<*>
+   (+<*>) :: f (a -> a) -> f a -> f a
+
+   infixl 5 ><
+   (><) :: Monoid a => f a -> f a -> f a
+ examples/Decl/ClosedTypeFamily.hs view
@@ -0,0 +1,9 @@+{-# LANGUAGE TypeFamilies #-}
+module Decl.ClosedTypeFamily where
+
+type family F a where
+  F Int  = Bool
+  F Bool = Char
+  F a    = Bool
+
+type family ClosedEmpty t where
+ examples/Decl/CompletePragma.hs view
@@ -0,0 +1,16 @@+{-# LANGUAGE PatternSynonyms #-}
+module Decl.CompletePragma where
+
+data Choice a = Choice Bool a
+
+pattern LeftChoice :: a -> Choice a
+pattern LeftChoice a = Choice False a
+
+pattern RightChoice :: a -> Choice a
+pattern RightChoice a = Choice True a
+
+{-# COMPLETE LeftChoice, RightChoice #-}
+
+foo :: Choice Int -> Int
+foo (LeftChoice n) = n * 2
+foo (RightChoice n) = n - 2
+ examples/Decl/CtorOp.hs view
@@ -0,0 +1,10 @@+{-# LANGUAGE TypeOperators #-}
+module Decl.CtorOp where
+
+data a :+: b = a :+: b
+
+data (a :!: b) c = a c :!: b c
+
+data ((:-:) a) b = a :-: b
+
+data (:*:) a b = a :*: b
+ examples/Decl/DataFamily.hs view
@@ -0,0 +1,6 @@+{-# LANGUAGE TypeFamilies #-}
+module Decl.DataFamily where
+
+data family Array :: * -> *
+
+data instance Array () = UnitArray Int deriving Show
+ examples/Decl/DataInstanceGADT.hs view
@@ -0,0 +1,6 @@+{-# LANGUAGE GADTs, KindSignatures, TypeFamilies #-}
+module Decl.DataInstanceGADT where
+
+data family GadtFam (a :: *) (b :: *)
+data instance GadtFam c d where
+  MkGadtFam1 :: x -> y -> GadtFam y x
+ examples/Decl/DataType.hs view
@@ -0,0 +1,5 @@+module Decl.DataType where
+
+data EmptyData
+
+data A = B Int | C
+ examples/Decl/DataTypeDerivings.hs view
@@ -0,0 +1,5 @@+module Decl.DataTypeDerivings where
+
+data A = A deriving (Eq, Show)
+data B = B deriving (Eq)
+data C = C deriving Eq
+ examples/Decl/DefaultDecl.hs view
@@ -0,0 +1,3 @@+module Decl.DefaultDecl where
+
+default ()
+ examples/Decl/FunBind.hs view
@@ -0,0 +1,4 @@+module Decl.FunBind where
+
+f 0 = 1
+f x = x
+ examples/Decl/FunFixity.hs view
@@ -0,0 +1,5 @@+module Decl.FunFixity where
+
+infixl `snoc`
+snoc :: [a] -> a -> [a]
+snoc xs x = xs ++ [x]
+ examples/Decl/FunGuards.hs view
@@ -0,0 +1,5 @@+module Decl.FunGuards where
+
+f 0 = 1
+f x | even x = 0
+    | otherwise = 2
+ examples/Decl/FunctionalDeps.hs view
@@ -0,0 +1,6 @@+{-# LANGUAGE FunctionalDependencies, MultiParamTypeClasses #-}
+module Decl.FunctionalDeps where
+
+class C a b | a -> b, b -> a where
+  trf :: a -> b
+  
+ examples/Decl/GADT.hs view
@@ -0,0 +1,9 @@+{-# LANGUAGE GADTs, KindSignatures, DeriveDataTypeable #-}
+module Decl.GADT where
+
+import Data.Typeable
+
+data DMap k f where
+    Tip :: DMap k f
+    Bin :: !Int -> !(k v) -> f v -> !(DMap k f) -> !(DMap k f) -> DMap k f
+    deriving Typeable
+ examples/Decl/GadtConWithCtx.hs view
@@ -0,0 +1,5 @@+{-# LANGUAGE GADTs #-}
+module Decl.GadtConWithCtx where
+
+data Concurrently m a where
+  Concurrently :: Monad m => { runConcurrently :: m a } -> Concurrently m a
+ examples/Decl/InfixAssertion.hs view
@@ -0,0 +1,9 @@+{-# LANGUAGE DataKinds, TypeOperators, KindSignatures, TypeFamilies #-}
+module Decl.InfixAssertion where
+
+import GHC.TypeLits
+
+data Proxy (n :: Nat) = Proxy
+
+divSNat :: (1 <= b) => Proxy b -> Proxy b
+divSNat n = n
+ examples/Decl/InfixInstances.hs view
@@ -0,0 +1,8 @@+{-# LANGUAGE TypeOperators, TypeFamilies #-}
+module Decl.InfixInstances where
+
+data Zipper h i a = Zipper
+data (:@) a i
+infixl 8 :>
+type family (:>) h p
+type instance h :> (a :@ i) = Zipper h i a
+ examples/Decl/InfixPatSyn.hs view
@@ -0,0 +1,10 @@+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+module Decl.InfixPatSyn where
+
+pattern x :. xs <- (uncons -> Just (x,xs)) where
+  x:.xs = cons x xs
+infixr 5 :.
+
+cons x xs = x:xs
+uncons (x:xs) = Just (x,xs)
+uncons [] = Nothing
+ examples/Decl/InjectiveTypeFamily.hs view
@@ -0,0 +1,6 @@+{-# LANGUAGE TypeFamilies, TypeFamilyDependencies #-}
+module Decl.InjectiveTypeFamily where
+
+type family Array a = r | r -> a
+
+type instance Array () = Int
+ examples/Decl/InlinePragma.hs view
@@ -0,0 +1,5 @@+module Decl.InlinePragma where
+
+comp :: (b -> c) -> (a -> b) -> a -> c
+{-# INLINE CONLIKE [~1] comp #-}
+comp f g = \x -> f (g x)
+ examples/Decl/InstanceFamily.hs view
@@ -0,0 +1,10 @@+{-# LANGUAGE TypeOperators, TypeFamilies #-}
+module Decl.InstanceFamily where
+
+import GHC.Generics
+
+class HasTrie a where
+  data (:->:) a :: * -> *
+
+instance (HasTrie (f x)) => HasTrie (M1 i t f x) where
+  data (M1 i t f x :->: b) = M1Trie (f x :->: b)
+ examples/Decl/InstanceOverlaps.hs view
@@ -0,0 +1,11 @@+{-# LANGUAGE FlexibleInstances #-}
+module Decl.InstanceOverlaps where
+
+data A a = A a
+
+instance {-# OVERLAPPING #-} Show (A String) where
+  show (A a) = a
+instance {-# OVERLAPS #-} Show a => Show (A [a]) where
+  show (A a) = show a
+instance {-# OVERLAPPABLE #-} Show (A a) where
+  show (A _) = "A"
+ examples/Decl/InstanceSpec.hs view
@@ -0,0 +1,7 @@+module Decl.InstanceSpec where
+
+data Foo a = Foo a
+
+instance (Eq a) => Eq (Foo a) where 
+   {-# SPECIALIZE instance Eq (Foo Char) #-}
+   Foo a == Foo b = a == b
+ examples/Decl/LocalBindingInDo.hs view
@@ -0,0 +1,7 @@+module Decl.LocalBindingInDo where
+
+x :: Maybe ()
+x = do let y = f a
+             where a = ()
+       return y
+    where f = id
+ examples/Decl/LocalBindings.hs view
@@ -0,0 +1,9 @@+module Decl.LocalBindings where
+
+f x = g x
+  where g :: Int -> Int
+        g = id
+        
+f' x | even x = g x
+  where g :: Int -> Int
+        g = id
+ examples/Decl/LocalFixity.hs view
@@ -0,0 +1,6 @@+module Decl.LocalFixity where
+
+x = 1 `f` 2
+  where f :: Int -> Int -> Int
+        f a b = a + b 
+        infixl 6 `f`
+ examples/Decl/MinimalPragma.hs view
@@ -0,0 +1,23 @@+module Decl.MinimalPragma where
+
+class A x where
+  f, g :: x -> ()
+  {-# MINIMAL f,g #-}
+
+class B x where
+  fb, gb :: x -> ()
+  fb = gb
+  gb = fb
+  {-# MINIMAL fb | gb #-}
+
+class C x where
+  fc, gc, hc :: x -> x
+  gc = fc
+  hc = fc
+  fc = gc . hc
+  {-# MINIMAL fc | (gc, hc) #-}
+
+class D x where
+  fd :: x -> x
+  fd = id
+  {-# MINIMAL #-}
+ examples/Decl/MixedInstance.hs view
@@ -0,0 +1,11 @@+{-# LANGUAGE TypeFamilies, MultiParamTypeClasses #-}
+module Decl.MixedInstance where
+
+data Canvas = Canvas
+data V2 = V2
+
+class Backend c v e where
+  data Options c v e :: *
+
+instance Backend Canvas V2 Double where
+  data Options Canvas V2 Double = CanvasOptions
+ examples/Decl/MultipleFixity.hs view
@@ -0,0 +1,12 @@+module Decl.MultipleFixity where
+
+f :: Int -> Int -> Int
+f a b = a + b
+
+g = f
+
+infixl 6 `f`, `g`
+
+h = f
+
+infixl 5 `h`
+ examples/Decl/MultipleSigs.hs view
@@ -0,0 +1,6 @@+module Decl.MultipleSigs where
+
+f, g :: Int -> Int -> Int
+f a b = a + b
+
+g = f
+ examples/Decl/OperatorBind.hs view
@@ -0,0 +1,6 @@+module Decl.OperatorBind where
+
+a >< b = a ++ b
+
+(<+>) :: Int -> Int -> Int -> Int
+(a <+> b) c = a + b + c
+ examples/Decl/OperatorDecl.hs view
@@ -0,0 +1,6 @@+module Decl.OperatorDecl where
+
+(-!-) :: Int -> Int -> Int
+(-!-) a b = a + b
+
+test = (-!-) (1 -!- 2) 3
+ examples/Decl/ParamDataType.hs view
@@ -0,0 +1,5 @@+module Decl.ParamDataType where
+
+data A a = B Int | C a
+
+data X a = X a
+ examples/Decl/PatternBind.hs view
@@ -0,0 +1,3 @@+module Decl.PatternBind where
+
+(x,y) | 1 == 1 = (1,2)
+ examples/Decl/PatternSynonym.hs view
@@ -0,0 +1,28 @@+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+module Decl.PatternSynonym where
+
+data Type = App String [Type]
+
+pattern Arrow :: Type -> Type -> Type
+pattern Arrow t1 t2 = App "->"    [t1, t2]
+
+
+pattern Int        <- App "Int"   []
+
+pattern Maybe t    <- App "Maybe" [t]
+   where Maybe (App "()" []) = App "Bool" []
+         Maybe t = App "Maybe" [t]
+
+pattern (:<) :: [a] -> a -> [a]
+pattern (:<) xs x <- ((\ys -> (init ys,last ys)) -> (xs,x))
+  where
+    (:<) xs x = xs ++ [x]
+
+------ this is not supported yet
+-- class ListLike a where
+--   pattern Head :: e -> a e0
+--   pattern Tail :: a e -> a e
+
+-- instance ListLike [] where
+--   pattern Head h = h:_
+--   pattern Tail t = _:t
+ examples/Decl/RecordPatternSynonyms.hs view
@@ -0,0 +1,8 @@+{-# LANGUAGE PatternSynonyms #-}
+module Decl.RecordPatternSynonyms where
+
+pattern XPoint {xp} <- (xp, 0) where XPoint xp = (xp, 0)
+
+pattern Point {x, y} = (x, y)
+
+r = (0, 0) { x = 1 }
+ examples/Decl/RecordType.hs view
@@ -0,0 +1,3 @@+module Decl.RecordType where
+
+data A = B { valB, extra :: Int, qq :: Double } | C
+ examples/Decl/RewriteRule.hs view
@@ -0,0 +1,3 @@+module Decl.RewriteRule where
+
+{-# RULES "map/map" forall f g xs . map f (map g xs) = map (f . g) xs #-}
+ examples/Decl/SpecializePragma.hs view
@@ -0,0 +1,5 @@+module Decl.SpecializePragma where
+
+hammeredLookup :: Ord key => [(key, value)] -> key -> value
+{-# SPECIALIZE hammeredLookup :: [(String, value)] -> String -> value, [(Char, value)] -> Char -> value #-}
+hammeredLookup = undefined
+ examples/Decl/StandaloneDeriving.hs view
@@ -0,0 +1,6 @@+{-# LANGUAGE StandaloneDeriving #-}
+module Decl.StandaloneDeriving where
+
+data WrapStr = WrapStr String 
+
+deriving instance Eq WrapStr
+ examples/Decl/TypeClass.hs view
@@ -0,0 +1,13 @@+{-# LANGUAGE TypeFamilies #-}
+module Decl.TypeClass where
+
+class EmptyClass a
+
+class Show a => C a where
+  type X a :: *
+  type X a = Int
+  data Q a :: *
+  
+  f :: a -> String
+  f = show
+  
+ examples/Decl/TypeClassMinimal.hs view
@@ -0,0 +1,8 @@+module Decl.TypeClassMinimal where
+
+class Eq' a where
+    (=.=) :: a -> a -> Bool
+    (/.=) :: a -> a -> Bool
+    x =.= y = not (x /.= y)
+    x /.= y = not (x =.= y)
+    {-# MINIMAL (=.=) | (/.=) #-}
+ examples/Decl/TypeFamily.hs view
@@ -0,0 +1,6 @@+{-# LANGUAGE TypeFamilies #-}
+module Decl.TypeFamily where
+
+type family Array a :: *
+
+type instance Array () = Int
+ examples/Decl/TypeFamilyKindSig.hs view
@@ -0,0 +1,6 @@+{-# LANGUAGE TypeFamilies #-}
+module Decl.TypeFamilyKindSig where
+
+type family Array (a :: *) :: *
+
+type instance Array () = Int
+ examples/Decl/TypeInstance.hs view
@@ -0,0 +1,14 @@+{-# LANGUAGE TypeFamilies, InstanceSigs #-}
+module Decl.TypeInstance where
+
+import Decl.TypeClass
+
+data A = A deriving Show
+
+instance C A where
+  type X A = Int
+  data Q A = Bool
+
+  f :: A -> String
+  f A = "XXX"
+  
+ examples/Decl/TypeRole.hs view
@@ -0,0 +1,5 @@+{-# LANGUAGE RoleAnnotations #-}
+module Decl.TypeRole where
+
+type role Foo representational representational
+data Foo a b = Foo Int
+ examples/Decl/TypeSynonym.hs view
@@ -0,0 +1,3 @@+module Decl.TypeSynonym where
+
+type List = Int
+ examples/Decl/ValBind.hs view
@@ -0,0 +1,3 @@+module Decl.ValBind where
+
+x = 1
+ examples/Decl/ViewPatternSynonym.hs view
@@ -0,0 +1,8 @@+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+module Decl.ViewPatternSynonym where
+
+data Uncert a = Un a a
+
+pattern x :+/- dx <- Un x (sqrt->dx)
+  where
+    x :+/- dx = Un x (dx*dx)
+ examples/Expr/ArrowNotation.hs view
@@ -0,0 +1,10 @@+{-# LANGUAGE Arrows #-}
+module Expr.ArrowNotation where
+
+import Control.Arrow
+
+addA :: Arrow a => a b Int -> a b Int -> a b Int
+addA f g = proc x -> do
+                y <- f -< x
+                z <- g -< x
+                returnA -< y + z
+ examples/Expr/Case.hs view
@@ -0,0 +1,8 @@+module Expr.Case where
+
+x = 12
+
+a = case x of 1 -> 0
+              _ -> 1
+
+b = case x of { 1 -> 0; _ -> 1 }
+ examples/Expr/DoNotation.hs view
@@ -0,0 +1,15 @@+module Expr.DoNotation where
+
+import Control.Monad.Identity
+
+x1 :: Identity ()
+x1 = return ()
+
+x2 :: Identity ()
+x2 = do return ()
+
+x3 :: Identity ()
+x3 = do { return () }
+
+x4 :: Identity Int
+x4 = do { one <- Identity 1; return (one + 1) }
+ examples/Expr/EmptyCase.hs view
@@ -0,0 +1,8 @@+{-# LANGUAGE EmptyCase #-}
+module Expr.EmptyCase where
+
+x = 12
+
+a = case x of 
+
+b = case x of {}
+ examples/Expr/EmptyLet.hs view
@@ -0,0 +1,6 @@+module Expr.EmptyLet where
+
+a = let in ()
+
+m = do let
+       putStrLn "hello"
+ examples/Expr/FunSection.hs view
@@ -0,0 +1,6 @@+module Expr.FunSection where
+
+data Rule = Rule {
+    rulePath :: String -> Bool }
+
+f r = filter (`rulePath` r)
+ examples/Expr/GeneralizedListComp.hs view
@@ -0,0 +1,31 @@+{-# LANGUAGE ParallelListComp, 
+             TransformListComp,
+             MonadComprehensions,
+             RecordWildCards #-}
+module Expr.GeneralizedListComp where
+
+import GHC.Exts
+import qualified Data.Map as M
+import Data.Ord (comparing)
+
+data Character = Character
+  { firstName :: String
+  , lastName :: String
+  , birthYear :: Int
+  } deriving (Show, Eq)
+
+friends :: [Character]
+friends = [ Character "Phoebe" "Buffay" 1963
+          , Character "Chandler" "Bing" 1969
+          , Character "Rachel" "Green" 1969
+          , Character "Joey" "Tribbiani" 1967
+          , Character "Monica" "Geller" 1964
+          , Character "Ross" "Geller" 1966
+          ]
+          
+oldest :: Int -> [Character] -> [String]
+oldest k tbl = [ firstName ++ " " ++ lastName
+               | Character{..} <- tbl
+               , then sortWith by birthYear
+               , then take k
+               ]
+ examples/Expr/If.hs view
@@ -0,0 +1,4 @@+module Expr.If where
+
+b = 12
+a = if b > 3 then 1 else 0
+ examples/Expr/LambdaCase.hs view
@@ -0,0 +1,11 @@+{-# LANGUAGE LambdaCase, EmptyCase #-}
+module Expr.LambdaCase where
+
+a = \case 1 -> 0
+          _ -> 1
+
+b = \case { 1 -> 0; _ -> 1 }
+
+c = \case {}
+
+d = \case
+ examples/Expr/ListComp.hs view
@@ -0,0 +1,3 @@+module Expr.ListComp where
+
+ls = [ x+y | x <- [1..5], y <- [1..5]]
+ examples/Expr/MultiwayIf.hs view
@@ -0,0 +1,7 @@+{-# LANGUAGE MultiWayIf #-}
+module Expr.MultiwayIf where
+
+b = 12
+a = if | b > 3     -> 1
+       | b < -5    -> 2
+       | otherwise -> 3
+ examples/Expr/Negate.hs view
@@ -0,0 +1,4 @@+module Expr.Negate where
+
+y = 1
+x = -y 
+ examples/Expr/Operator.hs view
@@ -0,0 +1,5 @@+module Expr.Operator where
+
+x = 1 + 2
+y = (+) 1 2
+z = 1 `mod` 2
+ examples/Expr/ParListComp.hs view
@@ -0,0 +1,4 @@+{-# LANGUAGE ParallelListComp #-}
+module Expr.ParListComp where
+
+ls = [ x+y | x <- [1..5] | y <- [1..5]]
+ examples/Expr/ParenName.hs view
@@ -0,0 +1,3 @@+module Expr.ParenName where
+
+a x y = (mod) x y
+ examples/Expr/PatternAndDo.hs view
@@ -0,0 +1,10 @@+{-# LANGUAGE RecordWildCards #-}
+module Expr.PatternAndDo where
+
+import Control.Monad
+import Control.Monad.Identity
+
+data A = A { x :: Int }
+
+a = forM_ [] $ \A {..} -> do
+      Identity "Hello"
+ examples/Expr/RecordPuns.hs view
@@ -0,0 +1,6 @@+{-# LANGUAGE NamedFieldPuns #-}
+module Expr.RecordPuns where
+
+data Point = Point { x :: Int, y :: Int }
+
+f (Point {y}) = y
+ examples/Expr/RecordWildcards.hs view
@@ -0,0 +1,6 @@+{-# LANGUAGE RecordWildCards #-}
+module Expr.RecordWildcards where
+
+data Point = Point { x :: Int, y :: Int }
+
+p1 = let x = 3; y = 4 in Point { x = 1, .. }
+ examples/Expr/RecursiveDo.hs view
@@ -0,0 +1,9 @@+{-# LANGUAGE RecursiveDo #-}
+module Expr.RecursiveDo where
+
+justOnes = mdo xs <- Just (1:xs)
+               return (map negate xs)
+
+justOnes' = do rec xs <- Just (1:xs)
+                   return (map negate xs)
+               return xs
+ examples/Expr/SccPragma.hs view
@@ -0,0 +1,4 @@+module Expr.SccPragma where
+
+f x = {-# SCC "drawComponent" #-}
+        case x of () -> ()
+ examples/Expr/Sections.hs view
@@ -0,0 +1,4 @@+module Expr.Sections where
+
+x = (1+)
+y = (+1)
+ examples/Expr/SemicolonDo.hs view
@@ -0,0 +1,7 @@+module Expr.SemicolonDo where
+
+import Control.Monad.Identity
+
+a = do { n <- Identity ()
+            ; return ()
+            }
+ examples/Expr/StaticPtr.hs view
@@ -0,0 +1,16 @@+{-# LANGUAGE StaticPointers #-}
+module Expr.StaticPtr where
+
+import GHC.StaticPtr
+
+inc :: Int -> Int
+inc x = x + 1
+
+ref1, ref3, ref4 :: StaticPtr Int
+ref2 :: StaticPtr (Int -> Int)
+ref5 :: Int -> StaticPtr Int
+ref1 = static 1
+ref2 = static inc
+ref3 = static (inc 1)
+ref4 = static ((\x -> x + 1) (1 :: Int))
+ref5 y = static (let x = 1 in x)
+ examples/Expr/TupleSections.hs view
@@ -0,0 +1,7 @@+{-# LANGUAGE TupleSections #-}
+module Expr.TupleSections where
+
+f1 = (1,,)
+f2 = (,1)
+
+x = (,("x", []))
+ examples/Expr/UnboxedSum.hs view
@@ -0,0 +1,13 @@+{-# LANGUAGE UnboxedSums #-}
+module Expr.UnboxedSum where
+
+f = ()
+  where
+    expr :: (# Int | Bool #)
+    expr = (# | True #)
+
+    expr2 :: (# Int | Bool #)
+    expr2 = (# 3 | #)
+
+    expr3 :: (# Int | String | Bool #)
+    expr3 = (# | "aaa" | #)
+ examples/Expr/UnicodeSyntax.hs view
@@ -0,0 +1,7 @@+{-# LANGUAGE UnicodeSyntax #-}
+module Expr.UnicodeSyntax where
+    
+import Data.List.Unicode ((∪))
+
+main ∷ IO ()
+main = print $ [1, 2, 3] ∪ [1, 3, 5]
+ examples/InstanceControl/Control/Instances/Morph.hs view
@@ -0,0 +1,149 @@+{-# LANGUAGE TypeFamilies, DataKinds, TypeOperators, MultiParamTypeClasses, FlexibleInstances, PolyKinds, UndecidableInstances, AllowAmbiguousTypes, RankNTypes, ScopedTypeVariables, FlexibleContexts #-}
+
+module Control.Instances.Morph (GenMorph(..), Morph(..)) where
+
+import Control.Instances.ShortestPath
+
+import Control.Monad.Identity
+import Control.Monad.Trans.Maybe
+import Control.Monad.Trans.List
+import Control.Monad.State
+import Data.Maybe
+import Data.Proxy
+import GHC.TypeLits
+import Control.Instances.TypeLevelPrelude
+
+-- | States that 'm1' can be represented with 'm2'.
+-- That is because 'm2' contains more infromation than 'm1'.
+--
+-- The 'MMorph' relation defines a natural transformation from 'm1' to 'm2'
+-- that keeps the following laws:
+--
+-- > morph (return x)  =  return x
+-- > morph (m >>= f)   =  morph m >>= morph . f
+-- 
+-- It is a reflexive and transitive relation.
+--
+class Morph (m1 :: * -> *) (m2 :: * -> *) where
+  -- | Lifts the first monad into the second.
+  morph :: m1 a -> m2 a
+  
+instance GenMorph DB m1 m2 => Morph m1 m2 where
+  morph = genMorph db
+  
+-- | A generalized version of 'Morph'. Can work on different
+-- rulesets, so this should be used if the ruleset is to be extended.
+class GenMorph db (m1 :: * -> *) (m2 :: * -> *) where
+  -- | Lifts the first monad into the second.
+  genMorph :: db -> m1 a -> m2 a
+  
+instance ( fl ~ (TransformPath (PathFromList (ShortestPath (ToMorphRepo DB) x y)))
+         , CorrectPath x y fl
+         , GeneratableMorph DB fl
+         , Morph' fl x y
+         ) => GenMorph DB x y where
+  genMorph db = repr (generateMorph db :: fl)
+  
+class Morph' fl x y where
+  repr :: fl -> x a -> y a
+  
+instance Morph' r y z => Morph' (ConnectMorph x y :+: r) x z where
+  repr (ConnectMorph m :+: r) = repr r . m
+ 
+instance (Morph' r m x, Monad m) => Morph' (IdentityMorph m :+: r) Identity x where
+  repr (IdentityMorph :+: r) = (repr r :: forall a . m a -> x a) . return . runIdentity
+  
+instance Morph' (MUMorph m :+: r) m Proxy where
+  repr (MUMorph :+: _) = const Proxy
+ 
+instance Morph' NoMorph x x where
+  repr fl = id
+  
+infixr 6 :+:
+data a :+: r = a :+: r 
+
+data NoMorph = NoMorph
+  
+type family ToMorphRepo db where
+  ToMorphRepo (cm :+: r) = TranslateConn cm ': ToMorphRepo r
+  ToMorphRepo NoMorph = '[]
+   
+type DB = ConnectMorph_2m Maybe MaybeT
+           :+: ConnectMorph_mt MaybeT 
+           :+: ConnectMorph Maybe [] 
+           :+: ConnectMorph_2m [] ListT
+           :+: ConnectMorph (MaybeT IO) (ListT IO)
+           :+: NoMorph
+ 
+db :: DB 
+db = ConnectMorph_2m (MaybeT . return) 
+       :+: ConnectMorph_mt (MaybeT . liftM Just) 
+       :+: ConnectMorph (maybeToList) 
+       :+: ConnectMorph_2m (ListT . return) 
+       :+: ConnectMorph (ListT . liftM maybeToList . runMaybeT) 
+       :+: NoMorph
+  
+-- | This class provides a way to construct the value-level transformations
+-- from the type-level path and a rulebase.
+class GeneratableMorph db ch where
+  generateMorph :: db -> ch
+    
+instance GeneratableMorph db NoMorph where
+  generateMorph _ = NoMorph
+  
+instance GeneratableMorph db r 
+      => GeneratableMorph db ((IdentityMorph m) :+: r) where
+  generateMorph db = IdentityMorph :+: generateMorph db
+  
+instance GeneratableMorph db r 
+      => GeneratableMorph db (MUMorph m :+: r) where
+  generateMorph db = MUMorph :+: generateMorph db
+  
+instance (HasMorph db (ConnectMorph a b), GeneratableMorph db r) 
+      => GeneratableMorph db (ConnectMorph a b :+: r) where
+  generateMorph db = getMorph db :+: generateMorph db
+  
+-- | This class extracts a given morph from the set of rules
+class HasMorph r m where 
+  getMorph :: r -> m
+instance {-# OVERLAPPING #-} Monad k => HasMorph (ConnectMorph_2m a b :+: r) (ConnectMorph a (b k)) where
+  getMorph (ConnectMorph_2m f :+: r) = ConnectMorph f
+instance {-# OVERLAPPING #-} Monad k => HasMorph (ConnectMorph_mt t :+: r) (ConnectMorph k (t k)) where
+  getMorph (ConnectMorph_mt f :+: r) = ConnectMorph f
+instance {-# OVERLAPS #-} HasMorph r m => HasMorph (c :+: r) m where
+  getMorph (c :+: r) = getMorph r
+instance {-# OVERLAPPABLE #-} HasMorph (m :+: r) m where
+  getMorph (c :+: r) = c
+
+-- | Checks if the path is found to provide usable error messages
+class CorrectPath from to path
+
+instance CorrectPath from to (a :+: b)
+instance CorrectPath from to NoMorph
+
+data ConnectMorph m1 m2 = ConnectMorph { fromConnectMorph :: forall a . m1 a -> m2 a }
+data ConnectMorph_2m m1 m2 = ConnectMorph_2m { fromConnectMorph_2m :: forall a k . Monad k => m1 a -> m2 k a }
+data ConnectMorph_mt mt = ConnectMorph_mt { fromConnectMorph_mt :: forall a k . Monad k => k a -> mt k a }
+data IdentityMorph (m :: * -> *) = IdentityMorph
+data MUMorph m = MUMorph
+
+-- | Transforms a path element from the generic format to the specific one
+type family TranslateConn m where
+  TranslateConn (ConnectMorph m1 m2) = Connect m1 m2
+  TranslateConn (ConnectMorph_2m m1 m2) = Connect_2m m1 m2
+  TranslateConn (ConnectMorph_mt mt) = Connect_mt mt
+  
+-- | Transforms the path from the generic format to the specific one
+type family TransformPath m where
+  TransformPath (Connect m1 m2 :+: r) = ConnectMorph m1 m2 :+: TransformPath r
+  TransformPath (Connect_id m :+: r) = IdentityMorph m :+: TransformPath r
+  TransformPath (Connect_MU m :+: r) = MUMorph m :+: TransformPath r
+  TransformPath NoMorph = NoMorph
+  TransformPath NoPathFound = NoPathFound
+  
+type family PathFromList ls where
+  PathFromList '[] = NoMorph
+  PathFromList '[ NoPathFound ] = NoPathFound
+  PathFromList (c ': ls) = c :+: PathFromList ls
+
+
+ examples/InstanceControl/Control/Instances/ShortestPath.hs view
@@ -0,0 +1,69 @@+{-# LANGUAGE TypeFamilies, DataKinds, TypeOperators, MultiParamTypeClasses, FlexibleInstances, PolyKinds, UndecidableInstances, AllowAmbiguousTypes, RankNTypes, ScopedTypeVariables, FlexibleContexts #-}
+
+module Control.Instances.ShortestPath where
+
+import Control.Monad.Identity
+import Control.Monad.Trans.Maybe
+import Control.Monad.Trans.List
+import Control.Monad.State
+import Data.Maybe
+import Data.Proxy
+import GHC.TypeLits
+import Control.Instances.TypeLevelPrelude
+
+-- * Generic datatypes to store connections
+  
+data Connect m1 m2
+data Connect_2m m1 m2
+data Connect_mt mt
+data Connect_id m
+data Connect_MU m
+
+-- | Marks that there is no legal path between the two types according
+-- to the rulebase.
+data NoPathFound
+  
+type family ShortestPath (e :: [*]) (s :: * -> *) (t :: * -> *) :: [*] where
+  ShortestPath e t t = '[]
+  ShortestPath e Identity t = '[ Connect_id t ]
+  ShortestPath e s Proxy = '[ Connect_MU s ]
+  ShortestPath e s t = ShortestPath' e s (InitCurrent e t)
+  
+type family ShortestPath' (e :: [*]) (s :: * -> *) (c :: [[*]]) :: [*] where
+  ShortestPath' e s '[] = '[ NoPathFound ]
+  ShortestPath' e s c = FromMaybe (ShortestPath' e s (ApplyEdges e c c))
+                                  (GetFinished s c) 
+                                  
+                                      
+type family GetFinished s c where
+  GetFinished s ((Connect s b ': p) ': lls) 
+    = Just (Connect s b ': p)
+  GetFinished s (p ': lls) = GetFinished s lls
+  GetFinished s '[] = Nothing
+
+type family InitCurrent (e :: [*]) (t :: * -> *) :: [[*]] where
+  InitCurrent '[] t = '[]
+  InitCurrent (e ': es) t = IfJust (ApplyEdge e t)
+                                   ('[ MonomorphEnd e t ] ': InitCurrent es t) 
+                                   (InitCurrent es t)
+  
+type family ApplyEdges (e :: [*]) (co :: [[*]]) (c :: [[*]]) :: [[*]] where
+  ApplyEdges (e ': es) co ((Connect s b ': p) ': cs) 
+    = AppendJust (IfThenJust (IsJust (ApplyEdge e s)) 
+                                (MonomorphEnd e s ': Connect s b ': p)) 
+                 (ApplyEdges (e ': es) co cs)
+  ApplyEdges (e ': es) co '[] = ApplyEdges es co co
+  ApplyEdges '[] co cr = '[]  
+  
+type family ApplyEdge e t :: Maybe (* -> *) where
+  ApplyEdge (Connect ms mr) mr = Just ms
+  ApplyEdge (Connect_2m ms mt) (mt m) = Just ms
+  ApplyEdge (Connect_mt mt) (mt m) = Just m
+  ApplyEdge e t = Nothing
+
+type family MonomorphEnd c v :: * where
+  MonomorphEnd (Connect_2m m m') v = Connect m v
+  MonomorphEnd (Connect_mt t) (t m) = Connect m (t m)
+  MonomorphEnd c v = c
+
+
+ examples/InstanceControl/Control/Instances/Test.hs view
@@ -0,0 +1,23 @@+module Control.Instances.Test where
+
+import Control.Instances.Morph
+
+import Control.Monad.Identity
+import Control.Monad.Trans.Maybe
+import Control.Monad.Trans.List
+import Control.Monad.State
+
+test1 :: Identity a -> IO a
+test1 = morph
+
+test2 :: Maybe a -> [a]
+test2 = morph
+
+test3 :: Maybe a -> ListT IO a
+test3 = morph
+
+test4 :: Maybe a -> MaybeT IO a
+test4 = morph
+
+test5 :: Monad m => Maybe a -> ListT (StateT s m) a
+test5 = morph
+ examples/InstanceControl/Control/Instances/TypeLevelPrelude.hs view
@@ -0,0 +1,88 @@+{-# LANGUAGE TypeFamilies, DataKinds, TypeOperators, MultiParamTypeClasses, FlexibleInstances, PolyKinds, UndecidableInstances, AllowAmbiguousTypes, RankNTypes, ScopedTypeVariables, FlexibleContexts #-}
+
+module Control.Instances.TypeLevelPrelude where
+
+import GHC.TypeLits
+
+type family Const a b where
+  Const a b = a
+  
+type family Seq a b where
+  Seq a b = b
+  
+type family LazyIfThenElse p a b where
+  LazyIfThenElse True a b = a
+  LazyIfThenElse False a b = b
+  
+type family Iterate a where
+  Iterate a = a ': Iterate a
+
+type family l1 :++: l2 where
+  '[] :++: l2       = l2
+  (e ': r1) :++: l2 = e ': (r1 :++: l2)
+  
+type family Elem e ls where
+  Elem e '[] = False
+  Elem e (e ': ls) = True
+  Elem e (x ': ls) = Elem e ls
+  
+type family IfThenElse (b :: Bool) (th :: x) (el :: x) :: x where
+  IfThenElse True  th el = th
+  IfThenElse False th el = el
+         
+type family Length ls :: Nat where
+  Length '[] = 0
+  Length (e ': ls) = 1 + Length ls
+           
+type family Head (ls :: [k]) :: k where
+  Head (e ': ls) = e   
+  
+type family HeadMaybe (ls :: [k]) :: Maybe k where
+  HeadMaybe (e ': ls) = Just e
+  HeadMaybe '[] = Nothing
+  
+type family FromMaybe d m where
+  FromMaybe d (Just x) = x
+  FromMaybe d Nothing = d
+  
+type family Same a b where
+  Same a a = True
+  Same a b = False
+  
+type family Null (ls :: [k]) :: Bool where
+  Null '[] = True
+  Null ls = False
+           
+type family MapAppend e lls where
+  MapAppend e (ls ': lls) = (e ': ls) ': MapAppend e lls
+  MapAppend e '[] = '[]
+  
+type family AppendJust m ls where
+  AppendJust (Just x) ls = x ': ls
+  AppendJust Nothing ls = ls
+  
+type family Revert ls where
+  Revert '[] = '[]
+  Revert (e ': ls) = Revert ls :++: '[ e ]
+  
+type family IfThenJust (p :: Bool) (v :: k) :: Maybe k where
+  IfThenJust True v = Just v
+  IfThenJust False v = Nothing  
+  
+type family IfJust (p :: Maybe k) (t :: kr) (e :: kr) :: kr where
+  IfJust (Just x) t e = t
+  IfJust Nothing t e = e
+  
+type family IsJust (p :: Maybe k) :: Bool where
+  IsJust (Just x) = True
+  IsJust Nothing = False    
+  
+type family FromJust (p :: Maybe k) :: k where
+  FromJust (Just x) = x
+  
+type family Cat (f2 :: k2 -> k3) (f1 :: k1 -> k2) (a :: k1) :: k3 where
+  Cat f2 f1 a = f2 (f1 a)
+  
+
+  
+  
+ examples/Module/DeprecatedPragma.hs view
@@ -0,0 +1,1 @@+module Module.DeprecatedPragma {-# DEPRECATED "this module is deprecated" #-} where
+ examples/Module/Export.hs view
@@ -0,0 +1,2 @@+module Module.Export (maybe, Maybe(..), Either(Left)) where
+-- this module reexports Maybe from Prelude
+ examples/Module/ExportModifiers.hs view
@@ -0,0 +1,4 @@+{-# LANGUAGE ExplicitNamespaces, PatternSynonyms #-}
+module Module.ExportModifiers (type Maybe, pattern Maybe) where
+
+pattern Maybe = 42
+ examples/Module/ExportSubs.hs view
@@ -0,0 +1,3 @@+module Module.ExportSubs (T(Cons, name)) where
+
+data T = Cons { name :: String }
+ examples/Module/GhcOptionsPragma.hs view
@@ -0,0 +1,2 @@+{-# OPTIONS_GHC -Wno-name-shadowing #-}
+module Module.GhcOptionsPragma where
+ examples/Module/Import.hs view
@@ -0,0 +1,11 @@+{-# LANGUAGE PackageImports, Safe #-}
+module Module.Import where
+
+import Data.List
+import "base" Data.List
+import {-# SOURCE #-} Data.List
+import qualified Data.List
+import Data.List as List
+import Data.List(map,(++))
+import Data.Function hiding ((&))
+import safe Control.Monad.Writer hiding (Alt, Writer())
+ examples/Module/ImportOp.hs view
@@ -0,0 +1,3 @@+module Module.ImportOp where
+
+import Module.Imported ((:-)(..))
+ examples/Module/Imported.hs view
@@ -0,0 +1,6 @@+{-# LANGUAGE TypeOperators #-}
+module Module.Imported where
+
+infixr 8 :-
+-- | A stack datatype. Just a better looking tuple.
+data a :- b = a :- b deriving (Eq, Show)
+ examples/Module/LangPragmas.hs view
@@ -0,0 +1,4 @@+{-# LANGUAGE LambdaCase #-}
+{-#LANGUAGE LambdaCase #-}
+{-# LANGUAGE LambdaCase#-}
+module Module.LangPragmas where
+ examples/Module/NamespaceExport.hs view
@@ -0,0 +1,4 @@+{-# LANGUAGE TypeOperators #-}
+module Module.NamespaceExport (type (++)) where
+
+data a ++ b = Ctor
+ examples/Module/PatternImport.hs view
@@ -0,0 +1,4 @@+{-# LANGUAGE PatternSynonyms #-}
+module Module.PatternImport where
+
+import Decl.PatternSynonym (pattern Arrow)
+ examples/Module/Simple.hs view
@@ -0,0 +1,1 @@+module Module.Simple where
+ examples/Module/WarningPragma.hs view
@@ -0,0 +1,1 @@+module Module.WarningPragma {-# WARNING "this module is dangerous" #-} where
+ examples/Pattern/Backtick.hs view
@@ -0,0 +1,5 @@+module Pattern.Backtick where
+
+data Point = Point { x :: Prelude.Int, y :: Int }
+
+f (x `Point` y) = 0
+ examples/Pattern/Constructor.hs view
@@ -0,0 +1,3 @@+module Pattern.Constructor where
+
+Just x = Just 1
+ examples/Pattern/ImplicitParams.hs view
@@ -0,0 +1,9 @@+{-# LANGUAGE ImplicitParams #-}
+module Pattern.ImplicitParams where
+
+import Data.List (sortBy)
+
+sort :: (?cmp :: a -> a -> Ordering) => [a] -> [a]
+sort = sortBy ?cmp
+
+main = let ?cmp = compare in putStrLn (show (sort [3,1,2]))
+ examples/Pattern/Infix.hs view
@@ -0,0 +1,5 @@+module Pattern.Infix where
+
+--(a:b:c:d) = ["1","2","3","4"]
+
+Nothing:_ = undefined
+ examples/Pattern/NPlusK.hs view
@@ -0,0 +1,6 @@+{-# LANGUAGE NPlusKPatterns #-}
+module Pattern.NPlusK where
+
+factorial :: Integer -> Integer
+factorial 0 = 1
+factorial (n+1) = (*) (n+1) (factorial n)
+ examples/Pattern/NestedWildcard.hs view
@@ -0,0 +1,7 @@+{-# LANGUAGE NamedFieldPuns, RecordWildCards #-}
+module Pattern.NestedWildcard where
+
+data A = A { b :: B, ai :: Int }
+data B = B { bi :: Int }
+
+h A { b = B {..}, .. } = bi + ai
+ examples/Pattern/OperatorPattern.hs view
@@ -0,0 +1,3 @@+module Pattern.OperatorPattern where
+
+child r (_:ps) = r ps
+ examples/Pattern/Record.hs view
@@ -0,0 +1,11 @@+{-# LANGUAGE NamedFieldPuns, RecordWildCards #-}
+module Pattern.Record where
+
+data Point = Point { x :: Int, y :: Int }
+
+f Point { x = 3, y = 1 } = 0
+f Point {} = 1
+
+g Point { x } = x
+
+h Point { x = 1, .. } = y
+ examples/Pattern/UnboxedSum.hs view
@@ -0,0 +1,6 @@+{-# LANGUAGE UnboxedSums #-}
+module Pattern.UnboxedSum where
+
+f :: (# Int | Bool #) -> ()
+f (# i | #) = ()
+f (# | b #) = ()
+ examples/TH/Brackets.hs view
@@ -0,0 +1,19 @@+{-# LANGUAGE TemplateHaskell #-}
+module TH.Brackets where
+
+import Language.Haskell.TH
+
+decls :: Q [Dec]
+decls = [d| w = 3 |]
+
+exp :: Q Exp
+exp = [| 3 |]
+
+exp' :: Q Exp
+exp' = [e| 3 |]
+
+pat :: Q Pat
+pat = [p| x |]
+
+typ :: Q Type
+typ = [t| Int |]
+ examples/TH/ClassUse.hs view
@@ -0,0 +1,10 @@+{-# LANGUAGE TemplateHaskell, FlexibleInstances #-}
+module TH.ClassUse where
+
+class C a where
+  f :: a -> a
+
+$([d|
+    instance C a where
+     f = id
+ |])
+ examples/TH/CrossDef.hs view
@@ -0,0 +1,4 @@+{-# LANGUAGE TemplateHaskell #-}
+module TH.CrossDef where
+
+$([d| x = 3 |])
+ examples/TH/DoubleSplice.hs view
@@ -0,0 +1,4 @@+{-# LANGUAGE TemplateHaskell #-}
+module TH.DoubleSplice where
+
+$($(id [| return [] |]))
+ examples/TH/GADTFields.hs view
@@ -0,0 +1,7 @@+{-# LANGUAGE GADTs, KindSignatures, TypeFamilies, TemplateHaskell #-}
+module TH.GADTFields where
+
+data Gadtrec1 a where
+  Gadtrecc1, Gadtrecc2 :: { gadtrec1a :: a, gadtrec1b :: b } -> Gadtrec1 (a,b)
+
+$( let a = ['gadtrec1a, 'gadtrec1b] in return [] )
+ examples/TH/LocalDefinition.hs view
@@ -0,0 +1,19 @@+{-# LANGUAGE TemplateHaskell #-}
+module TH.LocalDefinition where
+
+import Language.Haskell.TH
+
+decls :: Q [Dec]
+decls = [d| w = 3 |]
+
+exp :: Q Exp
+exp = [| 3 |]
+
+exp' :: Q Exp
+exp' = [e| 3 |]
+
+pat :: Q Pat
+pat = [p| x |]
+
+typ :: Q Type
+typ = [t| Int |]
+ examples/TH/MultiImport.hs view
@@ -0,0 +1,7 @@+{-# LANGUAGE TemplateHaskell #-}
+module TH.MultiImport where
+
+import Prelude (last,return)
+import qualified Data.Text (last)
+
+$(let f = last in return [])
+ examples/TH/NestedSplices.hs view
@@ -0,0 +1,6 @@+{-# LANGUAGE TemplateHaskell #-}
+module TH.NestedSplices where
+
+import Language.Haskell.TH
+
+f = [t| $(parensT [t| $(return ListT) |]) |]
+ examples/TH/QuasiQuote/Define.hs view
@@ -0,0 +1,8 @@+{-# OPTIONS_GHC -fno-warn-missing-fields #-}
+module TH.QuasiQuote.Define where
+
+import Language.Haskell.TH.Quote
+import Language.Haskell.TH
+
+expr :: QuasiQuoter
+expr = QuasiQuoter { quoteExp = const (return $ VarE $ mkName "hello") }
+ examples/TH/QuasiQuote/Use.hs view
@@ -0,0 +1,11 @@+{-# OPTIONS_GHC -fno-warn-missing-fields #-}
+{-# LANGUAGE QuasiQuotes #-}
+module TH.QuasiQuote.Use where
+
+import TH.QuasiQuote.Define
+
+hello :: Int
+hello = 3
+
+main :: IO ()
+main = print [expr| 1 + 2 + 4|]
+ examples/TH/Quoted.hs view
@@ -0,0 +1,6 @@+{-# LANGUAGE TemplateHaskell #-}
+module TH.Quoted where
+
+import qualified Text.Read.Lex (Lexeme)
+
+$(let x = ''Text.Read.Lex.Lexeme in return [])
+ examples/TH/Splice/Define.hs view
@@ -0,0 +1,24 @@+module TH.Splice.Define where
+
+import Language.Haskell.TH
+
+def :: String -> Q [Dec]
+def name = return [ ValD (VarP (mkName name)) (NormalB $ LitE $ IntegerL 3) [] ]
+
+defHello :: Q [Dec]
+defHello = def "hello"
+
+defHello2 :: Q [Dec]
+defHello2 = def "hello2"
+
+defHello3 :: Q [Dec]
+defHello3 = def "hello3"
+
+expr :: Q Exp
+expr = return $ LitE $ IntegerL 3
+
+typ :: Q Type
+typ = return $ TupleT 0
+
+nameOf :: Name -> Q [Dec]
+nameOf n = return []
+ examples/TH/Splice/Names.hs view
@@ -0,0 +1,12 @@+{-# LANGUAGE TemplateHaskell #-}
+module TH.Splice.Names where
+
+import TH.Splice.Define
+
+data A = A
+
+$(nameOf ''A)
+nameOf ''A
+
+$(nameOf 'A)
+nameOf 'A
+ examples/TH/Splice/Use.hs view
@@ -0,0 +1,22 @@+{-# LANGUAGE TemplateHaskell #-}
+module TH.Splice.Use where
+
+import TH.Splice.Define
+
+$(return [])
+
+$(let x = return [] in x)
+
+$(def "x")
+
+$(defHello)
+
+$defHello2
+
+defHello3
+
+a :: $typ
+a = ()
+
+e :: Int
+e = $expr
+ examples/TH/Splice/UseImported.hs view
@@ -0,0 +1,9 @@+{-# LANGUAGE TemplateHaskell #-}
+module TH.Splice.UseImported where
+
+data T a = T a
+
+$([d|
+  instance Show a => Show (T a) where show = undefined
+  instance (Eq a, Show a) => Eq (T a) where (==) = undefined
+  |])
+ examples/TH/Splice/UseQual.hs view
@@ -0,0 +1,6 @@+{-# LANGUAGE TemplateHaskell #-}
+module TH.Splice.UseQual where
+
+import qualified TH.Splice.Define as Def
+
+$(Def.def "x")
+ examples/TH/Splice/UseQualMulti.hs view
@@ -0,0 +1,8 @@+{-# LANGUAGE TemplateHaskell #-}
+module TH.Splice.UseQualMulti where
+
+import qualified TH.Splice.Define as Def
+import qualified TH.Splice.Define as Def2
+
+$(Def.def "x")
+$(Def2.def "y")
+ examples/TH/WithWildcards.hs view
@@ -0,0 +1,8 @@+{-# LANGUAGE TemplateHaskell, RecordWildCards #-}
+module TH.WithWildcards where
+
+import Language.Haskell.TH.Syntax
+
+data A = A { x :: Q Exp }
+
+g A{..} = [| $(x) |]
+ examples/Type/Bang.hs view
@@ -0,0 +1,4 @@+module Type.Bang where
+
+data X = X !Int
+
+ examples/Type/Builtin.hs view
@@ -0,0 +1,20 @@+{-# LANGUAGE MagicHash #-}
+module Type.Builtin where
+
+import GHC.Prim 
+import GHC.Base
+
+x1 :: IO ()
+x1 = undefined
+
+x2 :: IO Int
+x2 = return 2
+
+x3 :: Int
+x3 = I# x3'
+  where x3' :: Int#
+        x3' = 3#
+
+x4 :: (Int, Bool)
+x4 = (3,True)
+
+ examples/Type/Ctx.hs view
@@ -0,0 +1,10 @@+module Type.Ctx where
+
+sh :: Show a => a -> String
+sh = show
+
+sh' :: (Show a) => a -> String
+sh' = show
+
+sh'' :: (Show a, Eq a) => a -> String
+sh'' = show
+ examples/Type/ExplicitTypeApplication.hs view
@@ -0,0 +1,7 @@+{-# LANGUAGE TypeApplications #-}
+module Type.ExplicitTypeApplication where
+
+quad :: a -> b -> c -> d -> (a, b, c, d)
+quad w x y z = (w, x, y, z)
+
+foo = quad @Bool @_ @Int False 'c' 17 "Hello!"
+ examples/Type/Forall.hs view
@@ -0,0 +1,11 @@+{-# LANGUAGE ScopedTypeVariables #-}
+module Type.Forall where
+
+id :: forall a . a -> a
+id x = x
+
+id' :: a -> a
+id' x = x
+
+id'' :: forall a . Monoid a => a -> a
+id'' x = x
+ examples/Type/Primitives.hs view
@@ -0,0 +1,10 @@+{-# LANGUAGE MagicHash #-}
+module Type.Primitives where
+import GHC.Prim
+
+data MyInt = MyInt Int#
+
+my3 = MyInt 3#
+
+myPlus :: MyInt -> MyInt -> MyInt
+myPlus (MyInt i) (MyInt j) = MyInt (i +# j)
+ examples/Type/TupleAssert.hs view
@@ -0,0 +1,5 @@+{-# LANGUAGE ConstraintKinds #-}
+module Type.TupleAssert where
+
+f :: (Ord a, (Show a, Eq a)) => a -> String
+f = show
+ examples/Type/TypeOperators.hs view
@@ -0,0 +1,10 @@+{-# LANGUAGE TypeOperators #-}
+module Type.TypeOperators where
+
+infixr 6 :+:
+data a :+: r = a :+: r 
+
+type X = Int :+: Char :+: String
+
+type (:&:) = (,)
+infixr :&:
+ examples/Type/Unpack.hs view
@@ -0,0 +1,4 @@+module Type.Unpack where
+
+data X = X {-# UNPACK #-} !Int {-# NOUNPACK #-} !Int 
+
+ examples/Type/Wildcard.hs view
@@ -0,0 +1,7 @@+{-# OPTIONS_GHC -fno-warn-partial-type-signatures #-}
+{-# LANGUAGE PartialTypeSignatures #-}
+module Type.Wildcard where
+
+not' :: Bool -> _
+not' x = not x
+-- Inferred: Bool -> Bool
haskell-tools-refactor.cabal view
@@ -1,5 +1,5 @@ name:                haskell-tools-refactor
-version:             1.0.0.4
+version:             1.0.1.1
 synopsis:            Refactoring Tool for Haskell
 description:         Contains a set of refactorings based on the Haskell-Tools framework to easily transform a Haskell program. For the descriptions of the implemented refactorings, see the homepage.
 homepage:            https://github.com/haskell-tools/haskell-tools
@@ -11,23 +11,44 @@ build-type:          Simple
 cabal-version:       >=1.10
 
+extra-source-files: examples/CppHs/Language/Preprocessor/*.hs
+                  , examples/CppHs/Language/Preprocessor/Cpphs/*.hs
+                  , examples/CppHs/Language/Preprocessor/Cpphs/*.hs
+                  , examples/Decl/*.hs
+                  , examples/Expr/*.hs
+                  , examples/InstanceControl/Control/Instances/*.hs
+                  , examples/Module/*.hs
+                  , examples/Pattern/*.hs
+                  , examples/TH/*.hs
+                  , examples/CPP/*.hs
+                  , examples/TH/QuasiQuote/*.hs
+                  , examples/TH/Splice/*.hs
+                  , examples/Type/*.hs
+                  , examples/CommentHandling/*.hs
+
 library
   ghc-options: -O2
   exposed-modules:     Language.Haskell.Tools.Refactor
-                     , Language.Haskell.Tools.Refactor.Utils.BindingElem
-                     , Language.Haskell.Tools.Refactor.Utils.Monadic
                      , Language.Haskell.Tools.Refactor.Monad
-                     , Language.Haskell.Tools.Refactor.Representation
                      , Language.Haskell.Tools.Refactor.Prepare
-                     , Language.Haskell.Tools.Refactor.Utils.Lists
-                     , Language.Haskell.Tools.Refactor.Utils.Name
-                     , Language.Haskell.Tools.Refactor.Utils.Helpers
-                     , Language.Haskell.Tools.Refactor.Utils.AST
                      , Language.Haskell.Tools.Refactor.Refactoring
-                     , Language.Haskell.Tools.Refactor.Utils.Indentation
+                     , Language.Haskell.Tools.Refactor.Representation
+                     , Language.Haskell.Tools.Refactor.Utils.AST
+                     , Language.Haskell.Tools.Refactor.Utils.BindingElem
                      , Language.Haskell.Tools.Refactor.Utils.Extensions
+                     , Language.Haskell.Tools.Refactor.Utils.Helpers
+                     , Language.Haskell.Tools.Refactor.Utils.Indentation
+                     , Language.Haskell.Tools.Refactor.Utils.Lists
+                     , Language.Haskell.Tools.Refactor.Utils.Maybe
+                     , Language.Haskell.Tools.Refactor.Utils.Monadic
+                     , Language.Haskell.Tools.Refactor.Utils.Name
+                     , Language.Haskell.Tools.Refactor.Utils.Type
+                     , Language.Haskell.Tools.Refactor.Utils.NameLookup
+                     , Language.Haskell.Tools.Refactor.Utils.TypeLookup
+                     , Language.Haskell.Tools.Refactor.Querying
 
-  build-depends:       base                      >= 4.10  && < 4.11
+  build-depends:       base                      >= 4.10 && < 4.11
+                     , aeson                     >= 1.0  && < 1.4
                      , mtl                       >= 2.2  && < 2.3
                      , uniplate                  >= 1.6  && < 1.7
                      , ghc-paths                 >= 0.1  && < 0.2
@@ -39,9 +60,41 @@                      , filepath                  >= 1.4  && < 1.5
                      , template-haskell          >= 2.12 && < 2.13
                      , ghc                       >= 8.2  && < 8.3
-                     , Cabal                     >= 2.0 && < 2.1
+                     , Cabal                     >= 2.0  && < 2.3
                      , haskell-tools-ast         >= 1.0  && < 1.1
                      , haskell-tools-backend-ghc >= 1.0  && < 1.1
                      , haskell-tools-rewrite     >= 1.0  && < 1.1
                      , haskell-tools-prettyprint >= 1.0  && < 1.1
+  default-language:    Haskell2010
+
+test-suite haskell-tools-builtin-refactorings-test
+  type:                exitcode-stdio-1.0
+  ghc-options:         -with-rtsopts=-M2g
+  hs-source-dirs:      test
+  main-is:             Main.hs
+  build-depends:       base                      >= 4.10 && < 4.11
+                     , tasty                     >= 0.11 && < 0.12
+                     , tasty-hunit               >= 0.9  && < 0.10
+                     , transformers              >= 0.5  && < 0.6
+                     , either                    >= 4.4  && < 4.6
+                     , filepath                  >= 1.4  && < 1.5
+                     , mtl                       >= 2.2  && < 2.3
+                     , uniplate                  >= 1.6  && < 1.7
+                     , containers                >= 0.5  && < 0.6
+                     , directory                 >= 1.2  && < 1.4
+                     , references                >= 0.3  && < 0.4
+                     , split                     >= 0.2  && < 0.3
+                     , time                      >= 1.8  && < 1.9
+                     , template-haskell          >= 2.12 && < 2.13
+                     , ghc                       >= 8.2  && < 8.3
+                     , ghc-paths                 >= 0.1  && < 0.2
+                     , Cabal                     >= 2.0  && < 2.3
+                     , haskell-tools-ast         >= 1.0  && < 1.1
+                     , haskell-tools-backend-ghc >= 1.0  && < 1.1
+                     , haskell-tools-rewrite     >= 1.0  && < 1.1
+                     , haskell-tools-prettyprint >= 1.0  && < 1.1
+                     , haskell-tools-refactor
+                     -- libraries used by the examples
+                     , old-time                  >= 1.1  && < 1.2
+                     , polyparse                 >= 1.12 && < 1.13
   default-language:    Haskell2010
+ test/Main.hs view
@@ -0,0 +1,196 @@+{-# LANGUAGE LambdaCase, MonoLocalBinds #-}
+
+           
+module Main where
+
+import Test.Tasty (TestTree, testGroup, defaultMain)
+import Test.Tasty.HUnit
+
+import GHC hiding (loadModule, ParsedModule)
+import GHC.Paths ( libdir )
+
+import System.FilePath
+import System.IO
+
+import Language.Haskell.Tools.PrettyPrint (prettyPrint)
+import Language.Haskell.Tools.Refactor
+
+main :: IO ()
+main = defaultMain nightlyTests
+
+nightlyTests :: TestTree
+nightlyTests
+  = testGroup "all tests" [ testGroup "reprint tests" (map makeReprintTest languageTests)
+                          , testGroup "CppHs tests" $ map makeCpphsTest cppHsTests
+                          , testGroup "instance-control tests" $ map makeInstanceControlTest instanceControlTests
+                          ]
+
+makeReprintTest :: String -> TestTree
+makeReprintTest mod = testCase mod (checkCorrectlyPrinted rootDir mod)
+
+makeCpphsTest :: String -> TestTree
+makeCpphsTest mod = testCase mod (checkCorrectlyPrinted (rootDir </> "CppHs") mod)
+
+makeInstanceControlTest :: String -> TestTree
+makeInstanceControlTest mod = testCase mod (checkCorrectlyPrinted (rootDir </> "InstanceControl") mod)
+
+checkCorrectlyPrinted :: String -> String -> IO ()
+checkCorrectlyPrinted workingDir moduleName
+  = do -- need to use binary or line endings will be translated
+       expectedHandle <- openBinaryFile (workingDir </> map (\case '.' -> pathSeparator; c -> c) moduleName ++ ".hs") ReadMode
+       expected <- hGetContents expectedHandle
+       actual <- runGhc (Just libdir) $ do
+         parsed <- loadModule workingDir moduleName
+         prettyPrint <$> parseTyped parsed
+       assertEqual "The original and the transformed source differ" expected actual
+
+
+rootDir = "examples"
+
+cppHsTests =
+  [ "Language.Preprocessor.Cpphs"
+  , "Language.Preprocessor.Unlit"
+  , "Language.Preprocessor.Cpphs.CppIfdef"
+  , "Language.Preprocessor.Cpphs.HashDefine"
+  , "Language.Preprocessor.Cpphs.MacroPass"
+  , "Language.Preprocessor.Cpphs.Options"
+  , "Language.Preprocessor.Cpphs.Position"
+  , "Language.Preprocessor.Cpphs.ReadFirst"
+  , "Language.Preprocessor.Cpphs.RunCpphs"
+  , "Language.Preprocessor.Cpphs.SymTab"
+  , "Language.Preprocessor.Cpphs.Tokenise"
+  ]
+
+instanceControlTests =
+  [ "Control.Instances.Test"
+  , "Control.Instances.Morph"
+  , "Control.Instances.ShortestPath"
+  , "Control.Instances.TypeLevelPrelude"
+  ]
+
+languageTests =
+  [ "CPP.JustEnabled"
+  , "CPP.ConditionalCode"
+  , "Decl.AmbiguousFields"
+  , "Decl.AnnPragma"
+  , "Decl.ClassInfix"
+  , "Decl.ClosedTypeFamily"
+  , "Decl.CompletePragma"
+  , "Decl.CtorOp"
+  , "Decl.DataFamily"
+  , "Decl.DataType"
+  , "Decl.DataInstanceGADT"
+  , "Decl.DataTypeDerivings"
+  , "Decl.DefaultDecl"
+  , "Decl.FunBind"
+  , "Decl.FunctionalDeps"
+  , "Decl.FunGuards"
+  , "Decl.GADT"
+  , "Decl.GadtConWithCtx"
+  , "Decl.InfixAssertion"
+  , "Decl.InfixInstances"
+  , "Decl.InfixPatSyn"
+  , "Decl.InjectiveTypeFamily"
+  , "Decl.InlinePragma"
+  , "Decl.InstanceFamily"
+  , "Decl.InstanceOverlaps"
+  , "Decl.InstanceSpec"
+  , "Decl.LocalBindings"
+  , "Decl.LocalBindingInDo"
+  , "Decl.LocalFixity"
+  , "Decl.MinimalPragma"
+  , "Decl.MultipleFixity"
+  , "Decl.MultipleSigs"
+  , "Decl.OperatorBind"
+  , "Decl.OperatorDecl"
+  , "Decl.ParamDataType"
+  , "Decl.PatternBind"
+  , "Decl.PatternSynonym"
+  , "Decl.RecordPatternSynonyms"
+  , "Decl.RecordType"
+  , "Decl.RewriteRule"
+  , "Decl.SpecializePragma"
+  , "Decl.StandaloneDeriving"
+  , "Decl.TypeClass"
+  , "Decl.TypeClassMinimal"
+  , "Decl.TypeFamily"
+  , "Decl.TypeFamilyKindSig"
+  , "Decl.TypeInstance"
+  , "Decl.TypeRole"
+  , "Decl.TypeSynonym"
+  , "Decl.ValBind"
+  , "Decl.ViewPatternSynonym"
+  , "Expr.ArrowNotation"
+  , "Expr.Case"
+  , "Expr.DoNotation"
+  , "Expr.GeneralizedListComp"
+  , "Expr.EmptyCase"
+  , "Expr.FunSection"
+  , "Expr.If"
+  , "Expr.LambdaCase"
+  , "Expr.ListComp"
+  , "Expr.MultiwayIf"
+  , "Expr.Negate"
+  , "Expr.Operator"
+  , "Expr.ParenName"
+  , "Expr.ParListComp"
+  , "Expr.PatternAndDo"
+  , "Expr.RecordPuns"
+  , "Expr.RecordWildcards"
+  , "Expr.RecursiveDo"
+  , "Expr.Sections"
+  , "Expr.SemicolonDo"
+  , "Expr.StaticPtr"
+  , "Expr.TupleSections"
+  , "Expr.UnboxedSum"
+  , "Module.Simple"
+  , "Module.GhcOptionsPragma"
+  , "Module.Export"
+  , "Module.ExportSubs"
+  , "Module.ExportModifiers"
+  , "Module.NamespaceExport"
+  , "Module.Import"
+  , "Module.ImportOp"
+  , "Module.LangPragmas"
+  , "Module.PatternImport"
+  , "Pattern.Backtick"
+  , "Pattern.Constructor"
+  -- , "Pattern.ImplicitParams"
+  , "Pattern.Infix"
+  , "Pattern.NestedWildcard"
+  , "Pattern.NPlusK"
+  , "Pattern.OperatorPattern"
+  , "Pattern.Record"
+  , "Pattern.UnboxedSum"
+  , "Type.Bang"
+  , "Type.Builtin"
+  , "Type.Ctx"
+  , "Type.ExplicitTypeApplication"
+  , "Type.Forall"
+  , "Type.Primitives"
+  , "Type.TupleAssert"
+  , "Type.TypeOperators"
+  , "Type.Unpack"
+  , "Type.Wildcard"
+  , "TH.Brackets"
+  , "TH.QuasiQuote.Define"
+  , "TH.QuasiQuote.Use"
+  , "TH.Splice.Define"
+  , "TH.Splice.Use"
+  , "TH.CrossDef"
+  , "TH.ClassUse"
+  , "TH.Splice.UseImported"
+  , "TH.Splice.UseQual"
+  , "TH.Splice.UseQualMulti"
+  , "TH.LocalDefinition"
+  , "TH.MultiImport"
+  , "TH.NestedSplices"
+  , "TH.Quoted"
+  , "TH.WithWildcards"
+  , "TH.DoubleSplice"
+  , "TH.GADTFields"
+  , "CommentHandling.CommentTypes"
+  , "CommentHandling.BlockComments"
+  , "CommentHandling.Crosslinking"
+  , "CommentHandling.FunctionArgs"
+  ]