... | @@ -37,7 +37,7 @@ data Expr b -- "b" for the type of binders, |
... | @@ -37,7 +37,7 @@ data Expr b -- "b" for the type of binders, |
|
| Let (Bind b) (Expr b)
|
|
| Let (Bind b) (Expr b)
|
|
| Case (Expr b) b Type [Alt b]
|
|
| Case (Expr b) b Type [Alt b]
|
|
| Cast (Expr b) Coercion
|
|
| Cast (Expr b) Coercion
|
|
| Note Note (Expr b)
|
|
| Tick (Tickish Id) (Expr b)
|
|
| Type Type
|
|
| Type Type
|
|
|
|
|
|
type Arg b = Expr b
|
|
type Arg b = Expr b
|
... | @@ -52,6 +52,10 @@ data Bind b = NonRec b (Expr b) | Rec [(b, (Expr b))] |
... | @@ -52,6 +52,10 @@ data Bind b = NonRec b (Expr b) | Rec [(b, (Expr b))] |
|
That's it. All of Haskell gets compiled through this tiny core.
|
|
That's it. All of Haskell gets compiled through this tiny core.
|
|
|
|
|
|
`Expr` is parameterised over the type of its *binders*, `b`. This facility is used only rarely, and always temporarily; for example, the let-floater `SetLevels` pass attaches a binding level to every binder. By far the most important type is `CoreExpr`, which is `Expr` with `Var` binders.
|
|
`Expr` is parameterised over the type of its *binders*, `b`. This facility is used only rarely, and always temporarily; for example, the let-floater `SetLevels` pass attaches a binding level to every binder. By far the most important type is `CoreExpr`, which is `Expr` with `Var` binders.
|
|
|
|
If you want to learn more about such AST-parametrization, I encourage you to read a blog post about it: [ http://blog.ezyang.com/2013/05/the-ast-typing-problem](http://blog.ezyang.com/2013/05/the-ast-typing-problem) .
|
|
|
|
|
|
|
|
|
|
|
|
Binder is used (as the name suggest) to bind a variable to an expression. The `Expr` data type is parametrized by the binder type. The most common one is the `type CoreBndr = Var` where `Var` comes from [compiler/basicTypes/Var.hs](/trac/ghc/browser/ghc/compiler/basicTypes/Var.hs), which in fact is a `Name` with some extra informations attached (like types).
|
|
|
|
|
|
|
|
|
|
Here are some notes about the individual constructors of `Expr`.
|
|
Here are some notes about the individual constructors of `Expr`.
|
... | @@ -60,15 +64,15 @@ Here are some notes about the individual constructors of `Expr`. |
... | @@ -60,15 +64,15 @@ Here are some notes about the individual constructors of `Expr`. |
|
|
|
|
|
- `Lam` is used for both term and type abstraction (small and big lambdas).
|
|
- `Lam` is used for both term and type abstraction (small and big lambdas).
|
|
|
|
|
|
- `Type` appears only in type-argument positions (e.g. `App (Var f) (Type ty)`). To emphasise this, the type synonym `Arg` is used as documentation when we expect that a `Type` constructor may show up. Anything not called `Arg` should not use a `Type` constructor.
|
|
- `Type` appears only in type-argument positions (e.g. `App (Var f) (Type ty)`). To emphasise this, the type synonym `Arg` is used as documentation when we expect that a `Type` constructor may show up. Anything not called `Arg` should not use a `Type` constructor. Additional GHC Core uses so called type-lambdas, they are like lambdas, but instead of taking a real argument, they take a type instead. You should not confuse them with TypeFamilies, because type-lambdas are working on a value level, while type families are functions on the type level. The simplies example for a type-lambda usage is a polymorphic one: `\x -> x`. It will be represented in Core as `A.id = \ (@ t_aeK) (x_aeG :: t_aeK) -> x_aeG`, where `t_aeK` is a \*type argument\*, so when specyfying the argument of `x_aeG` we can refer to `t_aeK`. This is how polymorphism is represented in Core.
|
|
|
|
|
|
- `Let` handles both recursive and non-recursive let-bindings; see the the two constructors for `Bind`.
|
|
- `Let` handles both recursive and non-recursive let-bindings; see the the two constructors for `Bind`. The Let constructor contains both binders as well as the resulting expression. The resulting expression is the `e` in expression `let x = r in e`.
|
|
|
|
|
|
- `Case` expressions need [more explanation](commentary/compiler/core-syn-type#case-expressions).
|
|
- `Case` expressions need [more explanation](commentary/compiler/core-syn-type#case-expressions).
|
|
|
|
|
|
- `Cast` is used for an [FC cast expression](commentary/compiler/fc). `Coercion` is a synonym for `Type`.
|
|
- `Cast` is used for an [FC cast expression](commentary/compiler/fc). `Coercion` is a synonym for `Type`.
|
|
|
|
|
|
- `Note` is used for profiling and debugging information.
|
|
- `Tick` is used to represent all the kinds of source annotation we support: profiling SCCs, HPC ticks, and GHCi breakpoints. Was named `Note` some time ago.
|
|
|
|
|
|
## Case expressions
|
|
## Case expressions
|
|
|
|
|
... | @@ -168,3 +172,8 @@ variables that actually capture names of some earlier ones. For some more |
... | @@ -168,3 +172,8 @@ variables that actually capture names of some earlier ones. For some more |
|
explanations about this approach see
|
|
explanations about this approach see
|
|
[ Secrets of the Glasgow Haskell Compiler inliner (JFP'02)](http://research.microsoft.com/%7Esimonpj/Papers/inlining/index.htm)
|
|
[ Secrets of the Glasgow Haskell Compiler inliner (JFP'02)](http://research.microsoft.com/%7Esimonpj/Papers/inlining/index.htm)
|
|
(section 4 on name capture).
|
|
(section 4 on name capture).
|
|
|
|
|
|
|
|
## Human readable Core generation
|
|
|
|
|
|
|
|
|
|
|
|
If you are interested in the way Core is translated into human readable form, you should check the sources for [compiler/coreSyn/PprCore.hs](/trac/ghc/browser/ghc/compiler/coreSyn/PprCore.hs). It is especially usefull if you want to see how the Core data types are being build, especially when there is no Show instance defined for them. |