Safe Haskell | Safe-Infered |
---|

Commonly useful utilites for manipulating the Core language

- mkCast :: CoreExpr -> Coercion -> CoreExpr
- mkTick :: Tickish Id -> CoreExpr -> CoreExpr
- mkTickNoHNF :: Tickish Id -> CoreExpr -> CoreExpr
- bindNonRec :: Id -> CoreExpr -> CoreExpr -> CoreExpr
- needsCaseBinding :: Type -> CoreExpr -> Bool
- mkAltExpr :: AltCon -> [CoreBndr] -> [Type] -> CoreExpr
- findDefault :: [CoreAlt] -> ([CoreAlt], Maybe CoreExpr)
- findAlt :: AltCon -> [CoreAlt] -> Maybe CoreAlt
- isDefaultAlt :: CoreAlt -> Bool
- mergeAlts :: [CoreAlt] -> [CoreAlt] -> [CoreAlt]
- trimConArgs :: AltCon -> [CoreArg] -> [CoreArg]
- exprType :: CoreExpr -> Type
- coreAltType :: CoreAlt -> Type
- coreAltsType :: [CoreAlt] -> Type
- exprIsDupable :: 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, exprOkForSideEffects :: Expr b -> Bool
- exprIsBig :: Expr b -> Bool
- exprIsConLike :: CoreExpr -> Bool
- rhsIsStatic :: (Name -> Bool) -> CoreExpr -> Bool
- isCheapApp :: CheapAppFun
- isExpandableApp :: CheapAppFun
- coreBindsSize :: [CoreBind] -> Int
- exprSize :: CoreExpr -> Int
- data CoreStats = CS {}
- coreBindsStats :: [CoreBind] -> CoreStats
- hashExpr :: CoreExpr -> Int
- cheapEqExpr :: Expr b -> Expr b -> Bool
- eqExpr :: InScopeSet -> CoreExpr -> CoreExpr -> Bool
- eqExprX :: IdUnfoldingFun -> RnEnv2 -> 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 -> CoreExprSource

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

mkTick :: Tickish Id -> CoreExpr -> CoreExprSource

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

bindNonRec :: Id -> CoreExpr -> CoreExpr -> CoreExprSource

`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 -> BoolSource

:: 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

findAlt :: AltCon -> [CoreAlt] -> Maybe CoreAltSource

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

isDefaultAlt :: CoreAlt -> BoolSource

mergeAlts :: [CoreAlt] -> [CoreAlt] -> [CoreAlt]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 -> TypeSource

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 -> TypeSource

Returns the type of the alternatives right hand side

coreAltsType :: [CoreAlt] -> TypeSource

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

exprIsDupable :: CoreExpr -> BoolSource

exprIsTrivial :: CoreExpr -> BoolSource

exprIsBottom :: CoreExpr -> BoolSource

exprIsCheap :: CoreExpr -> BoolSource

exprIsCheap' :: CheapAppFun -> CoreExpr -> BoolSource

type CheapAppFun = Id -> Int -> BoolSource

exprIsHNF :: CoreExpr -> BoolSource

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, exprOkForSideEffects :: Expr b -> BoolSource

`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.

exprIsBig :: Expr b -> BoolSource

Returns `True`

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

exprIsConLike :: CoreExpr -> BoolSource

Similar to `exprIsHNF`

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

rhsIsStatic :: (Name -> Bool) -> CoreExpr -> BoolSource

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] -> IntSource

exprSize :: CoreExpr -> IntSource

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] -> CoreStatsSource

# Hashing

hashExpr :: CoreExpr -> IntSource

Two expressions that hash to the same `Int`

may be equal (but may not be)
Two expressions that hash to the different Ints are definitely unequal.

The emphasis is on a crude, fast hash, rather than on high precision.

But unequal here means "not identical"; two alpha-equivalent expressions may hash to the different Ints.

We must be careful that `\x.x`

and `\y.y`

map to the same hash code,
(at least if we want the above invariant to be true).

# Equality

cheapEqExpr :: Expr b -> Expr b -> BoolSource

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`

eqExprX :: IdUnfoldingFun -> RnEnv2 -> CoreExpr -> CoreExpr -> BoolSource

Compares expressions for equality, modulo alpha.
Does *not* look through newtypes or predicate types
Used in rule matching, and also CSE

# Eta reduction

# Manipulating data constructors and types

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

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 -> TypeSource

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

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