View patterns, record wildcards, and record puns
[ghc-hetmet.git] / compiler / iface / IfaceSyn.lhs
index 267a8cc..44ce235 100644 (file)
@@ -4,11 +4,18 @@
 %
 
 \begin{code}
+{-# OPTIONS -w #-}
+-- The above warning supression flag is a temporary kludge.
+-- While working on this module you are encouraged to remove it and fix
+-- any warnings in the module. See
+--     http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings
+-- for details
+
 module IfaceSyn (
        module IfaceType,               -- Re-export all this
 
        IfaceDecl(..), IfaceClassOp(..), IfaceConDecl(..), IfaceConDecls(..),
-       IfaceExpr(..), IfaceAlt, IfaceNote(..),
+       IfaceExpr(..), IfaceAlt, IfaceNote(..), IfaceLetBndr(..),
        IfaceBinding(..), IfaceConAlt(..), IfaceIdInfo(..),
        IfaceInfoItem(..), IfaceRule(..), IfaceInst(..), IfaceFamInst(..),
 
@@ -39,6 +46,7 @@ import ForeignCall
 import BasicTypes
 import Outputable
 import FastString
+import Module
 
 import Data.List
 import Data.Maybe
@@ -77,14 +85,21 @@ data IfaceDecl
                                                -- current compilation unit 
                 ifFamInst    :: Maybe (IfaceTyCon, [IfaceType])
                                                 -- Just <=> instance of family
+                                                -- Invariant: 
+                                                --   ifCons /= IfOpenDataTyCon
+                                                --   for family instances
     }
 
   | IfaceSyn  {        ifName    :: OccName,           -- Type constructor
                ifTyVars  :: [IfaceTvBndr],     -- Type variables
                ifOpenSyn :: Bool,              -- Is an open family?
-               ifSynRhs  :: IfaceType          -- Type for an ordinary
+               ifSynRhs  :: IfaceType,         -- Type for an ordinary
                                                -- synonym and kind for an
                                                -- open family
+                ifFamInst    :: Maybe (IfaceTyCon, [IfaceType])
+                                                -- Just <=> instance of family
+                                                -- Invariant: ifOpenSyn == False
+                                                --   for family instances
     }
 
   | IfaceClass { ifCtxt    :: IfaceContext,    -- Context...
@@ -108,14 +123,12 @@ data IfaceClassOp = IfaceClassOp OccName DefMeth IfaceType
 data IfaceConDecls
   = IfAbstractTyCon            -- No info
   | IfOpenDataTyCon            -- Open data family
-  | IfOpenNewTyCon             -- Open newtype family
   | IfDataTyCon [IfaceConDecl] -- data type decls
   | IfNewTyCon  IfaceConDecl   -- newtype decls
 
 visibleIfConDecls :: IfaceConDecls -> [IfaceConDecl]
 visibleIfConDecls IfAbstractTyCon  = []
 visibleIfConDecls IfOpenDataTyCon  = []
-visibleIfConDecls IfOpenNewTyCon   = []
 visibleIfConDecls (IfDataTyCon cs) = cs
 visibleIfConDecls (IfNewTyCon c)   = [c]
 
@@ -203,6 +216,7 @@ data IfaceExpr
   | IfaceCast   IfaceExpr IfaceCoercion
   | IfaceLit   Literal
   | IfaceFCall ForeignCall IfaceType
+  | IfaceTick   Module Int
 
 data IfaceNote = IfaceSCC CostCentre
               | IfaceInlineMe
@@ -219,10 +233,27 @@ data IfaceConAlt = IfaceDefault
                 | IfaceLitAlt Literal
 
 data IfaceBinding
-  = IfaceNonRec        IfaceIdBndr IfaceExpr
-  | IfaceRec   [(IfaceIdBndr, IfaceExpr)]
+  = IfaceNonRec        IfaceLetBndr IfaceExpr
+  | IfaceRec   [(IfaceLetBndr, IfaceExpr)]
+
+-- IfaceLetBndr is like IfaceIdBndr, but has IdInfo too
+-- It's used for *non-top-level* let/rec binders
+-- See Note [IdInfo on nested let-bindings]
+data IfaceLetBndr = IfLetBndr FastString IfaceType IfaceIdInfo
 \end{code}
 
+Note [IdInfo on nested let-bindings]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Occasionally we want to preserve IdInfo on nested let bindings The one
+that came up was a NOINLINE pragma on a let-binding inside an INLINE
+function.  The user (Duncan Coutts) really wanted the NOINLINE control
+to cross the separate compilation boundary.
+
+So a IfaceLetBndr keeps a trimmed-down list of IfaceIdInfo stuff.
+Currently we only actually retain InlinePragInfo, but in principle we could
+add strictness etc.
+
+
 Note [Orphans]: the ifInstOrph and ifRuleOrph fields
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 If a module contains any "orphans", then its interface file is read
@@ -307,56 +338,80 @@ ifaceDeclSubBndrs :: IfaceDecl -> [OccName]
 -- Deeply revolting, because it has to predict what gets bound,
 -- especially the question of whether there's a wrapper for a datacon
 
-ifaceDeclSubBndrs (IfaceClass {ifCtxt = sc_ctxt, ifName = cls_occ, 
-                              ifSigs = sigs, ifATs = ats })
-  = co_occs ++
-    [tc_occ, dc_occ, dcww_occ] ++
-    [op | IfaceClassOp op  _ _ <- sigs] ++
-    [ifName at | at <- ats ] ++
-    [mkSuperDictSelOcc n cls_occ | n <- [1..n_ctxt]] 
-  where
-    n_ctxt = length sc_ctxt
-    n_sigs = length sigs
-    tc_occ  = mkClassTyConOcc cls_occ
-    dc_occ  = mkClassDataConOcc cls_occ        
-    co_occs | is_newtype = [mkNewTyCoOcc tc_occ]
-           | otherwise  = []
-    dcww_occ -- | is_newtype = mkDataConWrapperOcc dc_occ      -- Newtypes have wrapper but no worker
-            | otherwise  = mkDataConWorkerOcc dc_occ   -- Otherwise worker but no wrapper
-    is_newtype = n_sigs + n_ctxt == 1                  -- Sigh 
+-- N.B. the set of names returned here *must* match the set of
+-- TyThings returned by HscTypes.implicitTyThings, in the sense that
+-- TyThing.getOccName should define a bijection between the two lists.
+-- This invariant is used in LoadIface.loadDecl (see note [Tricky iface loop])
+-- The order of the list does not matter.
+ifaceDeclSubBndrs IfaceData {ifCons = IfAbstractTyCon}  = []
 
-ifaceDeclSubBndrs IfaceData {ifCons = IfAbstractTyCon}
-  = []
 -- Newtype
 ifaceDeclSubBndrs (IfaceData {ifName = tc_occ,
-                             ifCons = IfNewTyCon (
-                                        IfCon { ifConOcc = con_occ, 
-                                                          ifConFields = fields
-                                                        }),
-                             ifFamInst = famInst}) 
-  = fields ++ [con_occ, mkDataConWorkerOcc con_occ, mkNewTyCoOcc tc_occ]
-    ++ famInstCo famInst tc_occ
+                              ifCons = IfNewTyCon (
+                                        IfCon { ifConOcc = con_occ, 
+                                                ifConFields = fields
+                                                 }),
+                              ifFamInst = famInst}) 
+  = -- fields (names of selectors)
+    fields ++ 
+    -- implicit coerion and (possibly) family instance coercion
+    (mkNewTyCoOcc tc_occ) : (famInstCo famInst tc_occ) ++
+    -- data constructor and worker (newtypes don't have a wrapper)
+    [con_occ, mkDataConWorkerOcc con_occ]
+
 
 ifaceDeclSubBndrs (IfaceData {ifName = tc_occ,
                              ifCons = IfDataTyCon cons, 
                              ifFamInst = famInst})
-  = nub (concatMap ifConFields cons)   -- Eliminate duplicate fields
-    ++ concatMap dc_occs cons
+  = -- fields (names of selectors) 
+    nub (concatMap ifConFields cons)   -- Eliminate duplicate fields
+    -- (possibly) family instance coercion;
+    -- there is no implicit coercion for non-newtypes
     ++ famInstCo famInst tc_occ
+    -- for each data constructor in order,
+    --    data constructor, worker, and (possibly) wrapper
+    ++ concatMap dc_occs cons
   where
     dc_occs con_decl
        | has_wrapper = [con_occ, work_occ, wrap_occ]
        | otherwise   = [con_occ, work_occ]
        where
-         con_occ = ifConOcc con_decl
-         strs    = ifConStricts con_decl
-         wrap_occ = mkDataConWrapperOcc con_occ
-         work_occ = mkDataConWorkerOcc con_occ
+         con_occ  = ifConOcc con_decl                  -- DataCon namespace
+         wrap_occ = mkDataConWrapperOcc con_occ        -- Id namespace
+         work_occ = mkDataConWorkerOcc con_occ         -- Id namespace
+         strs     = ifConStricts con_decl
          has_wrapper = any isMarkedStrict strs -- See MkId.mkDataConIds (sigh)
                        || not (null . ifConEqSpec $ con_decl)
                        || isJust famInst
                -- ToDo: may miss strictness in existential dicts
 
+ifaceDeclSubBndrs (IfaceClass {ifCtxt = sc_ctxt, ifName = cls_occ, 
+                              ifSigs = sigs, ifATs = ats })
+  = -- dictionary datatype:
+    --   type constructor
+    tc_occ : 
+    --   (possibly) newtype coercion
+    co_occs ++
+    --    data constructor (DataCon namespace)
+    --    data worker (Id namespace)
+    --    no wrapper (class dictionaries never have a wrapper)
+    [dc_occ, dcww_occ] ++
+    -- associated types
+    [ifName at | at <- ats ] ++
+    -- superclass selectors
+    [mkSuperDictSelOcc n cls_occ | n <- [1..n_ctxt]] ++
+    -- operation selectors
+    [op | IfaceClassOp op  _ _ <- sigs]
+  where
+    n_ctxt = length sc_ctxt
+    n_sigs = length sigs
+    tc_occ  = mkClassTyConOcc cls_occ
+    dc_occ  = mkClassDataConOcc cls_occ        
+    co_occs | is_newtype = [mkNewTyCoOcc tc_occ]
+           | otherwise  = []
+    dcww_occ = mkDataConWorkerOcc dc_occ
+    is_newtype = n_sigs + n_ctxt == 1                  -- Sigh 
+
 ifaceDeclSubBndrs _other = []
 
 -- coercion for data/newtype family instances
@@ -376,9 +431,10 @@ pprIfaceDecl (IfaceForeign {ifName = tycon})
   = hsep [ptext SLIT("foreign import type dotnet"), ppr tycon]
 
 pprIfaceDecl (IfaceSyn {ifName = tycon, ifTyVars = tyvars, 
-                       ifOpenSyn = False, ifSynRhs = mono_ty})
+                       ifOpenSyn = False, ifSynRhs = mono_ty, 
+                        ifFamInst = mbFamInst})
   = hang (ptext SLIT("type") <+> pprIfaceDeclHead [] tycon tyvars)
-       4 (equals <+> ppr mono_ty)
+       4 (vcat [equals <+> ppr mono_ty, pprFamily mbFamInst])
 
 pprIfaceDecl (IfaceSyn {ifName = tycon, ifTyVars = tyvars, 
                        ifOpenSyn = True, ifSynRhs = mono_ty})
@@ -397,7 +453,6 @@ pprIfaceDecl (IfaceData {ifName = tycon, ifGeneric = gen, ifCtxt = context,
                IfOpenDataTyCon -> ptext SLIT("data family")
                IfDataTyCon _   -> ptext SLIT("data")
                IfNewTyCon _    -> ptext SLIT("newtype")
-               IfOpenNewTyCon  -> ptext SLIT("newtype family")
 
 pprIfaceDecl (IfaceClass {ifCtxt = context, ifName = clas, ifTyVars = tyvars, 
                          ifFDs = fds, ifATs = ats, ifSigs = sigs, 
@@ -423,7 +478,6 @@ pprIfaceDeclHead context thing tyvars
          pprIfaceTvBndrs tyvars]
 
 pp_condecls tc IfAbstractTyCon  = ptext SLIT("{- abstract -}")
-pp_condecls tc IfOpenNewTyCon   = empty
 pp_condecls tc (IfNewTyCon c)   = equals <+> pprIfaceConDecl tc c
 pp_condecls tc IfOpenDataTyCon  = empty
 pp_condecls tc (IfDataTyCon cs) = equals <+> sep (punctuate (ptext SLIT(" |"))
@@ -499,6 +553,7 @@ pprIfaceExpr add_par (IfaceLcl v)       = ppr v
 pprIfaceExpr add_par (IfaceExt v)       = ppr v
 pprIfaceExpr add_par (IfaceLit l)       = ppr l
 pprIfaceExpr add_par (IfaceFCall cc ty) = braces (ppr cc <+> ppr ty)
+pprIfaceExpr add_par (IfaceTick m ix)   = braces (text "tick" <+> ppr m <+> ppr ix)
 pprIfaceExpr add_par (IfaceType ty)     = char '@' <+> pprParendIfaceType ty
 
 pprIfaceExpr add_par app@(IfaceApp _ _) = add_par (pprIfaceApp app [])
@@ -549,8 +604,9 @@ ppr_alt (con, bs, rhs) = sep [ppr_con_bs con bs,
 ppr_con_bs (IfaceTupleAlt tup_con) bs = tupleParens tup_con (interpp'SP bs)
 ppr_con_bs con bs                    = ppr con <+> hsep (map ppr bs)
   
-ppr_bind ((b,ty),rhs) = sep [ppr b <+> dcolon <+> ppr ty, 
-                            equals <+> pprIfaceExpr noParens rhs]
+ppr_bind (IfLetBndr b ty info, rhs) 
+  = sep [hang (ppr b <+> dcolon <+> ppr ty) 2 (ppr info),
+        equals <+> pprIfaceExpr noParens rhs]
 
 ------------------
 pprIfaceApp (IfaceApp fun arg) args = pprIfaceApp fun (nest 2 (pprIfaceExpr parens arg) : args)
@@ -572,16 +628,17 @@ instance Outputable IfaceConAlt where
 
 ------------------
 instance Outputable IfaceIdInfo where
-   ppr NoInfo       = empty
-   ppr (HasInfo is) = ptext SLIT("{-") <+> fsep (map ppr_hs_info is) <+> ptext SLIT("-}")
+  ppr NoInfo       = empty
+  ppr (HasInfo is) = ptext SLIT("{-") <+> fsep (map ppr is) <+> ptext SLIT("-}")
 
-ppr_hs_info (HsUnfold unf)     = ptext SLIT("Unfolding:") <+>
+instance Outputable IfaceInfoItem where
+  ppr (HsUnfold unf)    = ptext SLIT("Unfolding:") <+>
                                        parens (pprIfaceExpr noParens unf)
-ppr_hs_info (HsInline act)      = ptext SLIT("Inline:") <+> ppr act
-ppr_hs_info (HsArity arity)     = ptext SLIT("Arity:") <+> int arity
-ppr_hs_info (HsStrictness str)  = ptext SLIT("Strictness:") <+> pprIfaceStrictSig str
-ppr_hs_info HsNoCafRefs                = ptext SLIT("HasNoCafRefs")
-ppr_hs_info (HsWorker w a)     = ptext SLIT("Worker:") <+> ppr w <+> int a
+  ppr (HsInline act)     = ptext SLIT("Inline:") <+> ppr act
+  ppr (HsArity arity)    = ptext SLIT("Arity:") <+> int arity
+  ppr (HsStrictness str) = ptext SLIT("Strictness:") <+> pprIfaceStrictSig str
+  ppr HsNoCafRefs       = ptext SLIT("HasNoCafRefs")
+  ppr (HsWorker w a)    = ptext SLIT("Worker:") <+> ppr w <+> int a
 \end{code}
 
 
@@ -697,14 +754,10 @@ eqIfDecl d1@(IfaceData {}) d2@(IfaceData {})
        -- The type variables of the data type do not scope
        -- over the constructors (any more), but they do scope
        -- over the stupid context in the IfaceConDecls
-  where
-    Nothing             `eqIfTc_fam` Nothing             = Equal
-    (Just (fam1, tys1)) `eqIfTc_fam` (Just (fam2, tys2)) = 
-      fam1 `eqIfTc` fam2 &&& eqListBy eqIfType tys1 tys2
-    _                  `eqIfTc_fam` _                   = NotEqual
 
 eqIfDecl d1@(IfaceSyn {}) d2@(IfaceSyn {})
   = bool (ifName d1 == ifName d2) &&&
+    ifFamInst d1 `eqIfTc_fam` ifFamInst d2 &&&
     eqWith (ifTyVars d1) (ifTyVars d2) (\ env -> 
           eq_ifType env (ifSynRhs d1) (ifSynRhs d2)
         )
@@ -725,6 +778,15 @@ eqIfDecl _ _ = NotEqual    -- default case
 eqWith :: [IfaceTvBndr] -> [IfaceTvBndr] -> (EqEnv -> IfaceEq) -> IfaceEq
 eqWith = eq_ifTvBndrs emptyEqEnv
 
+eqIfTc_fam :: Maybe (IfaceTyCon, [IfaceType]) 
+           -> Maybe (IfaceTyCon, [IfaceType])
+           -> IfaceEq
+Nothing             `eqIfTc_fam` Nothing             = Equal
+(Just (fam1, tys1)) `eqIfTc_fam` (Just (fam2, tys2)) = 
+  fam1 `eqIfTc` fam2 &&& eqListBy eqIfType tys1 tys2
+_                      `eqIfTc_fam` _               = NotEqual
+
+
 -----------------------
 eqIfInst d1 d2 = bool (ifDFun d1 == ifDFun d2 && ifOFlag d1 == ifOFlag d2)
 -- All other changes are handled via the version info on the dfun
@@ -747,7 +809,6 @@ eq_hsCD env (IfDataTyCon c1) (IfDataTyCon c2)
 eq_hsCD env (IfNewTyCon c1)  (IfNewTyCon c2)  = eq_ConDecl env c1 c2
 eq_hsCD env IfAbstractTyCon  IfAbstractTyCon  = Equal
 eq_hsCD env IfOpenDataTyCon  IfOpenDataTyCon  = Equal
-eq_hsCD env IfOpenNewTyCon   IfOpenNewTyCon   = Equal
 eq_hsCD env d1              d2               = NotEqual
 
 eq_ConDecl env c1 c2
@@ -788,6 +849,7 @@ eq_ifaceExpr env (IfaceLcl v1)            (IfaceLcl v2)        = eqIfOcc env v1 v2
 eq_ifaceExpr env (IfaceExt v1)       (IfaceExt v2)        = eqIfExt v1 v2
 eq_ifaceExpr env (IfaceLit l1)        (IfaceLit l2)       = bool (l1 == l2)
 eq_ifaceExpr env (IfaceFCall c1 ty1)  (IfaceFCall c2 ty2)  = bool (c1==c2) &&& eq_ifType env ty1 ty2
+eq_ifaceExpr env (IfaceTick m1 ix1)   (IfaceTick m2 ix2)   = bool (m1==m2) &&& bool (ix1 == ix2)
 eq_ifaceExpr env (IfaceType ty1)      (IfaceType ty2)     = eq_ifType env ty1 ty2
 eq_ifaceExpr env (IfaceTuple n1 as1)  (IfaceTuple n2 as2)  = bool (n1==n2) &&& eqListBy (eq_ifaceExpr env) as1 as2
 eq_ifaceExpr env (IfaceLam b1 body1)  (IfaceLam b2 body2)  = eq_ifBndr env b1 b2 (\env -> eq_ifaceExpr env body1 body2)
@@ -805,10 +867,10 @@ eq_ifaceExpr env (IfaceCase s1 b1 ty1 as1) (IfaceCase s2 b2 ty2 as2)
          eq_ifNakedBndrs env bs1 bs2 (\env -> eq_ifaceExpr env r1 r2)
 
 eq_ifaceExpr env (IfaceLet (IfaceNonRec b1 r1) x1) (IfaceLet (IfaceNonRec b2 r2) x2)
-  = eq_ifaceExpr env r1 r2 &&& eq_ifIdBndr env b1 b2 (\env -> eq_ifaceExpr env x1 x2)
+  = eq_ifaceExpr env r1 r2 &&& eq_ifLetBndr env b1 b2 (\env -> eq_ifaceExpr env x1 x2)
 
 eq_ifaceExpr env (IfaceLet (IfaceRec as1) x1) (IfaceLet (IfaceRec as2) x2)
-  = eq_ifIdBndrs env bs1 bs2 (\env -> eqListBy (eq_ifaceExpr env) rs1 rs2 &&& eq_ifaceExpr env x1 x2)
+  = eq_ifLetBndrs env bs1 bs2 (\env -> eqListBy (eq_ifaceExpr env) rs1 rs2 &&& eq_ifaceExpr env x1 x2)
   where
     (bs1,rs1) = unzip as1
     (bs2,rs2) = unzip as2
@@ -909,14 +971,17 @@ eq_ifBndr _ _ _ _ = NotEqual
 eq_ifTvBndr env (v1, k1) (v2, k2) k = eq_ifType env k1 k2 &&& k (extendEqEnv env v1 v2)
 eq_ifIdBndr env (v1, t1) (v2, t2) k = eq_ifType env t1 t2 &&& k (extendEqEnv env v1 v2)
 
+eq_ifLetBndr env (IfLetBndr v1 t1 i1) (IfLetBndr v2 t2 i2) k 
+  = eq_ifType env t1 t2 &&& eqIfIdInfo i1 i2 &&& k (extendEqEnv env v1 v2)
+
 eq_ifBndrs     :: ExtEnv [IfaceBndr]
-eq_ifIdBndrs   :: ExtEnv [IfaceIdBndr]
+eq_ifLetBndrs  :: ExtEnv [IfaceLetBndr]
 eq_ifTvBndrs   :: ExtEnv [IfaceTvBndr]
 eq_ifNakedBndrs :: ExtEnv [FastString]
 eq_ifBndrs     = eq_bndrs_with eq_ifBndr
-eq_ifIdBndrs   = eq_bndrs_with eq_ifIdBndr
 eq_ifTvBndrs   = eq_bndrs_with eq_ifTvBndr
 eq_ifNakedBndrs = eq_bndrs_with eq_ifNakedBndr
+eq_ifLetBndrs   = eq_bndrs_with eq_ifLetBndr
 
 eq_bndrs_with eq env []       []       k = k env
 eq_bndrs_with eq env (b1:bs1) (b2:bs2) k = eq env b1 b2 (\env -> eq_bndrs_with eq env bs1 bs2 k)