{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE OverloadedStrings #-} ----------------------------------------------------------------------------- -- | -- Module : Language.Haskell.Extension -- Copyright : Isaac Jones 2003-2004 -- License : BSD3 -- -- Maintainer : libraries@haskell.org -- Portability : portable -- -- Haskell language dialects and extensions module Language.Haskell.Extension ( Language (..) , knownLanguages , classifyLanguage , Extension (..) , KnownExtension (..) , deprecatedExtensions , classifyExtension , knownExtensions ) where import Distribution.Compat.Prelude import Data.Array (Array, Ix (inRange), accumArray, bounds, (!)) import Distribution.Parsec import Distribution.Pretty import qualified Distribution.Compat.CharParsing as P import qualified Text.PrettyPrint as Disp -- ------------------------------------------------------------ -- * Language -- ------------------------------------------------------------ -- | This represents a Haskell language dialect. -- -- Language 'Extension's are interpreted relative to one of these base -- languages. data Language = -- | The Haskell 98 language as defined by the Haskell 98 report. -- Haskell98 | -- | The Haskell 2010 language as defined by the Haskell 2010 report. -- Haskell2010 | -- | The GHC2021 collection of language extensions. -- GHC2021 | -- | The GHC2024 collection of language extensions. -- GHC2024 | -- | An unknown language, identified by its name. UnknownLanguage String deriving (Generic, Show, Read, Eq, Ord, Typeable, Data) instance Binary Language instance Structured Language instance NFData Language where rnf = genericRnf -- | List of known (supported) languages for GHC, oldest first. knownLanguages :: [Language] knownLanguages = [Haskell98, Haskell2010, GHC2021, GHC2024] instance Pretty Language where pretty (UnknownLanguage other) = Disp.text other pretty other = Disp.text (show other) instance Parsec Language where parsec = classifyLanguage <$> P.munch1 isAlphaNum classifyLanguage :: String -> Language classifyLanguage = \str -> case lookup str langTable of Just lang -> lang Nothing -> UnknownLanguage str where langTable = [ (show lang, lang) | lang <- knownLanguages ] -- ------------------------------------------------------------ -- * Extension -- ------------------------------------------------------------ -- Note: if you add a new 'KnownExtension': -- -- * also add it to the Distribution.Simple.X.compilerExtensions lists -- (where X is each compiler: GHC, UHC, HaskellSuite) -- -- | This represents language extensions beyond a base 'Language' definition -- (such as 'Haskell98') that are supported by some implementations, usually -- in some special mode. -- -- Where applicable, references are given to an implementation's -- official documentation. data Extension = -- | Enable a known extension EnableExtension KnownExtension | -- | Disable a known extension DisableExtension KnownExtension | -- | An unknown extension, identified by the name of its @LANGUAGE@ -- pragma. UnknownExtension String deriving (Generic, Show, Read, Eq, Ord, Typeable, Data) instance Binary Extension instance Structured Extension instance NFData Extension where rnf = genericRnf -- | Known Haskell language extensions, including deprecated and undocumented -- ones. -- -- Check -- for more information. data KnownExtension = -- | Allow overlapping class instances, provided there is a unique -- most specific instance for each use. OverlappingInstances | -- | Ignore structural rules guaranteeing the termination of class -- instance resolution. Termination is guaranteed by a fixed-depth -- recursion stack, and compilation may fail if this depth is -- exceeded. UndecidableInstances | -- | Implies 'OverlappingInstances'. Allow the implementation to -- choose an instance even when it is possible that further -- instantiation of types will lead to a more specific instance -- being applicable. IncoherentInstances | -- | /(deprecated)/ Deprecated in favour of 'RecursiveDo'. -- -- Old description: Allow recursive bindings in @do@ blocks, using -- the @rec@ keyword. See also 'RecursiveDo'. DoRec | -- | Allow recursive bindings in @do@ blocks, using the @rec@ -- keyword, or @mdo@, a variant of @do@. RecursiveDo | -- | Provide syntax for writing list comprehensions which iterate -- over several lists together, like the 'zipWith' family of -- functions. ParallelListComp | -- | Allow multiple parameters in a type class. MultiParamTypeClasses | -- | Enable the dreaded monomorphism restriction. MonomorphismRestriction | -- | Enable deep subsumption, relaxing the simple subsumption rules, -- implicitly inserting eta-expansions when matching up function types -- with different quantification structures. DeepSubsumption | -- | Allow a specification attached to a multi-parameter type class -- which indicates that some parameters are entirely determined by -- others. The implementation will check that this property holds -- for the declared instances, and will use this property to reduce -- ambiguity in instance resolution. FunctionalDependencies | -- | /(deprecated)/ A synonym for 'RankNTypes'. -- -- Old description: Like 'RankNTypes' but does not allow a -- higher-rank type to itself appear on the left of a function -- arrow. Rank2Types | -- | Allow a universally-quantified type to occur on the left of a -- function arrow. RankNTypes | -- | /(deprecated)/ A synonym for 'RankNTypes'. -- -- Old description: Allow data constructors to have polymorphic -- arguments. Unlike 'RankNTypes', does not allow this for ordinary -- functions. PolymorphicComponents | -- | Allow existentially-quantified data constructors. ExistentialQuantification | -- | Cause a type variable in a signature, which has an explicit -- @forall@ quantifier, to scope over the definition of the -- accompanying value declaration. ScopedTypeVariables | -- | Deprecated, use 'ScopedTypeVariables' instead. PatternSignatures | -- | Enable implicit function parameters with dynamic scope. ImplicitParams | -- | Relax some restrictions on the form of the context of a type -- signature. FlexibleContexts | -- | Relax some restrictions on the form of the context of an -- instance declaration. FlexibleInstances | -- | Allow data type declarations with no constructors. EmptyDataDecls | -- | Run the C preprocessor on Haskell source code. CPP | -- | Allow an explicit kind signature giving the kind of types over -- which a type variable ranges. KindSignatures | -- | Enable a form of pattern which forces evaluation before an -- attempted match, and a form of strict @let@/@where@ binding. BangPatterns | -- | Allow type synonyms in instance heads. TypeSynonymInstances | -- | Enable Template Haskell, a system for compile-time -- metaprogramming. TemplateHaskell | -- | Enable the Foreign Function Interface. In GHC, implements the -- standard Haskell 98 Foreign Function Interface Addendum, plus -- some GHC-specific extensions. ForeignFunctionInterface | -- | Enable arrow notation. Arrows | -- | /(deprecated)/ Enable generic type classes, with default instances defined in -- terms of the algebraic structure of a type. Generics | -- | Enable the implicit importing of the module "Prelude". When -- disabled, when desugaring certain built-in syntax into ordinary -- identifiers, use whatever is in scope rather than the "Prelude" -- -- version. ImplicitPrelude | -- | Enable syntax for implicitly binding local names corresponding -- to the field names of a record. Puns bind specific names, unlike -- 'RecordWildCards'. NamedFieldPuns | -- | Enable a form of guard which matches a pattern and binds -- variables. PatternGuards | -- | Allow a type declared with @newtype@ to use @deriving@ for any -- class with an instance for the underlying type. GeneralizedNewtypeDeriving | -- Synonym for GeneralizedNewtypeDeriving added in GHC 8.6.1. GeneralisedNewtypeDeriving | -- | Enable the \"Trex\" extensible records system. ExtensibleRecords | -- | Enable type synonyms which are transparent in some definitions -- and opaque elsewhere, as a way of implementing abstract -- datatypes. RestrictedTypeSynonyms | -- | Enable an alternate syntax for string literals, -- with string templating. HereDocuments | -- | Allow the character @#@ as a postfix modifier on identifiers. -- Also enables literal syntax for unboxed values. MagicHash | -- | Allow data types and type synonyms which are indexed by types, -- i.e. ad-hoc polymorphism for types. TypeFamilies | -- | Allow a standalone declaration which invokes the type class -- @deriving@ mechanism. StandaloneDeriving | -- | Allow certain Unicode characters to stand for certain ASCII -- character sequences, e.g. keywords and punctuation. UnicodeSyntax | -- | Allow the use of unboxed types as foreign types, e.g. in -- @foreign import@ and @foreign export@. UnliftedFFITypes | -- | Enable interruptible FFI. InterruptibleFFI | -- | Allow use of CAPI FFI calling convention (@foreign import capi@). CApiFFI | -- | Defer validity checking of types until after expanding type -- synonyms, relaxing the constraints on how synonyms may be used. LiberalTypeSynonyms | -- | Allow the name of a type constructor, type class, or type -- variable to be an infix operator. TypeOperators | -- | Enable syntax for implicitly binding local names corresponding -- to the field names of a record. A wildcard binds all unmentioned -- names, unlike 'NamedFieldPuns'. RecordWildCards | -- | Deprecated, use 'NamedFieldPuns' instead. RecordPuns | -- | Allow a record field name to be disambiguated by the type of -- the record it's in. DisambiguateRecordFields | -- | Enable traditional record syntax (as supported by Haskell 98) TraditionalRecordSyntax | -- | Enable overloading of string literals using a type class, much -- like integer literals. OverloadedStrings | -- | Enable generalized algebraic data types, in which type -- variables may be instantiated on a per-constructor basis. Implies -- 'GADTSyntax'. GADTs | -- | Enable GADT syntax for declaring ordinary algebraic datatypes. GADTSyntax | -- | /(deprecated)/ Has no effect. -- -- Old description: Make pattern bindings monomorphic. MonoPatBinds | -- | Relax the requirements on mutually-recursive polymorphic -- functions. RelaxedPolyRec | -- | Allow default instantiation of polymorphic types in more -- situations. ExtendedDefaultRules | -- | Enable unboxed tuples. UnboxedTuples | -- | Enable @deriving@ for classes 'Data.Typeable.Typeable' and -- 'Data.Generics.Data'. DeriveDataTypeable | -- | Enable @deriving@ for 'GHC.Generics.Generic' and 'GHC.Generics.Generic1'. DeriveGeneric | -- | Enable support for default signatures. DefaultSignatures | -- | Allow type signatures to be specified in instance declarations. InstanceSigs | -- | Allow a class method's type to place additional constraints on -- a class type variable. ConstrainedClassMethods | -- | Allow imports to be qualified by the package name the module is -- intended to be imported from, e.g. -- -- > import "network" Network.Socket PackageImports | -- | /(deprecated)/ Allow a type variable to be instantiated at a -- polymorphic type. ImpredicativeTypes | -- | /(deprecated)/ Change the syntax for qualified infix operators. NewQualifiedOperators | -- | Relax the interpretation of left operator sections to allow -- unary postfix operators. PostfixOperators | -- | Enable quasi-quotation, a mechanism for defining new concrete -- syntax for expressions and patterns. QuasiQuotes | -- | Enable generalized list comprehensions, supporting operations -- such as sorting and grouping. TransformListComp | -- | Enable monad comprehensions, which generalise the list -- comprehension syntax to work for any monad. MonadComprehensions | -- | Enable view patterns, which match a value by applying a -- function and matching on the result. ViewPatterns | -- | Allow concrete XML syntax to be used in expressions and patterns, -- as per the Haskell Server Pages extension language: -- . The ideas behind it are -- discussed in the paper \"Haskell Server Pages through Dynamic Loading\" -- by Niklas Broberg, from Haskell Workshop '05. XmlSyntax | -- | Allow regular pattern matching over lists, as discussed in the -- paper \"Regular Expression Patterns\" by Niklas Broberg, Andreas Farre -- and Josef Svenningsson, from ICFP '04. RegularPatterns | -- | Enable the use of tuple sections, e.g. @(, True)@ desugars into -- @\x -> (x, True)@. TupleSections | -- | Allow GHC primops, written in C--, to be imported into a Haskell -- file. GHCForeignImportPrim | -- | Support for patterns of the form @n + k@, where @k@ is an -- integer literal. NPlusKPatterns | -- | Improve the layout rule when @if@ expressions are used in a @do@ -- block. DoAndIfThenElse | -- | Enable support for multi-way @if@-expressions. MultiWayIf | -- | Enable support lambda-@case@ expressions. LambdaCase | -- | Makes much of the Haskell sugar be desugared into calls to the -- function with a particular name that is in scope. RebindableSyntax | -- | Make @forall@ a keyword in types, which can be used to give the -- generalisation explicitly. ExplicitForAll | -- | Allow contexts to be put on datatypes, e.g. the @Eq a@ in -- @data Eq a => Set a = NilSet | ConsSet a (Set a)@. DatatypeContexts | -- | Local (@let@ and @where@) bindings are monomorphic. MonoLocalBinds | -- | Enable @deriving@ for the 'Data.Functor.Functor' class. DeriveFunctor | -- | Enable @deriving@ for the 'Data.Traversable.Traversable' class. DeriveTraversable | -- | Enable @deriving@ for the 'Data.Foldable.Foldable' class. DeriveFoldable | -- | Enable non-decreasing indentation for @do@ blocks. NondecreasingIndentation | -- | Allow imports to be qualified with a safe keyword that requires -- the imported module be trusted as according to the Safe Haskell -- definition of trust. -- -- > import safe Network.Socket SafeImports | -- | Compile a module in the Safe, Safe Haskell mode -- a restricted -- form of the Haskell language to ensure type safety. Safe | -- | Compile a module in the Trustworthy, Safe Haskell mode -- no -- restrictions apply but the module is marked as trusted as long as -- the package the module resides in is trusted. Trustworthy | -- | Compile a module in the Unsafe, Safe Haskell mode so that -- modules compiled using Safe, Safe Haskell mode can't import it. Unsafe | -- | Allow type class/implicit parameter/equality constraints to be -- used as types with the special kind constraint. Also generalise -- the @(ctxt => ty)@ syntax so that any type of kind constraint can -- occur before the arrow. ConstraintKinds | -- | Enable kind polymorphism. PolyKinds | -- | Enable datatype promotion. DataKinds | -- | Enable @type data@ declarations, defining constructors at the type level. TypeData | -- | Enable parallel arrays syntax (@[:@, @:]@) for /Data Parallel Haskell/. ParallelArrays | -- | Enable explicit role annotations, like in (@type role Foo representational representational@). RoleAnnotations | -- | Enable overloading of list literals, arithmetic sequences and -- list patterns using the 'IsList' type class. OverloadedLists | -- | Enable case expressions that have no alternatives. Also applies to lambda-case expressions if they are enabled. EmptyCase | -- | /(deprecated)/ Deprecated in favour of 'DeriveDataTypeable'. -- -- Old description: Triggers the generation of derived 'Typeable' -- instances for every datatype and type class declaration. AutoDeriveTypeable | -- | Desugars negative literals directly (without using negate). NegativeLiterals | -- | Allow the use of binary integer literal syntax (e.g. @0b11001001@ to denote @201@). BinaryLiterals | -- | Allow the use of floating literal syntax for all instances of 'Num', including 'Int' and 'Integer'. NumDecimals | -- | Enable support for type classes with no type parameter. NullaryTypeClasses | -- | Enable explicit namespaces in module import/export lists. ExplicitNamespaces | -- | Allow the user to write ambiguous types, and the type inference engine to infer them. AllowAmbiguousTypes | -- | Enable @foreign import javascript@. JavaScriptFFI | -- | Allow giving names to and abstracting over patterns. PatternSynonyms | -- | Allow anonymous placeholders (underscore) inside type signatures. The -- type inference engine will generate a message describing the type inferred -- at the hole's location. PartialTypeSignatures | -- | Allow named placeholders written with a leading underscore inside type -- signatures. Wildcards with the same name unify to the same type. NamedWildCards | -- | Enable @deriving@ for any class. DeriveAnyClass | -- | Enable @deriving@ for the 'Language.Haskell.TH.Syntax.Lift' class. DeriveLift | -- | Enable support for 'static pointers' (and the @static@ -- keyword) to refer to globally stable names, even across -- different programs. StaticPointers | -- | Switches data type declarations to be strict by default (as if -- they had a bang using @BangPatterns@), and allow opt-in field -- laziness using @~@. StrictData | -- | Switches all pattern bindings to be strict by default (as if -- they had a bang using @BangPatterns@), ordinary patterns are -- recovered using @~@. Implies @StrictData@. Strict | -- | Allows @do@-notation for types that are @'Applicative'@ as well -- as @'Monad'@. When enabled, desugaring @do@ notation tries to use -- @(<*>)@ and @'fmap'@ and @'join'@ as far as possible. ApplicativeDo | -- | Allow records to use duplicated field labels for accessors. DuplicateRecordFields | -- | Enable explicit type applications with the syntax @id \@Int@. TypeApplications | -- | Dissolve the distinction between types and kinds, allowing the compiler -- to reason about kind equality and therefore enabling GADTs to be promoted -- to the type-level. TypeInType | -- | Allow recursive (and therefore undecidable) super-class relationships. UndecidableSuperClasses | -- | A temporary extension to help library authors check if their -- code will compile with the new planned desugaring of fail. MonadFailDesugaring | -- | A subset of @TemplateHaskell@ including only quoting. TemplateHaskellQuotes | -- | Allows use of the @#label@ syntax. OverloadedLabels | -- | Allow functional dependency annotations on type families to declare them -- as injective. TypeFamilyDependencies | -- | Allow multiple @deriving@ clauses, each optionally qualified with a -- /strategy/. DerivingStrategies | -- | Enable deriving instances via types of the same runtime representation. -- Implies 'DerivingStrategies'. DerivingVia | -- | Enable the use of unboxed sum syntax. UnboxedSums | -- | Allow use of hexadecimal literal notation for floating-point values. HexFloatLiterals | -- | Allow @do@ blocks etc. in argument position. BlockArguments | -- | Allow use of underscores in numeric literals. NumericUnderscores | -- | Allow @forall@ in constraints. QuantifiedConstraints | -- | Have @*@ refer to @Type@. StarIsType | -- | Liberalises deriving to provide instances for empty data types. EmptyDataDeriving | -- | Enable detection of complete user-supplied kind signatures. CUSKs | -- | Allows the syntax @import M qualified@. ImportQualifiedPost | -- | Allow the use of standalone kind signatures. StandaloneKindSignatures | -- | Enable unlifted newtypes. UnliftedNewtypes | -- | Use whitespace to determine whether the minus sign stands for negation or subtraction. LexicalNegation | -- | Enable qualified do-notation desugaring. QualifiedDo | -- | Enable linear types. LinearTypes | -- | Allow the use of visible forall in types of terms. RequiredTypeArguments | -- | Enable the generation of selector functions corresponding to record fields. FieldSelectors | -- | Enable the use of record dot-accessor and updater syntax OverloadedRecordDot | -- | Provides record @.@ syntax in record updates, e.g. @x {foo.bar = 1}@. OverloadedRecordUpdate | -- | Enable data types for which an unlifted or levity-polymorphic result kind is inferred. UnliftedDatatypes | -- | Enable syntax for primitive numeric literals, e.g. @3#Int8@ ExtendedLiterals | -- | Undocumented parsing-related extensions introduced in GHC 7.0. AlternativeLayoutRule | -- | Undocumented parsing-related extensions introduced in GHC 7.0. AlternativeLayoutRuleTransitional | -- | Undocumented parsing-related extensions introduced in GHC 7.2. RelaxedLayout | -- | Allow the use of type abstraction syntax. TypeAbstractions | -- | Allow the use of built-in syntax for list, tuple and sum type constructors -- rather than being exclusive to data constructors. ListTuplePuns deriving (Generic, Show, Read, Eq, Ord, Enum, Bounded, Typeable, Data) instance Binary KnownExtension instance Structured KnownExtension instance NFData KnownExtension where rnf = genericRnf -- | Extensions that have been deprecated, possibly paired with another -- extension that replaces it. deprecatedExtensions :: [(Extension, Maybe Extension)] deprecatedExtensions = [ (EnableExtension RecordPuns, Just (EnableExtension NamedFieldPuns)) , (EnableExtension PatternSignatures, Just (EnableExtension ScopedTypeVariables)) ] -- NOTE: when adding deprecated extensions that have new alternatives -- we must be careful to make sure that the deprecation messages are -- valid. We must not recommend aliases that cannot be used with older -- compilers, perhaps by adding support in Cabal to translate the new -- name to the old one for older compilers. Otherwise we are in danger -- of the scenario in ticket #689. instance Pretty Extension where pretty (UnknownExtension other) = Disp.text other pretty (EnableExtension ke) = Disp.text (show ke) pretty (DisableExtension ke) = Disp.text ("No" ++ show ke) instance Parsec Extension where parsec = classifyExtension <$> P.munch1 isAlphaNum instance Pretty KnownExtension where pretty ke = Disp.text (show ke) classifyExtension :: String -> Extension classifyExtension string = case classifyKnownExtension string of Just ext -> EnableExtension ext Nothing -> case string of 'N' : 'o' : string' -> case classifyKnownExtension string' of Just ext -> DisableExtension ext Nothing -> UnknownExtension string _ -> UnknownExtension string -- | 'read' for 'KnownExtension's is really really slow so for the Text -- instance -- what we do is make a simple table indexed off the first letter in the -- extension name. The extension names actually cover the range @'A'-'Z'@ -- pretty densely and the biggest bucket is 7 so it's not too bad. We just do -- a linear search within each bucket. -- -- This gives an order of magnitude improvement in parsing speed, and it'll -- also allow us to do case insensitive matches in future if we prefer. classifyKnownExtension :: String -> Maybe KnownExtension classifyKnownExtension "" = Nothing classifyKnownExtension string@(c : _) | inRange (bounds knownExtensionTable) c = lookup string (knownExtensionTable ! c) | otherwise = Nothing knownExtensionTable :: Array Char [(String, KnownExtension)] knownExtensionTable = accumArray (flip (:)) [] ('A', 'Z') [ (hd, (str, extension)) -- assume KnownExtension's Show returns a non-empty string | (extension, str@(hd : _)) <- map (\e -> (e, show e)) [toEnum 0 ..] ] knownExtensions :: [KnownExtension] knownExtensions = [minBound .. maxBound]