|
|
|
|
|
Description |
CoreSyn holds all the main data types for use by for the Glasgow Haskell Compiler midsection
|
|
Synopsis |
|
| | type Alt b = (AltCon, [b], Expr b) | | | | | | type Arg b = Expr b | | | | type CoreExpr = Expr CoreBndr | | type CoreAlt = Alt CoreBndr | | type CoreBind = Bind CoreBndr | | type CoreArg = Arg CoreBndr | | type CoreBndr = Var | | type TaggedExpr t = Expr (TaggedBndr t) | | type TaggedAlt t = Alt (TaggedBndr t) | | type TaggedBind t = Bind (TaggedBndr t) | | type TaggedArg t = Arg (TaggedBndr t) | | data TaggedBndr t = TB CoreBndr t | | mkLets :: [Bind b] -> Expr b -> Expr b | | mkLams :: [b] -> Expr b -> Expr b | | mkApps :: Expr b -> [Arg b] -> Expr b | | mkTyApps :: Expr b -> [Type] -> Expr b | | mkVarApps :: Expr b -> [Var] -> Expr b | | mkIntLit :: Integer -> Expr b | | mkIntLitInt :: Int -> Expr b | | mkWordLit :: Integer -> Expr b | | mkWordLitWord :: Word -> Expr b | | mkCharLit :: Char -> Expr b | | mkStringLit :: String -> Expr b | | mkFloatLit :: Rational -> Expr b | | mkFloatLitFloat :: Float -> Expr b | | mkDoubleLit :: Rational -> Expr b | | mkDoubleLitDouble :: Double -> Expr b | | mkConApp :: DataCon -> [Arg b] -> Expr b | | mkTyBind :: TyVar -> Type -> CoreBind | | varToCoreExpr :: CoreBndr -> Expr b | | varsToCoreExprs :: [CoreBndr] -> [Expr b] | | isTyVar :: Var -> Bool | | isIdVar :: Var -> Bool | | cmpAltCon :: AltCon -> AltCon -> Ordering | | cmpAlt :: Alt b -> Alt b -> Ordering | | ltAlt :: Alt b -> Alt b -> Bool | | bindersOf :: Bind b -> [b] | | bindersOfBinds :: [Bind b] -> [b] | | rhssOfBind :: Bind b -> [Expr b] | | rhssOfAlts :: [Alt b] -> [Expr b] | | collectBinders :: Expr b -> ([b], Expr b) | | collectTyBinders :: CoreExpr -> ([TyVar], CoreExpr) | | collectValBinders :: CoreExpr -> ([Id], CoreExpr) | | collectTyAndValBinders :: CoreExpr -> ([TyVar], [Id], CoreExpr) | | collectArgs :: Expr b -> (Expr b, [Arg b]) | | coreExprCc :: Expr b -> CostCentre | | flattenBinds :: [Bind b] -> [(b, Expr b)] | | isValArg :: Expr b -> Bool | | isTypeArg :: Expr b -> Bool | | valArgCount :: [Arg b] -> Int | | valBndrCount :: [CoreBndr] -> Int | | isRuntimeArg :: CoreExpr -> Bool | | isRuntimeVar :: Var -> Bool | | | | | | noUnfolding :: Unfolding | | evaldUnfolding :: Unfolding | | mkOtherCon :: [AltCon] -> Unfolding | | unfoldingTemplate :: Unfolding -> CoreExpr | | maybeUnfoldingTemplate :: Unfolding -> Maybe CoreExpr | | otherCons :: Unfolding -> [AltCon] | | isValueUnfolding :: Unfolding -> Bool | | isEvaldUnfolding :: Unfolding -> Bool | | isCheapUnfolding :: Unfolding -> Bool | | isCompulsoryUnfolding :: Unfolding -> Bool | | hasUnfolding :: Unfolding -> Bool | | hasSomeUnfolding :: Unfolding -> Bool | | neverUnfold :: Unfolding -> Bool | | seqExpr :: CoreExpr -> () | | seqExprs :: [CoreExpr] -> () | | seqUnfolding :: Unfolding -> () | | type AnnExpr bndr annot = (annot, AnnExpr' bndr annot) | | | | | | type AnnAlt bndr annot = (AltCon, [bndr], AnnExpr bndr annot) | | deAnnotate :: AnnExpr bndr annot -> Expr bndr | | deAnnotate' :: AnnExpr' bndr annot -> Expr bndr | | deAnnAlt :: AnnAlt bndr annot -> Alt bndr | | collectAnnBndrs :: AnnExpr bndr annot -> ([bndr], AnnExpr bndr annot) | | | | type RuleName = FastString | | seqRules :: [CoreRule] -> () | | ruleArity :: CoreRule -> Int | | ruleName :: CoreRule -> RuleName | | ruleIdName :: CoreRule -> Name | | ruleActivation_maybe :: CoreRule -> Maybe Activation | | setRuleIdName :: Name -> CoreRule -> CoreRule | | isBuiltinRule :: CoreRule -> Bool | | isLocalRule :: CoreRule -> Bool |
|
|
|
Main data types
|
|
data Expr b |
This is the data type that represents GHCs core intermediate language. Currently
GHC uses System FC http://research.microsoft.com/~simonpj/papers/ext-f/ for this purpose,
which is closely related to the simpler and better known System F http://en.wikipedia.org/wiki/System_F.
We get from Haskell source to this Core language in a number of stages:
1. The source code is parsed into an abstract syntax tree, which is represented
by the data type HsExpr.HsExpr with the names being RdrName.RdrNames
2. This syntax tree is renamed, which attaches a Unique.Unique to every RdrName.RdrName
(yielding a Name) to disambiguate identifiers which are lexically identical.
For example, this program:
f x = let f x = x + 1
in f (x - 2)
Would be renamed by having Uniques attached so it looked something like this:
f_1 x_2 = let f_3 x_4 = x_4 + 1
in f_3 (x_2 - 2)
3. The resulting syntax tree undergoes type checking (which also deals with instantiating
type class arguments) to yield a HsExpr.HsExpr type that has Id.Id as it's names.
4. Finally the syntax tree is desugared from the expressive HsExpr.HsExpr type into
this Expr type, which has far fewer constructors and hence is easier to perform
optimization, analysis and code generation on.
The type parameter b is for the type of binders in the expression tree.
| Constructors | Var Id | Variables
| Lit Literal | Primitive literals
| App (Expr b) (Arg b) | Applications: note that the argument may be a Type.
See CoreSyn#let_app_invariant for another invariant
| Lam b (Expr b) | Lambda abstraction
| Let (Bind b) (Expr b) | Recursive and non recursive lets. Operationally
this corresponds to allocating a thunk for the things
bound and then executing the sub-expression.
The right hand sides of all top-level and recursive lets
must be of lifted type (see Type#type_classification for
the meaning of lifted vs. unlifted).
The right hand side of of a non-recursive Let _and_ the argument of an App,
may be of unlifted type, but only if the expression
is ok-for-speculation. This means that the let can be floated around
without difficulty. For example, this is OK:
y::Int# = x +# 1#
But this is not, as it may affect termination if the expression is floated out:
y::Int# = fac 4#
In this situation you should use case rather than a let. The function
CoreUtils.needsCaseBinding can help you determine which to generate, or
alternatively use MkCore.mkCoreLet rather than this constructor directly,
which will generate a case if necessary
We allow a non-recursive let to bind a type variable, thus:
Let (NonRec tv (Type ty)) body
This can be very convenient for postponing type substitutions until
the next run of the simplifier.
At the moment, the rest of the compiler only deals with type-let
in a Let expression, rather than at top level. We may want to revist
this choice.
| Case (Expr b) b Type [Alt b] | Case split. Operationally this corresponds to evaluating
the scrutinee (expression examined) to weak head normal form
and then examining at most one level of resulting constructor (i.e. you
cannot do nested pattern matching directly with this).
The binder gets bound to the value of the scrutinee,
and the Type must be that of all the case alternatives
This is one of the more complicated elements of the Core language, and comes
with a number of restrictions:
The DEFAULT case alternative must be first in the list, if it occurs at all.
The remaining cases are in order of increasing
tag (for DataAlts) or
lit (for LitAlts).
This makes finding the relevant constructor easy, and makes comparison easier too.
The list of alternatives must be exhaustive. An exhaustive case
does not necessarily mention all constructors:
data Foo = Red | Green | Blue
... case x of
Red -> True
other -> f (case x of
Green -> ...
Blue -> ... ) ...
The inner case does not need a Red alternative, because x can't be Red at
that program point.
| Cast (Expr b) Coercion | Cast an expression to a particular type. This is used to implement newtypes
(a newtype constructor or destructor just becomes a Cast in Core) and GADTs.
| Note Note (Expr b) | Notes. These allow general information to be
added to expressions in the syntax tree
| Type Type | A type: this should only show up at the top
level of an Arg
|
| Instances | |
|
|
type Alt b = (AltCon, [b], Expr b) |
A case split alternative. Consists of the constructor leading to the alternative,
the variables bound from the constructor, and the expression to be executed given that binding.
The default alternative is (DEFAULT, [], rhs)
|
|
data Bind b |
Binding, used for top level bindings in a module and local bindings in a let.
| Constructors | | Instances | |
|
|
data AltCon |
A case alternative constructor (i.e. pattern match)
| Constructors | DataAlt DataCon | A plain data constructor: case e of { Foo x -> ... }.
Invariant: the DataCon is always from a data type, and never from a newtype
| LitAlt Literal | A literal: case e of { 1 -> ... }
| DEFAULT | Trivial alternative: case e of { _ -> ... }
|
| Instances | |
|
|
type Arg b = Expr b |
Type synonym for expressions that occur in function argument positions.
Only Arg should contain a Type at top level, general Expr should not
|
|
data Note |
Allows attaching extra information to points in expressions rather than e.g. identifiers.
| Constructors | SCC CostCentre | A cost centre annotation for profiling
| InlineMe | Instructs the core simplifer to treat the enclosed expression
as very small, and inline it at its call sites
| CoreNote String | A generic core annotation, propagated but not used by GHC
|
|
|
|
type CoreExpr = Expr CoreBndr |
Expressions where binders are CoreBndrs
|
|
type CoreAlt = Alt CoreBndr |
Case alternatives where binders are CoreBndrs
|
|
type CoreBind = Bind CoreBndr |
Binding groups where binders are CoreBndrs
|
|
type CoreArg = Arg CoreBndr |
Argument expressions where binders are CoreBndrs
|
|
type CoreBndr = Var |
The common case for the type of binders and variables when
we are manipulating the Core language within GHC
|
|
type TaggedExpr t = Expr (TaggedBndr t) |
|
type TaggedAlt t = Alt (TaggedBndr t) |
|
type TaggedBind t = Bind (TaggedBndr t) |
|
type TaggedArg t = Arg (TaggedBndr t) |
|
data TaggedBndr t |
Binders are tagged with a t
| Constructors | | Instances | |
|
|
Expr construction
|
|
mkLets :: [Bind b] -> Expr b -> Expr b |
Bind all supplied binding groups over an expression in a nested let expression. Prefer to
use CoreUtils.mkCoreLets if possible
|
|
mkLams :: [b] -> Expr b -> Expr b |
Bind all supplied binders over an expression in a nested lambda expression. Prefer to
use CoreUtils.mkCoreLams if possible
|
|
mkApps :: Expr b -> [Arg b] -> Expr b |
Apply a list of argument expressions to a function expression in a nested fashion. Prefer to
use CoreUtils.mkCoreApps if possible
|
|
mkTyApps :: Expr b -> [Type] -> Expr b |
Apply a list of type argument expressions to a function expression in a nested fashion
|
|
mkVarApps :: Expr b -> [Var] -> Expr b |
Apply a list of type or value variables to a function expression in a nested fashion
|
|
mkIntLit :: Integer -> Expr b |
Create a machine integer literal expression of type Int# from an Integer.
If you want an expression of type Int use MkCore.mkIntExpr
|
|
mkIntLitInt :: Int -> Expr b |
Create a machine integer literal expression of type Int# from an Int.
If you want an expression of type Int use MkCore.mkIntExpr
|
|
mkWordLit :: Integer -> Expr b |
Create a machine word literal expression of type Word# from an Integer.
If you want an expression of type Word use MkCore.mkWordExpr
|
|
mkWordLitWord :: Word -> Expr b |
Create a machine word literal expression of type Word# from a Word.
If you want an expression of type Word use MkCore.mkWordExpr
|
|
mkCharLit :: Char -> Expr b |
Create a machine character literal expression of type Char#.
If you want an expression of type Char use MkCore.mkCharExpr
|
|
mkStringLit :: String -> Expr b |
Create a machine string literal expression of type Addr#.
If you want an expression of type String use MkCore.mkStringExpr
|
|
mkFloatLit :: Rational -> Expr b |
Create a machine single precision literal expression of type Float# from a Rational.
If you want an expression of type Float use MkCore.mkFloatExpr
|
|
mkFloatLitFloat :: Float -> Expr b |
Create a machine single precision literal expression of type Float# from a Float.
If you want an expression of type Float use MkCore.mkFloatExpr
|
|
mkDoubleLit :: Rational -> Expr b |
Create a machine double precision literal expression of type Double# from a Rational.
If you want an expression of type Double use MkCore.mkDoubleExpr
|
|
mkDoubleLitDouble :: Double -> Expr b |
Create a machine double precision literal expression of type Double# from a Double.
If you want an expression of type Double use MkCore.mkDoubleExpr
|
|
mkConApp :: DataCon -> [Arg b] -> Expr b |
Apply a list of argument expressions to a data constructor in a nested fashion. Prefer to
use MkCore.mkCoreConApps if possible
|
|
mkTyBind :: TyVar -> Type -> CoreBind |
Create a binding group where a type variable is bound to a type. Per CoreSyn#type_let,
this can only be used to bind something in a non-recursive let expression
|
|
varToCoreExpr :: CoreBndr -> Expr b |
Convert a binder into either a Var or Type Expr appropriately
|
|
varsToCoreExprs :: [CoreBndr] -> [Expr b] |
|
isTyVar :: Var -> Bool |
|
isIdVar :: Var -> Bool |
|
cmpAltCon :: AltCon -> AltCon -> Ordering |
Compares AltCons within a single list of alternatives
|
|
cmpAlt :: Alt b -> Alt b -> Ordering |
|
ltAlt :: Alt b -> Alt b -> Bool |
|
Simple Expr access functions and predicates
|
|
bindersOf :: Bind b -> [b] |
Extract every variable by this group
|
|
bindersOfBinds :: [Bind b] -> [b] |
bindersOf applied to a list of binding groups
|
|
rhssOfBind :: Bind b -> [Expr b] |
|
rhssOfAlts :: [Alt b] -> [Expr b] |
|
collectBinders :: Expr b -> ([b], Expr b) |
We often want to strip off leading lambdas before getting down to
business. This function is your friend.
|
|
collectTyBinders :: CoreExpr -> ([TyVar], CoreExpr) |
Collect as many type bindings as possible from the front of a nested lambda
|
|
collectValBinders :: CoreExpr -> ([Id], CoreExpr) |
Collect as many value bindings as possible from the front of a nested lambda
|
|
collectTyAndValBinders :: CoreExpr -> ([TyVar], [Id], CoreExpr) |
Collect type binders from the front of the lambda first,
then follow up by collecting as many value bindings as possible
from the resulting stripped expression
|
|
collectArgs :: Expr b -> (Expr b, [Arg b]) |
Takes a nested application expression and returns the the function
being applied and the arguments to which it is applied
|
|
coreExprCc :: Expr b -> CostCentre |
Gets the cost centre enclosing an expression, if any.
It looks inside lambdas because (scc "foo" \x.e) = \x. scc "foo" e
|
|
flattenBinds :: [Bind b] -> [(b, Expr b)] |
Collapse all the bindings in the supplied groups into a single
list of lhs/rhs pairs suitable for binding in a Rec binding group
|
|
isValArg :: Expr b -> Bool |
Returns False iff the expression is a Type expression at its top level
|
|
isTypeArg :: Expr b -> Bool |
Returns True iff the expression is a Type expression at its top level
|
|
valArgCount :: [Arg b] -> Int |
The number of argument expressions that are values rather than types at their top level
|
|
valBndrCount :: [CoreBndr] -> Int |
The number of binders that bind values rather than types
|
|
isRuntimeArg :: CoreExpr -> Bool |
Will this argument expression exist at runtime?
|
|
isRuntimeVar :: Var -> Bool |
Will this variable exist at runtime?
|
|
Unfolding data types
|
|
data Unfolding |
Records the unfolding of an identifier, which is approximately the form the
identifier would have if we substituted its definition in for the identifier.
This type should be treated as abstract everywhere except in CoreUnfold
| Constructors | NoUnfolding | We have no information about the unfolding
| OtherCon [AltCon] | It ain't one of these constructors.
OtherCon xs also indicates that something has been evaluated
and hence there's no point in re-evaluating it.
OtherCon [] is used even for non-data-type values
to indicated evaluated-ness. Notably:
data C = C !(Int -> Int)
case x of { C f -> ... }
Here, f gets an OtherCon [] unfolding.
| CompulsoryUnfolding CoreExpr | There is no original definition,
so you'd better unfold.
| CoreUnfolding CoreExpr Bool Bool Bool UnfoldingGuidance | An unfolding with redundant cached information. Parameters:
1) Template used to perform unfolding; binder-info is correct
2) Is this a top level binding?
3) exprIsHNF template (cached); it is ok to discard a seq on
this variable
4) Does this waste only a little work if we expand it inside an inlining?
Basically this is a cached version of exprIsCheap
5) Tells us about the size of the unfolding template
|
| Instances | |
|
|
data UnfoldingGuidance |
When unfolding should take place
| Constructors | | Instances | |
|
|
Constructing Unfoldings
|
|
noUnfolding :: Unfolding |
There is no known Unfolding
|
|
evaldUnfolding :: Unfolding |
This unfolding marks the associated thing as being evaluated
|
|
mkOtherCon :: [AltCon] -> Unfolding |
|
Predicates and deconstruction on Unfolding
|
|
unfoldingTemplate :: Unfolding -> CoreExpr |
Retrieves the template of an unfolding: panics if none is known
|
|
maybeUnfoldingTemplate :: Unfolding -> Maybe CoreExpr |
Retrieves the template of an unfolding if possible
|
|
otherCons :: Unfolding -> [AltCon] |
The constructors that the unfolding could never be:
returns [] if no information is available
|
|
isValueUnfolding :: Unfolding -> Bool |
Determines if it is certainly the case that the unfolding will
yield a value (something in HNF): returns False if unsure
|
|
isEvaldUnfolding :: Unfolding -> Bool |
Determines if it possibly the case that the unfolding will
yield a value. Unlike isValueUnfolding it returns True
for OtherCon
|
|
isCheapUnfolding :: Unfolding -> Bool |
Is the thing we will unfold into certainly cheap?
|
|
isCompulsoryUnfolding :: Unfolding -> Bool |
Must this unfolding happen for the code to be executable?
|
|
hasUnfolding :: Unfolding -> Bool |
Do we have an available or compulsory unfolding?
|
|
hasSomeUnfolding :: Unfolding -> Bool |
Only returns False if there is no unfolding information available at all
|
|
neverUnfold :: Unfolding -> Bool |
Similar to not . hasUnfolding, but also returns True
if it has an unfolding that says it should never occur
|
|
Strictness
|
|
seqExpr :: CoreExpr -> () |
|
seqExprs :: [CoreExpr] -> () |
|
seqUnfolding :: Unfolding -> () |
|
Annotated expression data types
|
|
type AnnExpr bndr annot = (annot, AnnExpr' bndr annot) |
Annotated core: allows annotation at every node in the tree
|
|
data AnnExpr' bndr annot |
A clone of the Expr type but allowing annotation at every tree node
| Constructors | |
|
|
data AnnBind bndr annot |
A clone of the Bind type but allowing annotation at every tree node
| Constructors | AnnNonRec bndr (AnnExpr bndr annot) | | AnnRec [(bndr, AnnExpr bndr annot)] | |
|
|
|
type AnnAlt bndr annot = (AltCon, [bndr], AnnExpr bndr annot) |
A clone of the Alt type but allowing annotation at every tree node
|
|
Operations on annotations
|
|
deAnnotate :: AnnExpr bndr annot -> Expr bndr |
|
deAnnotate' :: AnnExpr' bndr annot -> Expr bndr |
|
deAnnAlt :: AnnAlt bndr annot -> Alt bndr |
|
collectAnnBndrs :: AnnExpr bndr annot -> ([bndr], AnnExpr bndr annot) |
As collectBinders but for AnnExpr rather than Expr
|
|
Core rule data types
|
|
data CoreRule |
A CoreRule is:
- "Local" if the function it is a rule for is defined in the
same module as the rule itself.
- "Orphan" if nothing on the LHS is defined in the same module
as the rule itself
| Constructors | Rule | | ru_name :: RuleName | Name of the rule, for communication with the user
| ru_act :: Activation | When the rule is active
| ru_fn :: Name | Name of the Id.Id at the head of this rule
| ru_rough :: [Maybe Name] | Name at the head of each argument to the left hand side
| ru_bndrs :: [CoreBndr] | Variables quantified over
| ru_args :: [CoreExpr] | Left hand side arguments
| ru_rhs :: CoreExpr | Right hand side of the rule
| ru_local :: Bool | True iff the fn at the head of the rule is
defined in the same module as the rule
and is not an implicit Id (like a record selector,
class operation, or data constructor)
|
| BuiltinRule | Built-in rules are used for constant folding
and suchlike. They have no free variables.
| ru_name :: RuleName | As above
| ru_fn :: Name | As above
| ru_nargs :: Int | Number of arguments that ru_try expects,
including type arguments
| ru_try :: [CoreExpr] -> Maybe CoreExpr | This function does the rewrite. It given too many
arguments, it simply discards them; the returned CoreExpr
is just the rewrite of ru_fn applied to the first ru_nargs args
|
|
| Instances | |
|
|
type RuleName = FastString |
|
Operations on CoreRules
|
|
seqRules :: [CoreRule] -> () |
|
ruleArity :: CoreRule -> Int |
The number of arguments the ru_fn must be applied
to before the rule can match on it
|
|
ruleName :: CoreRule -> RuleName |
|
ruleIdName :: CoreRule -> Name |
The Name of the Id.Id at the head of the rule left hand side
|
|
ruleActivation_maybe :: CoreRule -> Maybe Activation |
|
setRuleIdName :: Name -> CoreRule -> CoreRule |
Set the Name of the Id.Id at the head of the rule left hand side
|
|
isBuiltinRule :: CoreRule -> Bool |
|
isLocalRule :: CoreRule -> Bool |
|
Produced by Haddock version 2.3.0 |