    {-# LANGUAGE CPP, DeriveDataTypeable #-}
    -----------------------------------------------------------------------------
    -- |
    -- Module      :  Language.Haskell.Exts.Syntax
    -- Copyright   :  (c) Niklas Broberg 2004-2009,
    --                (c) The GHC Team, 1997-2000
    -- License     :  BSD-style (see the file LICENSE.txt)
    --
    -- Maintainer  :  Niklas Broberg, d00nibro@chalmers.se
    -- Stability   :  stable
    -- Portability :  portable
    --
    -- A suite of datatypes describing the abstract syntax of Haskell 98
    -- <http://www.haskell.org/onlinereport/> plus registered extensions, including:
    --
    --   * multi-parameter type classes with functional dependencies (MultiParamTypeClasses, FunctionalDependencies)
    --
    --   * parameters of type class assertions are unrestricted (FlexibleContexts)
    --
    --   * 'forall' types as universal and existential quantification (RankNTypes, ExistentialQuantification, etc)
    --
    --   * pattern guards (PatternGuards)
    --
    --   * implicit parameters (ImplicitParameters)
    --
    --   * generalised algebraic data types (GADTs)
    --
    --   * template haskell (TemplateHaskell)
    --
    --   * empty data type declarations (EmptyDataDecls)
    --
    --   * unboxed tuples (UnboxedTuples)
    --
    --   * regular patterns (RegularPatterns)
    --
    --   * HSP-style XML expressions and patterns (XmlSyntax)
    --
    -----------------------------------------------------------------------------

    module Language.Haskell.Exts.Syntax (
        -- * Modules
        Module(..), WarningText(..), ExportSpec(..),
        ImportDecl(..), ImportSpec(..), Assoc(..),
        -- * Declarations
        Decl(..), Binds(..), IPBind(..),
        -- ** Type classes and instances
        ClassDecl(..), InstDecl(..), Deriving,
        -- ** Data type declarations
        DataOrNew(..), ConDecl(..), QualConDecl(..), GadtDecl(..), BangType(..),
        -- ** Function bindings
        Match(..), Rhs(..), GuardedRhs(..),
        -- * Class Assertions and Contexts
        Context, FunDep(..), Asst(..),
        -- * Types
        Type(..), Boxed(..), Kind(..), TyVarBind(..),
        -- * Expressions
        Exp(..), Stmt(..), QualStmt(..), FieldUpdate(..),
        Alt(..), GuardedAlts(..), GuardedAlt(..), XAttr(..),
        -- * Patterns
        Pat(..), PatField(..), PXAttr(..), RPat(..), RPatOp(..),
        -- * Literals
        Literal(..),
        -- * Variables, Constructors and Operators
        ModuleName(..), QName(..), Name(..), QOp(..), Op(..),
        SpecialCon(..), CName(..), IPName(..), XName(..),

        -- * Template Haskell
        Bracket(..), Splice(..),

        -- * FFI
        Safety(..), CallConv(..),

        -- * Pragmas
        ModulePragma(..), Tool(..),
        Rule(..), RuleVar(..), Activation(..),
        Annotation(..),

        -- * Builtin names

        -- ** Modules
        prelude_mod, main_mod,
        -- ** Main function of a program
        main_name,
        -- ** Constructors
        unit_con_name, tuple_con_name, list_cons_name, unboxed_singleton_con_name,
        unit_con, tuple_con, unboxed_singleton_con,
        -- ** Special identifiers
        as_name, qualified_name, hiding_name, minus_name, bang_name, dot_name, star_name,
        export_name, safe_name, unsafe_name, threadsafe_name, stdcall_name, ccall_name,
        -- ** Type constructors
        unit_tycon_name, fun_tycon_name, list_tycon_name, tuple_tycon_name, unboxed_singleton_tycon_name,
        unit_tycon, fun_tycon, list_tycon, tuple_tycon, unboxed_singleton_tycon,

        -- * Source coordinates
        SrcLoc(..),
      ) where

    #ifdef __GLASGOW_HASKELL__
    #ifdef BASE4
    import Data.Data
    #else
    import Data.Generics (Data(..),Typeable(..))
    #endif
    #endif

    import Language.Haskell.Exts.SrcLoc (SrcLoc(..))

    import Language.Haskell.Exts.Annotated.Syntax (Boxed(..), Tool(..))

    -- | The name of a Haskell module.
    newtype ModuleName = ModuleName String
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | Constructors with special syntax.
    -- These names are never qualified, and always refer to builtin type or
    -- data constructors.
    data SpecialCon
        = UnitCon               -- ^ unit type and data constructor @()@
        | ListCon               -- ^ list type constructor @[]@
        | FunCon                -- ^ function type constructor @->@
        | TupleCon Boxed Int    -- ^ /n/-ary tuple type and data
                                --   constructors @(,)@ etc, possibly boxed @(\#,\#)@
        | Cons                  -- ^ list data constructor @(:)@
        | UnboxedSingleCon      -- ^ unboxed singleton tuple constructor @(\# \#)@
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | This type is used to represent qualified variables, and also
    --   qualified constructors.
    data QName
        = Qual ModuleName Name    -- ^ name qualified with a module name
        | UnQual Name             -- ^ unqualified local name
        | Special SpecialCon      -- ^ built-in constructor with special syntax
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | This type is used to represent variables, and also constructors.
    data Name
        = Ident String    -- ^ /varid/ or /conid/.
        | Symbol String   -- ^ /varsym/ or /consym/
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | An implicit parameter name.
    data IPName
        = IPDup String -- ^ ?/ident/, non-linear implicit parameter
        | IPLin String -- ^ %/ident/, linear implicit parameter
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | Possibly qualified infix operators (/qop/), appearing in expressions.
    data QOp
        = QVarOp QName  -- ^ variable operator (/qvarop/)
        | QConOp QName  -- ^ constructor operator (/qconop/)
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | Operators appearing in @infix@ declarations are never qualified.
    data Op
        = VarOp Name    -- ^ variable operator (/varop/)
        | ConOp Name    -- ^ constructor operator (/conop/)
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | A name (/cname/) of a component of a class or data type in an @import@
    --   or export specification.
    data CName
        = VarName Name  -- ^ name of a method or field
        | ConName Name  -- ^ name of a data constructor
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | A complete Haskell source module.
    data Module = Module SrcLoc ModuleName [ModulePragma] (Maybe WarningText)
                            (Maybe [ExportSpec]) [ImportDecl] [Decl]
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | An item in a module's export specification.
    data ExportSpec
         = EVar QName                   -- ^ variable
         | EAbs QName                   -- ^ @T@:
                                        --   a class or datatype exported abstractly,
                                        --   or a type synonym.
         | EThingAll QName              -- ^ @T(..)@:
                                        --   a class exported with all of its methods, or
                                        --   a datatype exported with all of its constructors.
         | EThingWith QName [CName]     -- ^ @T(C_1,...,C_n)@:
                                        --   a class exported with some of its methods, or
                                        --   a datatype exported with some of its constructors.
         | EModuleContents ModuleName   -- ^ @module M@:
                                        --   re-export a module.
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | An import declaration.
    data ImportDecl = ImportDecl
        { importLoc :: SrcLoc           -- ^ position of the @import@ keyword.
        , importModule :: ModuleName    -- ^ name of the module imported.
        , importQualified :: Bool       -- ^ imported @qualified@?
        , importSrc :: Bool             -- ^ imported with @{-\# SOURCE \#-}@?
        , importPkg :: Maybe String     -- ^ imported with explicit package name
        , importAs :: Maybe ModuleName  -- ^ optional alias name in an @as@ clause.
        , importSpecs :: Maybe (Bool,[ImportSpec])
                -- ^ optional list of import specifications.
                -- The 'Bool' is 'True' if the names are excluded
                -- by @hiding@.
        }
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | An import specification, representing a single explicit item imported
    --   (or hidden) from a module.
    data ImportSpec
         = IVar Name                -- ^ variable
         | IAbs Name                -- ^ @T@:
                                    --   the name of a class, datatype or type synonym.
         | IThingAll Name           -- ^ @T(..)@:
                                    --   a class imported with all of its methods, or
                                    --   a datatype imported with all of its constructors.
         | IThingWith Name [CName]  -- ^ @T(C_1,...,C_n)@:
                                    --   a class imported with some of its methods, or
                                    --   a datatype imported with some of its constructors.
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | Associativity of an operator.
    data Assoc
         = AssocNone  -- ^ non-associative operator (declared with @infix@)
         | AssocLeft  -- ^ left-associative operator (declared with @infixl@).
         | AssocRight -- ^ right-associative operator (declared with @infixr@)
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | A single derived instance, which may have arguments since it may be a MPTC.
    type Deriving = (QName, [Type])

    -- | A top-level declaration.
    data Decl
         = TypeDecl     SrcLoc Name [TyVarBind] Type
         -- ^ A type declaration
         | TypeFamDecl  SrcLoc Name [TyVarBind] (Maybe Kind)
         -- ^ A type family declaration
         | DataDecl     SrcLoc DataOrNew Context Name [TyVarBind]              [QualConDecl] [Deriving]
         -- ^ A data OR newtype declaration
         | GDataDecl    SrcLoc DataOrNew Context Name [TyVarBind] (Maybe Kind) [GadtDecl]    [Deriving]
         -- ^ A data OR newtype declaration, GADT style
         | DataFamDecl  SrcLoc {-data-}  Context Name [TyVarBind] (Maybe Kind)
         -- ^ A data family declaration
         | TypeInsDecl  SrcLoc Type Type
         -- ^ A type family instance declaration
         | DataInsDecl  SrcLoc DataOrNew Type              [QualConDecl] [Deriving]
         -- ^ A data family instance declaration
         | GDataInsDecl SrcLoc DataOrNew Type (Maybe Kind) [GadtDecl]    [Deriving]
         -- ^ A data family instance declaration, GADT style
         | ClassDecl    SrcLoc Context Name [TyVarBind] [FunDep] [ClassDecl]
         -- ^ A declaration of a type class
         | InstDecl     SrcLoc Context QName [Type] [InstDecl]
         -- ^ An declaration of a type class instance
         | DerivDecl    SrcLoc Context QName [Type]
         -- ^ A standalone deriving declaration
         | InfixDecl    SrcLoc Assoc Int [Op]
         -- ^ A declaration of operator fixity
         | DefaultDecl  SrcLoc [Type]
         -- ^ A declaration of default types
         | SpliceDecl   SrcLoc Exp
         -- ^ A Template Haskell splicing declaration
         | TypeSig      SrcLoc [Name] Type
         -- ^ A type signature declaration
         | FunBind      [Match]
         -- ^ A set of function binding clauses
         | PatBind      SrcLoc Pat (Maybe Type) Rhs {-where-} Binds
         -- ^ A pattern binding
         | ForImp   SrcLoc CallConv Safety String Name Type
         -- ^ A foreign import declaration
         | ForExp   SrcLoc CallConv          String Name Type
         -- ^ A foreign export declaration

         | RulePragmaDecl   SrcLoc [Rule]
         -- ^ A RULES pragma
         | DeprPragmaDecl   SrcLoc [([Name], String)]
         -- ^ A DEPRECATED pragma
         | WarnPragmaDecl   SrcLoc [([Name], String)]
         -- ^ A WARNING pragma
         | InlineSig        SrcLoc Bool Activation QName
         -- ^ An INLINE pragma
         | InlineConlikeSig SrcLoc      Activation QName
         -- ^ An INLINE CONLIKE pragma
         | SpecSig          SrcLoc                 QName [Type]
         -- ^ A SPECIALISE pragma
         | SpecInlineSig    SrcLoc Bool Activation QName [Type]
         -- ^ A SPECIALISE INLINE pragma
         | InstSig          SrcLoc Context         QName [Type]
         -- ^ A SPECIALISE instance pragma
         | AnnPragma        SrcLoc Annotation
         -- ^ An ANN pragma
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | An annotation through an ANN pragma.
    data Annotation
        = Ann       Name Exp
        -- ^ An annotation for a declared name.
        | TypeAnn   Name Exp
        -- ^ An annotation for a declared type.
        | ModuleAnn      Exp
        -- ^ An annotation for the defining module.
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | A flag stating whether a declaration is a data or newtype declaration.
    data DataOrNew = DataType | NewType
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | A binding group inside a @let@ or @where@ clause.
    data Binds
        = BDecls [Decl]     -- ^ An ordinary binding group
        | IPBinds [IPBind]  -- ^ A binding group for implicit parameters
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | A binding of an implicit parameter.
    data IPBind = IPBind SrcLoc IPName Exp
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | Clauses of a function binding.
    data Match
         = Match SrcLoc Name [Pat] (Maybe Type) Rhs {-where-} Binds
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | A single constructor declaration within a data type declaration,
    --   which may have an existential quantification binding.
    data QualConDecl
        = QualConDecl SrcLoc
            {-forall-} [TyVarBind] {- . -} Context
            {- => -} ConDecl
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | Declaration of an ordinary data constructor.
    data ConDecl
         = ConDecl Name [BangType]
                    -- ^ ordinary data constructor
         | InfixConDecl BangType Name BangType
                    -- ^ infix data constructor
         | RecDecl Name [([Name],BangType)]
                    -- ^ record constructor
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | A single constructor declaration in a GADT data type declaration.
    data GadtDecl
        = GadtDecl SrcLoc Name Type
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | Declarations inside a class declaration.
    data ClassDecl
        = ClsDecl    Decl
                -- ^ ordinary declaration
        | ClsDataFam SrcLoc Context Name [TyVarBind] (Maybe Kind)
                -- ^ declaration of an associated data type
        | ClsTyFam   SrcLoc         Name [TyVarBind] (Maybe Kind)
                -- ^ declaration of an associated type synonym
        | ClsTyDef   SrcLoc Type    Type
                -- ^ default choice for an associated type synonym
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | Declarations inside an instance declaration.
    data InstDecl
        = InsDecl   Decl
                -- ^ ordinary declaration
        | InsType   SrcLoc Type Type
                -- ^ an associated type definition
        | InsData   SrcLoc DataOrNew Type [QualConDecl] [Deriving]
                -- ^ an associated data type implementation
        | InsGData  SrcLoc DataOrNew Type (Maybe Kind) [GadtDecl] [Deriving]
                -- ^ an associated data type implemented using GADT style
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | The type of a constructor argument or field, optionally including
    --   a strictness annotation.
    data BangType
         = BangedTy   Type  -- ^ strict component, marked with \"@!@\"
         | UnBangedTy Type  -- ^ non-strict component
         | UnpackedTy Type  -- ^ unboxed component, marked with an UNPACK pragma
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | The right hand side of a function or pattern binding.
    data Rhs
         = UnGuardedRhs Exp -- ^ unguarded right hand side (/exp/)
         | GuardedRhss  [GuardedRhs]
                            -- ^ guarded right hand side (/gdrhs/)
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | A guarded right hand side @|@ /stmts/ @=@ /exp/.
    --   The guard is a series of statements when using pattern guards,
    --   otherwise it will be a single qualifier expression.
    data GuardedRhs
         = GuardedRhs SrcLoc [Stmt] Exp
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | A type qualified with a context.
    --   An unqualified type has an empty context.
    data Type
         = TyForall
            (Maybe [TyVarBind])
            Context
            Type                    -- ^ qualified type
         | TyFun   Type Type        -- ^ function type
         | TyTuple Boxed [Type]     -- ^ tuple type, possibly boxed
         | TyList  Type             -- ^ list syntax, e.g. [a], as opposed to [] a
         | TyApp   Type Type        -- ^ application of a type constructor
         | TyVar   Name             -- ^ type variable
         | TyCon   QName            -- ^ named type or type constructor
         | TyParen Type             -- ^ type surrounded by parentheses
         | TyInfix Type QName Type  -- ^ infix type constructor
         | TyKind  Type Kind        -- ^ type with explicit kind signature
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | A type variable declaration, optionally with an explicit kind annotation.
    data TyVarBind
        = KindedVar Name Kind   -- ^ variable binding with kind annotation
        | UnkindedVar Name      -- ^ ordinary variable binding
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | An explicit kind annotation.
    data Kind
        = KindStar          -- ^ @*@, the kind of types
        | KindBang          -- ^ @!@, the kind of unboxed types
        | KindFn Kind Kind  -- ^ @->@, the kind of a type constructor
        | KindParen Kind    -- ^ a kind surrounded by parentheses
        | KindVar Name      -- ^ a kind variable (as of yet unsupported by compilers)
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | A functional dependency, given on the form
    --   l1 l2 ... ln -> r2 r3 .. rn
    data FunDep
        = FunDep [Name] [Name]
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | A context is a set of assertions
    type Context = [Asst]

    -- | Class assertions.
    --   In Haskell 98, the argument would be a /tyvar/, but this definition
    --   allows multiple parameters, and allows them to be /type/s.
    --   Also extended with support for implicit parameters and equality constraints.
    data Asst = ClassA QName [Type]     -- ^ ordinary class assertion
              | InfixA Type QName Type  -- ^ class assertion where the class name is given infix
              | IParam IPName Type      -- ^ implicit parameter assertion
              | EqualP Type   Type      -- ^ type equality constraint
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | /literal/
    -- Values of this type hold the abstract value of the literal, not the
    -- precise string representation used.  For example, @10@, @0o12@ and @0xa@
    -- have the same representation.
    data Literal
        = Char    Char          -- ^ character literal
        | String  String        -- ^ string literal
        | Int     Integer       -- ^ integer literal
        | Frac    Rational      -- ^ floating point literal
        | PrimInt    Integer    -- ^ unboxed integer literal
        | PrimWord   Integer    -- ^ unboxed word literal
        | PrimFloat  Rational   -- ^ unboxed float literal
        | PrimDouble Rational   -- ^ unboxed double literal
        | PrimChar   Char       -- ^ unboxed character literal
        | PrimString String     -- ^ unboxed string literal
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | Haskell expressions.
    data Exp
        = Var QName                 -- ^ variable
        | IPVar IPName              -- ^ implicit parameter variable
        | Con QName                 -- ^ data constructor
        | Lit Literal               -- ^ literal constant
        | InfixApp Exp QOp Exp      -- ^ infix application
        | App Exp Exp               -- ^ ordinary application
        | NegApp Exp                -- ^ negation expression @-/exp/@ (unary minus)
        | Lambda SrcLoc [Pat] Exp   -- ^ lambda expression
        | Let Binds Exp             -- ^ local declarations with @let@ ... @in@ ...
        | If Exp Exp Exp            -- ^ @if@ /exp/ @then@ /exp/ @else@ /exp/
        | Case Exp [Alt]            -- ^ @case@ /exp/ @of@ /alts/
        | Do [Stmt]                 -- ^ @do@-expression:
                                    --   the last statement in the list
                                    --   should be an expression.
        | MDo [Stmt]                -- ^ @mdo@-expression
        | Tuple [Exp]               -- ^ tuple expression
        | TupleSection [Maybe Exp]  -- ^ tuple section expression, e.g. @(,,3)@
        | List [Exp]                -- ^ list expression
        | Paren Exp                 -- ^ parenthesised expression
        | LeftSection Exp QOp       -- ^ left section @(@/exp/ /qop/@)@
        | RightSection QOp Exp      -- ^ right section @(@/qop/ /exp/@)@
        | RecConstr QName [FieldUpdate]
                                    -- ^ record construction expression
        | RecUpdate Exp [FieldUpdate]
                                    -- ^ record update expression
        | EnumFrom Exp              -- ^ unbounded arithmetic sequence,
                                    --   incrementing by 1: @[from ..]@
        | EnumFromTo Exp Exp        -- ^ bounded arithmetic sequence,
                                    --   incrementing by 1 @[from .. to]@
        | EnumFromThen Exp Exp      -- ^ unbounded arithmetic sequence,
                                    --   with first two elements given @[from, then ..]@
        | EnumFromThenTo Exp Exp Exp
                                    -- ^ bounded arithmetic sequence,
                                    --   with first two elements given @[from, then .. to]@
        | ListComp Exp  [QualStmt]    -- ^ ordinary list comprehension
        | ParComp  Exp [[QualStmt]]   -- ^ parallel list comprehension
        | ExpTypeSig SrcLoc Exp Type  -- ^ expression with explicit type signature

        | VarQuote QName            -- ^ @'x@ for template haskell reifying of expressions
        | TypQuote QName            -- ^ @''T@ for template haskell reifying of types
        | BracketExp Bracket        -- ^ template haskell bracket expression
        | SpliceExp Splice          -- ^ template haskell splice expression
        | QuasiQuote String String  -- ^ quasi-quotaion: @[$/name/| /string/ |]@

    -- Hsx
        | XTag SrcLoc XName [XAttr] (Maybe Exp) [Exp]
                                    -- ^ xml element, with attributes and children
        | XETag SrcLoc XName [XAttr] (Maybe Exp)
                                    -- ^ empty xml element, with attributes
        | XPcdata String            -- ^ PCDATA child element
        | XExpTag Exp               -- ^ escaped haskell expression inside xml

    -- Pragmas
        | CorePragma        String Exp      -- ^ CORE pragma
        | SCCPragma         String Exp      -- ^ SCC pragma
        | GenPragma         String (Int, Int) (Int, Int) Exp
                                            -- ^ GENERATED pragma

    -- Arrows
        | Proc SrcLoc     Pat Exp   -- ^ arrows proc: @proc@ /pat/ @->@ /exp/
        | LeftArrApp      Exp Exp   -- ^ arrow application (from left): /exp/ @-<@ /exp/
        | RightArrApp     Exp Exp   -- ^ arrow application (from right): /exp/ @>-@ /exp/
        | LeftArrHighApp  Exp Exp   -- ^ higher-order arrow application (from left): /exp/ @-<<@ /exp/
        | RightArrHighApp Exp Exp   -- ^ higher-order arrow application (from right): /exp/ @>>-@ /exp/
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | The name of an xml element or attribute,
    --   possibly qualified with a namespace.
    data XName
        = XName String              -- <name ...
        | XDomName String String    -- <dom:name ...
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | An xml attribute, which is a name-expression pair.
    data XAttr = XAttr XName Exp
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | A template haskell bracket expression.
    data Bracket
        = ExpBracket Exp        -- ^ expression bracket: @[| ... |]@
        | PatBracket Pat        -- ^ pattern bracket: @[p| ... |]@
        | TypeBracket Type      -- ^ type bracket: @[t| ... |]@
        | DeclBracket [Decl]    -- ^ declaration bracket: @[d| ... |]@
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | A template haskell splice expression
    data Splice
        = IdSplice String       -- ^ variable splice: @$var@
        | ParenSplice Exp       -- ^ parenthesised expression splice: @$(/exp/)@
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | The safety of a foreign function call.
    data Safety
        = PlayRisky         -- ^ unsafe
        | PlaySafe Bool     -- ^ safe ('False') or threadsafe ('True')
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | The calling convention of a foreign function call.
    data CallConv
        = StdCall
        | CCall
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | A top level options pragma, preceding the module header.
    data ModulePragma
        = LanguagePragma   SrcLoc [Name]    -- ^ LANGUAGE pragma
        | OptionsPragma    SrcLoc (Maybe Tool) String
                            -- ^ OPTIONS pragma, possibly qualified with a tool, e.g. OPTIONS_GHC
        | AnnModulePragma  SrcLoc Annotation
                            -- ^ ANN pragma with module scope
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | Activation clause of a RULES pragma.
    data Activation
        = AlwaysActive
        | ActiveFrom  Int
        | ActiveUntil Int
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | The body of a RULES pragma.
    data Rule
        = Rule String Activation (Maybe [RuleVar]) Exp Exp
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | Variables used in a RULES pragma, optionally annotated with types
    data RuleVar
        = RuleVar Name
        | TypedRuleVar Name Type
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | Warning text to optionally use in the module header of e.g.
    --   a deprecated module.
    data WarningText
        = DeprText String
        | WarnText String
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | A pattern, to be matched against a value.
    data Pat
        = PVar Name                     -- ^ variable
        | PLit Literal                  -- ^ literal constant
        | PNeg Pat                      -- ^ negated pattern
        | PNPlusK Name Integer          -- ^ n+k pattern
        | PInfixApp Pat QName Pat       -- ^ pattern with an infix data constructor
        | PApp QName [Pat]              -- ^ data constructor and argument patterns
        | PTuple [Pat]                  -- ^ tuple pattern
        | PList [Pat]                   -- ^ list pattern
        | PParen Pat                    -- ^ parenthesized pattern
        | PRec QName [PatField]         -- ^ labelled pattern, record style
        | PAsPat Name Pat               -- ^ @\@@-pattern
        | PWildCard                     -- ^ wildcard pattern: @_@
        | PIrrPat Pat                   -- ^ irrefutable pattern: @~/pat/@
        | PatTypeSig SrcLoc Pat Type    -- ^ pattern with type signature
        | PViewPat Exp Pat              -- ^ view patterns of the form @(/exp/ -> /pat/)@
        | PRPat [RPat]                  -- ^ regular list pattern
        | PXTag SrcLoc XName [PXAttr] (Maybe Pat) [Pat]
                                        -- ^ XML element pattern
        | PXETag SrcLoc XName [PXAttr] (Maybe Pat)
                                        -- ^ XML singleton element pattern
        | PXPcdata String               -- ^ XML PCDATA pattern
        | PXPatTag Pat                  -- ^ XML embedded pattern
        | PXRPats [RPat]                -- ^ XML regular list pattern
        | PExplTypeArg QName Type       -- ^ Explicit generics style type argument e.g. @f {| Int |} x = ...@
        | PQuasiQuote String String     -- ^ quasi quote patter: @[$/name/| /string/ |]@
        | PBangPat Pat                  -- ^ strict (bang) pattern: @f !x = ...@
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | An XML attribute in a pattern.
    data PXAttr = PXAttr XName Pat
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | A regular pattern operator.
    data RPatOp
        = RPStar    -- ^ @*@ = 0 or more
        | RPStarG   -- ^ @*!@ = 0 or more, greedy
        | RPPlus    -- ^ @+@ = 1 or more
        | RPPlusG   -- ^ @+!@ = 1 or more, greedy
        | RPOpt     -- ^ @?@ = 0 or 1
        | RPOptG    -- ^ @?!@ = 0 or 1, greedy
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | An entity in a regular pattern.
    data RPat
        = RPOp RPat RPatOp      -- ^ operator pattern, e.g. pat*
        | RPEither RPat RPat    -- ^ choice pattern, e.g. (1 | 2)
        | RPSeq [RPat]          -- ^ sequence pattern, e.g. (| 1, 2, 3 |)
        | RPGuard Pat [Stmt]    -- ^ guarded pattern, e.g. (| p | p < 3 |)
        | RPCAs Name RPat       -- ^ non-linear variable binding, e.g. (foo\@:(1 | 2))*
        | RPAs Name RPat        -- ^ linear variable binding, e.g. foo\@(1 | 2)
        | RPParen RPat          -- ^ parenthesised pattern, e.g. (2*)
        | RPPat Pat             -- ^ an ordinary pattern
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | An /fpat/ in a labeled record pattern.
    data PatField
        = PFieldPat QName Pat       -- ^ ordinary label-pattern pair
        | PFieldPun Name            -- ^ record field pun
        | PFieldWildcard            -- ^ record field wildcard
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | A statement, representing both a /stmt/ in a @do@-expression,
    --   an ordinary /qual/ in a list comprehension, as well as a /stmt/
    --   in a pattern guard.
    data Stmt
        = Generator SrcLoc Pat Exp
                            -- ^ a generator: /pat/ @<-@ /exp/
        | Qualifier Exp     -- ^ an /exp/ by itself: in a @do@-expression,
                            --   an action whose result is discarded;
                            --   in a list comprehension and pattern guard,
                            --   a guard expression
        | LetStmt Binds     -- ^ local bindings
        | RecStmt [Stmt]    -- ^ a recursive binding group for arrows
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | A general /transqual/ in a list comprehension,
    --   which could potentially be a transform of the kind
    --   enabled by TransformListComp.
    data QualStmt
        = QualStmt     Stmt         -- ^ an ordinary statement
        | ThenTrans    Exp          -- ^ @then@ /exp/
        | ThenBy       Exp Exp      -- ^ @then@ /exp/ @by@ /exp/
        | GroupBy      Exp          -- ^ @then@ @group@ @by@ /exp/
        | GroupUsing   Exp          -- ^ @then@ @group@ @using@ /exp/
        | GroupByUsing Exp Exp      -- ^ @then@ @group@ @by@ /exp/ @using@ /exp/
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | An /fbind/ in a labeled construction or update expression.
    data FieldUpdate
        = FieldUpdate QName Exp     -- ^ ordinary label-expresion pair
        | FieldPun Name             -- ^ record field pun
        | FieldWildcard             -- ^ record field wildcard
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | An /alt/ alternative in a @case@ expression.
    data Alt
        = Alt SrcLoc Pat GuardedAlts Binds
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | The right-hand sides of a @case@ alternative,
    --   which may be a single right-hand side or a
    --   set of guarded ones.
    data GuardedAlts
        = UnGuardedAlt Exp          -- ^ @->@ /exp/
        | GuardedAlts  [GuardedAlt] -- ^ /gdpat/
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -- | A guarded case alternative @|@ /stmts/ @->@ /exp/.
    data GuardedAlt
        = GuardedAlt SrcLoc [Stmt] Exp
    #ifdef __GLASGOW_HASKELL__
      deriving (Eq,Ord,Show,Typeable,Data)
    #else
      deriving (Eq,Ord,Show)
    #endif

    -----------------------------------------------------------------------------
    -- Builtin names.

    prelude_mod, main_mod :: ModuleName
    prelude_mod = ModuleName "Prelude"
    main_mod    = ModuleName "Main"

    main_name :: Name
    main_name = Ident "main"

    unit_con_name :: QName
    unit_con_name = Special UnitCon

    tuple_con_name :: Boxed -> Int -> QName
    tuple_con_name b i = Special (TupleCon b (i+1))

    list_cons_name :: QName
    list_cons_name = Special Cons

    unboxed_singleton_con_name :: QName
    unboxed_singleton_con_name = Special UnboxedSingleCon

    unit_con :: Exp
    unit_con = Con unit_con_name

    tuple_con :: Boxed -> Int -> Exp
    tuple_con b i = Con (tuple_con_name b i)

    unboxed_singleton_con :: Exp
    unboxed_singleton_con = Con (unboxed_singleton_con_name)

    as_name, qualified_name, hiding_name, minus_name, bang_name, dot_name, star_name :: Name
    as_name        = Ident "as"
    qualified_name = Ident "qualified"
    hiding_name    = Ident "hiding"
    minus_name     = Symbol "-"
    bang_name      = Symbol "!"
    dot_name       = Symbol "."
    star_name      = Symbol "*"

    export_name, safe_name, unsafe_name, threadsafe_name, stdcall_name, ccall_name :: Name
    export_name     = Ident "export"
    safe_name       = Ident "safe"
    unsafe_name     = Ident "unsafe"
    threadsafe_name = Ident "threadsafe"
    stdcall_name    = Ident "stdcall"
    ccall_name      = Ident "ccall"

    unit_tycon_name, fun_tycon_name, list_tycon_name, unboxed_singleton_tycon_name :: QName
    unit_tycon_name = unit_con_name
    fun_tycon_name  = Special FunCon
    list_tycon_name = Special ListCon
    unboxed_singleton_tycon_name = Special UnboxedSingleCon

    tuple_tycon_name :: Boxed -> Int -> QName
    tuple_tycon_name b i = tuple_con_name b i

    unit_tycon, fun_tycon, list_tycon, unboxed_singleton_tycon :: Type
    unit_tycon = TyCon unit_tycon_name
    fun_tycon  = TyCon fun_tycon_name
    list_tycon = TyCon list_tycon_name
    unboxed_singleton_tycon = TyCon unboxed_singleton_tycon_name

    tuple_tycon :: Boxed -> Int -> Type
    tuple_tycon b i = TyCon (tuple_tycon_name b i)