Safe Haskell | None |
---|---|

Language | Haskell98 |

Commonly useful utilites for manipulating the Core language

- mkCast :: CoreExpr -> Coercion -> CoreExpr
- mkTick :: Tickish Id -> CoreExpr -> CoreExpr
- mkTickNoHNF :: Tickish Id -> CoreExpr -> CoreExpr
- tickHNFArgs :: Tickish Id -> CoreExpr -> CoreExpr
- bindNonRec :: Id -> CoreExpr -> CoreExpr -> CoreExpr
- needsCaseBinding :: Type -> CoreExpr -> Bool
- mkAltExpr :: AltCon -> [CoreBndr] -> [Type] -> CoreExpr
- findDefault :: [(AltCon, [a], b)] -> ([(AltCon, [a], b)], Maybe b)
- findAlt :: AltCon -> [(AltCon, a, b)] -> Maybe (AltCon, a, b)
- isDefaultAlt :: (AltCon, a, b) -> Bool
- mergeAlts :: [(AltCon, a, b)] -> [(AltCon, a, b)] -> [(AltCon, a, b)]
- trimConArgs :: AltCon -> [CoreArg] -> [CoreArg]
- filterAlts :: [Unique] -> Type -> [AltCon] -> [(AltCon, [Var], a)] -> ([AltCon], Bool, [(AltCon, [Var], a)])
- exprType :: CoreExpr -> Type
- coreAltType :: CoreAlt -> Type
- coreAltsType :: [CoreAlt] -> Type
- exprIsDupable :: DynFlags -> CoreExpr -> Bool
- exprIsTrivial :: CoreExpr -> Bool
- getIdFromTrivialExpr :: CoreExpr -> Id
- exprIsBottom :: CoreExpr -> Bool
- exprIsCheap :: CoreExpr -> Bool
- exprIsExpandable :: CoreExpr -> Bool
- exprIsCheap' :: CheapAppFun -> CoreExpr -> Bool
- type CheapAppFun = Id -> Int -> Bool
- exprIsHNF :: CoreExpr -> Bool
- exprOkForSpeculation :: Expr b -> Bool
- exprOkForSideEffects :: Expr b -> Bool
- exprIsWorkFree :: CoreExpr -> Bool
- exprIsBig :: Expr b -> Bool
- exprIsConLike :: CoreExpr -> Bool
- rhsIsStatic :: Platform -> (Name -> Bool) -> CoreExpr -> Bool
- isCheapApp :: CheapAppFun
- isExpandableApp :: CheapAppFun
- coreBindsSize :: [CoreBind] -> Int
- exprSize :: CoreExpr -> Int
- data CoreStats = CS {}
- coreBindsStats :: [CoreBind] -> CoreStats
- cheapEqExpr :: Expr b -> Expr b -> Bool
- eqExpr :: InScopeSet -> CoreExpr -> CoreExpr -> Bool
- tryEtaReduce :: [Var] -> CoreExpr -> Maybe CoreExpr
- applyTypeToArgs :: CoreExpr -> Type -> [CoreExpr] -> Type
- applyTypeToArg :: Type -> CoreExpr -> Type
- dataConRepInstPat :: [Unique] -> DataCon -> [Type] -> ([TyVar], [Id])
- dataConRepFSInstPat :: [FastString] -> [Unique] -> DataCon -> [Type] -> ([TyVar], [Id])

# Constructing expressions

mkCast :: CoreExpr -> Coercion -> CoreExpr Source

Wrap the given expression in the coercion safely, dropping identity coercions and coalescing nested coercions

mkTick :: Tickish Id -> CoreExpr -> CoreExpr Source

Wraps the given expression in the source annotation, dropping the annotation if possible.

bindNonRec :: Id -> CoreExpr -> CoreExpr -> CoreExpr Source

`bindNonRec x r b`

produces either:

let x = r in b

or:

case r of x { _DEFAULT_ -> b }

depending on whether we have to use a `case`

or `let`

binding for the expression (see `needsCaseBinding`

).
It's used by the desugarer to avoid building bindings
that give Core Lint a heart attack, although actually
the simplifier deals with them perfectly well. See
also `mkCoreLet`

needsCaseBinding :: Type -> CoreExpr -> Bool Source

:: AltCon | Case alternative constructor |

-> [CoreBndr] | Things bound by the pattern match |

-> [Type] | The type arguments to the case alternative |

-> CoreExpr |

This guy constructs the value that the scrutinee must have given that you are in one particular branch of a case

# Taking expressions apart

findDefault :: [(AltCon, [a], b)] -> ([(AltCon, [a], b)], Maybe b) Source

Extract the default case alternative

findAlt :: AltCon -> [(AltCon, a, b)] -> Maybe (AltCon, a, b) Source

Find the case alternative corresponding to a particular constructor: panics if no such constructor exists

isDefaultAlt :: (AltCon, a, b) -> Bool Source

mergeAlts :: [(AltCon, a, b)] -> [(AltCon, a, b)] -> [(AltCon, a, b)] Source

Merge alternatives preserving order; alternatives in the first argument shadow ones in the second

trimConArgs :: AltCon -> [CoreArg] -> [CoreArg] Source

Given:

case (C a b x y) of C b x y -> ...

We want to drop the leading type argument of the scrutinee leaving the arguments to match agains the pattern

# Properties of expressions

exprType :: CoreExpr -> Type Source

Recover the type of a well-typed Core expression. Fails when
applied to the actual `Type`

expression as it cannot
really be said to have a type

coreAltType :: CoreAlt -> Type Source

Returns the type of the alternatives right hand side

coreAltsType :: [CoreAlt] -> Type Source

Returns the type of the first alternative, which should be the same as for all alternatives

exprIsDupable :: DynFlags -> CoreExpr -> Bool Source

exprIsTrivial :: CoreExpr -> Bool Source

getIdFromTrivialExpr :: CoreExpr -> Id Source

exprIsBottom :: CoreExpr -> Bool Source

exprIsCheap :: CoreExpr -> Bool Source

exprIsExpandable :: CoreExpr -> Bool Source

exprIsCheap' :: CheapAppFun -> CoreExpr -> Bool Source

type CheapAppFun = Id -> Int -> Bool Source

exprIsHNF :: CoreExpr -> Bool Source

exprIsHNF returns true for expressions that are certainly *already*
evaluated to *head* normal form. This is used to decide whether it's ok
to change:

case x of _ -> e

into:

e

and to decide whether it's safe to discard a `seq`

.

So, it does *not* treat variables as evaluated, unless they say they are.
However, it *does* treat partial applications and constructor applications
as values, even if their arguments are non-trivial, provided the argument
type is lifted. For example, both of these are values:

(:) (f x) (map f xs) map (...redex...)

because `seq`

on such things completes immediately.

For unlifted argument types, we have to be careful:

C (f x :: Int#)

Suppose `f x`

diverges; then `C (f x)`

is not a value. However this can't
happen: see CoreSyn. This invariant states that arguments of
unboxed type must be ok-for-speculation (or trivial).

exprOkForSpeculation :: Expr b -> Bool Source

`exprOkForSpeculation`

returns True of an expression that is:

- Safe to evaluate even if normal order eval might not evaluate the expression at all, or
- Safe
*not*to evaluate even if normal order would do so

It is usually called on arguments of unlifted type, but not always
In particular, Simplify.rebuildCase calls it on lifted types
when a 'case' is a plain `seq`

. See the example in
Note [exprOkForSpeculation: case expressions] below

Precisely, it returns `True`

iff:

- The expression guarantees to terminate,
- soon,
- without raising an exception,
- without causing a side effect (e.g. writing a mutable variable)

Note that if `exprIsHNF e`

, then `exprOkForSpecuation e`

.
As an example of the considerations in this test, consider:

let x = case y# +# 1# of { r# -> I# r# } in E

being translated to:

case y# +# 1# of { r# -> let x = I# r# in E }

We can only do this if the `y + 1`

is ok for speculation: it has no
side effects, and can't diverge or raise an exception.

exprOkForSideEffects :: Expr b -> Bool Source

`exprOkForSpeculation`

returns True of an expression that is:

- Safe to evaluate even if normal order eval might not evaluate the expression at all, or
- Safe
*not*to evaluate even if normal order would do so

It is usually called on arguments of unlifted type, but not always
In particular, Simplify.rebuildCase calls it on lifted types
when a 'case' is a plain `seq`

. See the example in
Note [exprOkForSpeculation: case expressions] below

Precisely, it returns `True`

iff:

- The expression guarantees to terminate,
- soon,
- without raising an exception,
- without causing a side effect (e.g. writing a mutable variable)

Note that if `exprIsHNF e`

, then `exprOkForSpecuation e`

.
As an example of the considerations in this test, consider:

let x = case y# +# 1# of { r# -> I# r# } in E

being translated to:

case y# +# 1# of { r# -> let x = I# r# in E }

We can only do this if the `y + 1`

is ok for speculation: it has no
side effects, and can't diverge or raise an exception.

exprIsWorkFree :: CoreExpr -> Bool Source

exprIsBig :: Expr b -> Bool Source

Returns `True`

of expressions that are too big to be compared by `cheapEqExpr`

exprIsConLike :: CoreExpr -> Bool Source

Similar to `exprIsHNF`

but includes CONLIKE functions as well as
data constructors. Conlike arguments are considered interesting by the
inliner.

rhsIsStatic :: Platform -> (Name -> Bool) -> CoreExpr -> Bool Source

This function is called only on *top-level* right-hand sides.
Returns `True`

if the RHS can be allocated statically in the output,
with no thunks involved at all.

# Expression and bindings size

coreBindsSize :: [CoreBind] -> Int Source

exprSize :: CoreExpr -> Int Source

A measure of the size of the expressions, strictly greater than 0 It also forces the expression pretty drastically as a side effect Counts *leaves*, not internal nodes. Types and coercions are not counted.

coreBindsStats :: [CoreBind] -> CoreStats Source

# Equality

cheapEqExpr :: Expr b -> Expr b -> Bool Source

A cheap equality test which bales out fast!
If it returns `True`

the arguments are definitely equal,
otherwise, they may or may not be equal.

See also `exprIsBig`

# Eta reduction

# Manipulating data constructors and types

applyTypeToArgs :: CoreExpr -> Type -> [CoreExpr] -> Type Source

A more efficient version of `applyTypeToArg`

when we have several arguments.
The first argument is just for debugging, and gives some context

applyTypeToArg :: Type -> CoreExpr -> Type Source

Determines the type resulting from applying an expression with given type to a given argument expression

dataConRepFSInstPat :: [FastString] -> [Unique] -> DataCon -> [Type] -> ([TyVar], [Id]) Source