-- | Representation of Haskell expressions module Language.Haskell.Tools.AST.Exprs where import Language.Haskell.Tools.AST.Ann import Language.Haskell.Tools.AST.Base import Language.Haskell.Tools.AST.Literals import Language.Haskell.Tools.AST.Types import Language.Haskell.Tools.AST.Patterns import Language.Haskell.Tools.AST.Stmts import {-# SOURCE #-} Language.Haskell.Tools.AST.TH import {-# SOURCE #-} Language.Haskell.Tools.AST.Binds (LocalBind, LocalBinds, RhsGuard) -- | Haskell expressions data Expr a = Var { _exprName :: Ann Name a } -- ^ A variable or a data constructor (@ a @) | Lit { _exprLit :: Ann Literal a } -- ^ Primitive literal | InfixApp { _exprLhs :: Ann Expr a , _exprOperator :: Ann Operator a , _exprRhs :: Ann Expr a } -- ^ Infix operator application (@ a + b @) | PrefixApp { _exprOperator :: Ann Operator a , _exprRhs :: Ann Expr a } -- ^ Prefix operator application (@ -x @) | App { _exprFun :: Ann Expr a , _exprArg :: Ann Expr a } -- ^ Function application (@ f 4 @) -- unary minus omitted | Lambda { _exprBindings :: AnnList Pattern a -- ^ at least one , _exprInner :: Ann Expr a } -- ^ Lambda expression (@ \a b -> a + b @) | Let { _exprFunBind :: AnnList LocalBind a -- ^ nonempty , _exprInner :: Ann Expr a } -- ^ Local binding (@ let x = 2; y = 3 in e x y @) | If { _exprCond :: Ann Expr a , _exprThen :: Ann Expr a , _exprElse :: Ann Expr a } -- ^ If expression (@ if a then b else c @) | MultiIf { _exprIfAlts :: AnnList GuardedCaseRhs a } -- ^ Multi way if expressions with @MultiWayIf@ extension (@ if | guard1 -> expr1; guard2 -> expr2 @) | Case { _exprCase :: Ann Expr a , _exprAlts :: AnnList Alt a } -- ^ Pattern matching expression (@ case expr of pat1 -> expr1; pat2 -> expr2 @) | Do { _doKind :: Ann DoKind a , _exprStmts :: AnnList Stmt a } -- ^ Do-notation expressions (@ do x <- act1; act2 @) | Tuple { _tupleElems :: AnnList Expr a } -- ^ Tuple expression (@ (e1, e2, e3) @) | UnboxedTuple { _tupleElems :: AnnList Expr a } -- ^ Unboxed tuple expression (@ (# e1, e2, e3 #) @) | TupleSection { _tupleSectionElems :: AnnList TupSecElem a } -- ^ Tuple section, enabled with @TupleSections@ (@ (a,,b) @). One of the elements must be missing. | UnboxedTupSec { _tupleSectionElems :: AnnList TupSecElem a } | List { _listElems :: AnnList Expr a } -- ^ List expression: @[1,2,3]@ | ParArray { _listElems :: AnnList Expr a } -- ^ Parallel array expression: @[: 1,2,3 :]@ | Paren { _exprInner :: Ann Expr a } | LeftSection { _exprLhs :: Ann Expr a , _exprOperator :: Ann Operator a } -- ^ Left operator section: @(1+)@ | RightSection { _exprOperator :: Ann Operator a , _exprRhs :: Ann Expr a } -- ^ Right operator section: @(+1)@ | RecCon { _exprRecName :: Ann Name a , _exprRecFields :: AnnList FieldUpdate a } -- ^ Record value construction: @Point { x = 3, y = -2 }@ | RecUpdate { _exprInner :: Ann Expr a , _exprRecFields :: AnnList FieldUpdate a } -- ^ Record value update: @p1 { x = 3, y = -2 }@ | Enum { _enumFrom :: Ann Expr a , _enumThen :: AnnMaybe Expr a , _enumTo :: AnnMaybe Expr a } -- ^ Enumeration expression (@ [1,3..10] @) | ParArrayEnum { _enumFrom :: Ann Expr a , _enumThen :: AnnMaybe Expr a , _enumToFix :: Ann Expr a } -- ^ Parallel array enumeration (@ [: 1,3 .. 10 :] @) | ListComp { _compExpr :: Ann Expr a , _compBody :: AnnList ListCompBody a -- ^ Can only have 1 element without @ParallelListComp@ } -- ^ List comprehension (@ [ (x, y) | x <- xs | y <- ys ] @) | ParArrayComp { _compExpr :: Ann Expr a , _compBody :: AnnList ListCompBody a } -- ^ Parallel array comprehensions @ [: (x, y) | x <- xs , y <- ys :] @ enabled by @ParallelArrays@ | TypeSig { _exprInner :: Ann Expr a , _exprSig :: Ann Type a } -- ^ Explicit type signature (@ _x :: Int @) | ExplTypeApp { _exprInner :: Ann Expr a , _exprType :: Ann Type a } -- ^ Explicit type application (@ show \@Integer (read "5") @) | VarQuote { _quotedName :: Ann Name a } -- ^ @'x@ for template haskell reifying of expressions | TypeQuote { _quotedName :: Ann Name a } -- ^ @''T@ for template haskell reifying of types | BracketExpr { _bracket :: Ann Bracket a } -- ^ Template haskell bracket expression | Splice { _innerExpr :: Ann Splice a } -- ^ Template haskell splice expression, for example: @$(gen a)@ or @$x@ | QuasiQuoteExpr { _exprQQ :: Ann QuasiQuote a } -- ^ Template haskell quasi-quotation: @[$quoter|str]@ | ExprPragma { _exprPragma :: Ann ExprPragma a } -- Arrows | Proc { _procPattern :: Ann Pattern a , _procExpr :: Ann Cmd a } -- ^ Arrow definition: @proc a -> f -< a+1@ | ArrowApp { _exprLhs :: Ann Expr a , _arrowAppl :: Ann ArrowAppl a , _exprRhs :: Ann Expr a } -- ^ Arrow application: @f -< a+1@ | LamCase { _exprAlts :: AnnList Alt a } -- ^ Lambda case ( @\case 0 -> 1; 1 -> 2@ ) | StaticPtr { _exprInner :: Ann Expr a } -- ^ Static pointer expression (@ static e @). The inner expression must be closed (cannot have variables bound outside) -- XML expressions omitted -- | Field update expressions data FieldUpdate a = NormalFieldUpdate { _fieldName :: Ann Name a , _fieldValue :: Ann Expr a } -- ^ Update of a field (@ x = 1 @) | FieldPun { _fieldUpdateName :: Ann Name a } -- ^ Update the field to the value of the same name (@ x @) | FieldWildcard -- ^ Update the fields of the bounded names to their values (@ .. @). Must be the last update. Cannot be used in a record update expression. -- | An element of a tuple section that can be an expression or missing (indicating a value from a parameter) data TupSecElem a = Present { _tupSecExpr :: Ann Expr a } -- ^ An existing element in a tuple section | Missing -- ^ A missing element in a tuple section -- | Clause of case expression data Alt' expr a = Alt { _altPattern :: Ann Pattern a , _altRhs :: Ann (CaseRhs' expr) a , _altBinds :: AnnMaybe LocalBinds a } type Alt = Alt' Expr type CmdAlt = Alt' Cmd -- | Right hand side of a match (possible with guards): (@ = 3 @ or @ | x == 1 = 3; | otherwise = 4 @) data CaseRhs' expr a = UnguardedCaseRhs { _rhsCaseExpr :: Ann expr a } | GuardedCaseRhss { _rhsCaseGuards :: AnnList (GuardedCaseRhs' expr) a } type CaseRhs = CaseRhs' Expr type CmdCaseRhs = CaseRhs' Cmd -- | A guarded right-hand side of pattern matches binding (@ | x > 3 -> 2 @) data GuardedCaseRhs' expr a = GuardedCaseRhs { _caseGuardStmts :: AnnList RhsGuard a -- ^ Cannot be empty. , _caseGuardExpr :: Ann expr a } type GuardedCaseRhs = GuardedCaseRhs' Expr type CmdGuardedCaseRhs = GuardedCaseRhs' Cmd -- | Pragmas that can be applied to expressions data ExprPragma a = CorePragma { _pragmaStr :: Ann StringNode a } | SccPragma { _pragmaStr :: Ann StringNode a } | GeneratedPragma { _pragmaSrcRange :: Ann SourceRange a } -- | In-AST source ranges (for generated pragmas) data SourceRange a = SourceRange { _srFileName :: Ann StringNode a , _srFromLine :: Ann Number a , _srFromCol :: Ann Number a , _srToLine :: Ann Number a , _srToCol :: Ann Number a } data Number a = Number { _numberInteger :: Integer } data Cmd a = ArrowAppCmd { _cmdLhs :: Ann Expr a , _cmdArrowOp :: Ann ArrowAppl a , _cmdRhs :: Ann Expr a } | ArrowFormCmd { _cmdExpr :: Ann Expr a , _cmdInnerCmds :: AnnList Cmd a } | AppCmd { _cmdInnerCmd :: Ann Cmd a , _cmdApplied :: Ann Expr a } | InfixCmd { _cmdLeftCmd :: Ann Cmd a , _cmdOperator :: Ann Name a , _cmdRightCmd :: Ann Cmd a } | LambdaCmd { _cmdBindings :: AnnList Pattern a -- ^ at least one , _cmdInner :: Ann Cmd a } | ParenCmd { _cmdInner :: Ann Cmd a } | CaseCmd { _cmdExpr :: Ann Expr a , _cmdAlts :: AnnList CmdAlt a } | IfCmd { _cmdExpr :: Ann Expr a , _cmdThen :: Ann Cmd a , _cmdElse :: Ann Cmd a } | LetCmd { _cmdBinds :: AnnList LocalBind a -- ^ nonempty , _cmdInner :: Ann Cmd a } | DoCmd { _cmdStmts :: AnnList (Stmt' Cmd) a }