module Language.Haskell.Exts.Extension (
    
    Extension(..), classifyExtension, impliesExts,
    
    glasgowExts, knownExtensions
    ) where
data Extension
  = OverlappingInstances
  | UndecidableInstances
  | IncoherentInstances
  | RecursiveDo
  | ParallelListComp
  | MultiParamTypeClasses
  | NoMonomorphismRestriction
  | FunctionalDependencies
  | ExplicitForall
  | Rank2Types
  | RankNTypes
  | PolymorphicComponents
  | ExistentialQuantification
  | ScopedTypeVariables
  | ImplicitParams
  | FlexibleContexts
  | FlexibleInstances
  | EmptyDataDecls
  | CPP
  | KindSignatures
  | BangPatterns
  | TypeSynonymInstances
  | TemplateHaskell
  | ForeignFunctionInterface
  | Arrows
  | Generics
  | NoImplicitPrelude
  | NamedFieldPuns
  | PatternGuards
  | GeneralizedNewtypeDeriving
  | ExtensibleRecords
  | RestrictedTypeSynonyms
  | HereDocuments
  | MagicHash
  | TypeFamilies
  | StandaloneDeriving
  | UnicodeSyntax
  | PatternSignatures
  | UnliftedFFITypes
  | LiberalTypeSynonyms
  | TypeOperators
  | RecordWildCards
  | RecordPuns 
  | DisambiguateRecordFields
  | OverloadedStrings
  | GADTs
  | MonoPatBinds
  | NoMonoPatBinds 
  | RelaxedPolyRec
  | ExtendedDefaultRules
  | UnboxedTuples
  | DeriveDataTypeable
  | ConstrainedClassMethods
  | PackageImports
  | ImpredicativeTypes
  | NewQualifiedOperators
  | PostfixOperators
  | QuasiQuotes
  | TransformListComp
  | ViewPatterns
  | XmlSyntax
  | RegularPatterns
  | TupleSections
  | UnknownExtension String
  deriving (Eq, Ord, Show, Read)
impliesExts :: [Extension] -> [Extension]
impliesExts = go
  where go [] = []
        go es = let xs = concatMap implE es
                    ys = filter (not . flip elem es) xs
                 in es ++ go ys
        implE e = case e of
                    TypeFamilies        -> [KindSignatures]
                    ScopedTypeVariables -> [TypeOperators, ExplicitForall]
                    XmlSyntax           -> [RegularPatterns]
                    RegularPatterns     -> [PatternGuards]
                    RankNTypes          -> [Rank2Types]
                    Rank2Types          -> [PolymorphicComponents]
                    PolymorphicComponents   -> [ExplicitForall]
                    LiberalTypeSynonyms -> [ExplicitForall]
                    
                    RecordPuns          -> [NamedFieldPuns]
                    PatternSignatures   -> [ScopedTypeVariables]
                    e                   -> []
glasgowExts :: [Extension]
glasgowExts = [
      ForeignFunctionInterface
    , UnliftedFFITypes
    , GADTs
    , ImplicitParams
    , ScopedTypeVariables
    , UnboxedTuples
    , TypeSynonymInstances
    , StandaloneDeriving
    , DeriveDataTypeable
    , FlexibleContexts
    , FlexibleInstances
    , ConstrainedClassMethods
    , MultiParamTypeClasses
    , FunctionalDependencies
    , MagicHash
    , PolymorphicComponents
    , ExistentialQuantification
    , UnicodeSyntax
    , PostfixOperators
    , PatternGuards
    , LiberalTypeSynonyms
    , RankNTypes
    , ImpredicativeTypes
    , TypeOperators
    , RecursiveDo
    , ParallelListComp
    , EmptyDataDecls
    , KindSignatures
    , GeneralizedNewtypeDeriving
    , TypeFamilies
    ]
knownExtensions :: [Extension]
knownExtensions = 
    [ OverlappingInstances
    , UndecidableInstances
    , IncoherentInstances
    , RecursiveDo
    , ParallelListComp
    , MultiParamTypeClasses
    , NoMonomorphismRestriction
    , FunctionalDependencies
    , ExplicitForall
    , Rank2Types
    , RankNTypes
    , PolymorphicComponents
    , ExistentialQuantification
    , ScopedTypeVariables
    , ImplicitParams
    , FlexibleContexts
    , FlexibleInstances
    , EmptyDataDecls
    , CPP
    , KindSignatures
    , BangPatterns
    , TypeSynonymInstances
    , TemplateHaskell
    , ForeignFunctionInterface
    , Arrows
    , Generics
    , NoImplicitPrelude
    , NamedFieldPuns
    , PatternGuards
    , GeneralizedNewtypeDeriving
    , ExtensibleRecords
    , RestrictedTypeSynonyms
    , HereDocuments
    , MagicHash
    , TypeFamilies
    , StandaloneDeriving
    , UnicodeSyntax
    , PatternSignatures
    , UnliftedFFITypes
    , LiberalTypeSynonyms
    , TypeOperators
    , RecordWildCards
    , RecordPuns 
    , DisambiguateRecordFields
    , OverloadedStrings
    , GADTs
    , MonoPatBinds
    , NoMonoPatBinds 
    , RelaxedPolyRec
    , ExtendedDefaultRules
    , UnboxedTuples
    , DeriveDataTypeable
    , ConstrainedClassMethods
    , PackageImports
    , ImpredicativeTypes
    , NewQualifiedOperators
    , PostfixOperators
    , QuasiQuotes
    , TransformListComp
    , ViewPatterns
    , XmlSyntax
    , RegularPatterns
    , TupleSections
    ]
classifyExtension :: String -> Extension
classifyExtension str
  = case readsPrec 0 str of
      [(e,"")]     -> e
      _            -> UnknownExtension str