diff options
author | Simon Peyton Jones <simonpj@microsoft.com> | 2016-07-20 15:28:10 +0100 |
---|---|---|
committer | Simon Peyton Jones <simonpj@microsoft.com> | 2016-07-21 09:49:44 +0100 |
commit | a09c0e3e68c96882a1fb392c9dbeea84056bf32f (patch) | |
tree | 2561e24a794b46747a4f38181869cd8882f15781 /compiler/prelude/TysPrim.hs | |
parent | 714bebff44076061d0a719c4eda2cfd213b7ac3d (diff) | |
download | haskell-a09c0e3e68c96882a1fb392c9dbeea84056bf32f.tar.gz |
Comments only
Diffstat (limited to 'compiler/prelude/TysPrim.hs')
-rw-r--r-- | compiler/prelude/TysPrim.hs | 127 |
1 files changed, 88 insertions, 39 deletions
diff --git a/compiler/prelude/TysPrim.hs b/compiler/prelude/TysPrim.hs index 19728ee430..7430ec82c1 100644 --- a/compiler/prelude/TysPrim.hs +++ b/compiler/prelude/TysPrim.hs @@ -351,43 +351,91 @@ funTyCon = mkFunTyCon funTyConName tc_bndrs tc_rep_nm * * ************************************************************************ -Note [TYPE] -~~~~~~~~~~~ -There are a few places where we wish to be able to deal interchangeably -with kind * and kind #. unsafeCoerce#, error, and (->) are some of these -places. The way we do this is to use runtime-representation polymorphism. - -We have - - data RuntimeRep = PtrRepLifted | PtrRepUnlifted | ... - -and a magical constant (tYPETyCon) - - TYPE :: RuntimeRep -> TYPE PtrRepLifted - -We then have synonyms (liftedTypeKindTyCon, unliftedTypeKindTyCon) - - type * = TYPE PtrRepLifted - type # = TYPE PtrRepUnlifted - -The (...) in the definition for RuntimeRep includes possibilities for -the unboxed, unlifted representations, isomorphic to the PrimRep type -in TyCon. RuntimeRep is itself declared in GHC.Types. - -An alternative design would be to have - - data RuntimeRep = PtrRep Levity | ... - data Levity = Lifted | Unlifted - -but this slowed down GHC because every time we looked at *, we had to -follow a bunch of pointers. When we have unpackable sums, we should -go back to the stratified representation. This would allow, for example: - - unsafeCoerce# :: forall (r1 :: RuntimeRep) (v2 :: Levity) - (a :: TYPE v1) (b :: TYPE v2). a -> b - -TYPE replaces the old sub-kinding machinery. We call variables `a` and `b` -above "runtime-representation polymorphic". +Note [TYPE and RuntimeRep] +~~~~~~~~~~~~~~~~~~~~~~~~~~ +All types that classify values have a kind of the form (TYPE rr), where + + data RuntimeRep -- Defined in ghc-prim:GHC.Types + = PtrRepLifted + | PtrRepUnlifted + | IntRep + | FloatRep + .. etc .. + + rr :: RuntimeRep + + TYPE :: RuntimeRep -> TYPE 'PtrRepLifted -- Built in + +So for example: + Int :: TYPE 'PtrRepLifted + Array# Int :: TYPE 'PtrRepUnlifted + Int# :: TYPE 'IntRep + Float# :: TYPE 'FloatRep + Maybe :: TYPE 'PtrRepLifted -> TYPE 'PtrRepLifted + +We abbreviate '*' specially: + type * = TYPE 'PtrRepLifted + +The 'rr' parameter tells us how the value is represented at runime. + +Generally speaking, you can't be polymorphic in 'rr'. E.g + f :: forall (rr:RuntimeRep) (a:TYPE rr). a -> [a] + f = /\(rr:RuntimeRep) (a:rr) \(a:rr). ... +This is no good: we could not generate code code for 'f', because the +calling convention for 'f' varies depending on whether the argument is +a a Int, Int#, or Float#. (You could imagine generating specialised +code, one for each instantiation of 'rr', but we don't do that.) + +Certain functions CAN be runtime-rep-polymorphic, because the code +generator never has to manipulate a value of type 'a :: TYPE rr'. + +* error :: forall (rr:RuntimeRep) (a:TYPE rr). String -> a + Code generator never has to manipulate the return value. + +* unsafeCoerce#, defined in MkId.unsafeCoerceId: + Always inlined to be a no-op + unsafeCoerce# :: forall (r1 :: RuntimeRep) (r2 :: RuntimeRep) + (a :: TYPE r1) (b :: TYPE r2). + a -> b + +* Unboxed tuples, and unboxed sums, defined in TysWiredIn + Always inlined, and hence specialised to the call site + (#,#) :: forall (r1 :: RuntimeRep) (r2 :: RuntimeRep) + (a :: TYPE r1) (b :: TYPE r2). + a -> b -> TYPE 'UnboxedTupleRep + See Note [Unboxed tuple kinds] + +Note [Unboxed tuple kinds] +~~~~~~~~~~~~~~~~~~~~~~~~~~ +What kind does (# Int, Float# #) have? +The "right" answer would be + TYPE ('UnboxedTupleRep [PtrRepLifted, FloatRep]) +Currently we do not do this. We just have + (# Int, Float# #) :: TYPE 'UnboxedTupleRep +which does not tell us exactly how is is represented. + +Note [PrimRep and kindPrimRep] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +As part of its source code, in TyCon, GHC has + data PrimRep = PtrRep | IntRep | FloatRep | ...etc... + +Notice that + * RuntimeRep is part of the syntax tree of the program being compiled + (defined in a library: ghc-prim:GHC.Types) + * PrimRep is part of GHC's source code. + (defined in TyCon) + +We need to get from one to the other; that is what kindPrimRep does. +Suppose we have a value + (v :: t) where (t :: k) +Given this kind + k = TyConApp "TYPE" [rep] +GHC needs to be able to figure out how 'v' is represented at runtime. +It expects 'rep' to be form + TyConApp rr_dc args +where 'rr_dc' is a promoteed data constructor from RuntimeRep. So +now we need to go from 'dc' to the correponding PrimRep. We store this +PrimRep in the promoted data constructor itself: see TyCon.promDcRepInfo. -} @@ -400,7 +448,7 @@ tYPETyCon = mkKindTyCon tYPETyConName [Nominal] (mkPrelTyConRepName tYPETyConName) - -- See Note [TYPE] + -- See Note [TYPE and RuntimeRep] -- NB: unlifted is wired in because there is no way to parse it in -- Haskell. That's the only reason for wiring it in. unliftedTypeKindTyCon = mkSynonymTyCon unliftedTypeKindTyConName @@ -425,7 +473,8 @@ mkPrimTcName built_in_syntax occ key tycon = mkWiredInName gHC_PRIM (mkTcOccFS occ) key (ATyCon tycon) built_in_syntax ----------------------------- --- | Given a RuntimeRep, applies TYPE to it. See Note [TYPE]. +-- | Given a RuntimeRep, applies TYPE to it. +-- see Note [TYPE and RuntimeRep] tYPE :: Type -> Type tYPE rr = TyConApp tYPETyCon [rr] |