[project @ 2002-04-01 08:23:30 by simonpj]
[ghc-hetmet.git] / ghc / compiler / basicTypes / DataCon.lhs
index b5a093e..6ba6096 100644 (file)
@@ -10,12 +10,12 @@ module DataCon (
        mkDataCon,
        dataConRepType, dataConSig, dataConName, dataConTag, dataConTyCon,
        dataConArgTys, dataConOrigArgTys, dataConInstOrigArgTys,
-       dataConRepArgTys, dataConTheta,
+       dataConRepArgTys, dataConTheta, 
        dataConFieldLabels, dataConStrictMarks,
        dataConSourceArity, dataConRepArity,
-       dataConNumInstArgs, dataConId, dataConWrapId, dataConRepStrictness,
+       dataConNumInstArgs, dataConWorkId, dataConWrapId, dataConRepStrictness,
        isNullaryDataCon, isTupleCon, isUnboxedTupleCon,
-       isExistentialDataCon, classDataCon,
+       isExistentialDataCon, classDataCon, dataConExistentialTyVars,
 
        splitProductType_maybe, splitProductType,
     ) where
@@ -25,25 +25,24 @@ module DataCon (
 import {-# SOURCE #-} Subst( substTyWith )
 import {-# SOURCE #-} PprType( pprType )
 
-import Type            ( Type, TauType, ThetaType, 
+import Type            ( Type, ThetaType, 
                          mkForAllTys, mkFunTys, mkTyConApp,
                          mkTyVarTys, splitTyConApp_maybe, repType, 
                          mkPredTys, isStrictType
                        )
-import TyCon           ( TyCon, tyConDataCons, tyConDataConsIfAvailable, isProductTyCon,
+import TyCon           ( TyCon, tyConDataCons, tyConDataCons, isProductTyCon,
                          isTupleTyCon, isUnboxedTupleTyCon, isRecursiveTyCon )
 import Class           ( Class, classTyCon )
 import Name            ( Name, NamedThing(..), nameUnique )
 import Var             ( TyVar, Id )
 import FieldLabel      ( FieldLabel )
 import BasicTypes      ( Arity, StrictnessMark(..) )
-import NewDemand       ( Demand, lazyDmd, seqDmd )
 import Outputable
 import Unique          ( Unique, Uniquable(..) )
 import CmdLineOpts     ( opt_UnboxStrictFields )
 import Maybe
 import ListSetOps      ( assoc )
-import Util            ( zipEqual, zipWithEqual )
+import Util            ( zipEqual, zipWithEqual, equalLength )
 \end{code}
 
 
@@ -64,6 +63,41 @@ Every constructor, C, comes with a
   The worker is very like a primop, in that it has no binding,
 
 
+A note about the stupid context
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Data types can have a context:
+       
+       data (Eq a, Ord b) => T a b = T1 a b | T2 a
+
+and that makes the constructors have a context too
+(notice that T2's context is "thinned"):
+
+       T1 :: (Eq a, Ord b) => a -> b -> T a b
+       T2 :: (Eq a) => a -> T a b
+
+Furthermore, this context pops up when pattern matching
+(though GHC hasn't implemented this, but it is in H98, and
+I've fixed GHC so that it now does):
+
+       f (T2 x) = x
+gets inferred type
+       f :: Eq a => T a b -> a
+
+I say the context is "stupid" because the dictionaries passed
+are immediately discarded -- they do nothing and have no benefit.
+It's a flaw in the language.
+
+Up to now [March 2002] I have put this stupid context into the type of
+the "wrapper" constructors functions, T1 and T2, but that turned out
+to be jolly inconvenient for generics, and record update, and other
+functions that build values of type T (because they don't have
+suitable dictionaries available).
+
+So now I've taken the stupid context out.  I simply deal with it
+separately in the type checker on occurrences of a constructor, either
+in an expression or in a pattern.
+
+
 
 %************************************************************************
 %*                                                                     *
@@ -84,9 +118,13 @@ data DataCon
        --      data Eq a => T a = forall b. Ord b => MkT a [b]
 
        dcRepType   :: Type,    -- Type of the constructor
-                               --      forall ab . Ord b => a -> [b] -> MkT a
-                               -- (this is *not* of the constructor Id:
+                               --      forall b a . Ord b => a -> [b] -> MkT a
+                               -- (this is *not* of the constructor wrapper Id:
                                --  see notes after this data type declaration)
+                               --
+                               -- Notice that the existential type parameters come
+                               -- *first*.  It doesn't really matter provided we are
+                               -- consistent.
 
        -- The next six fields express the type of the constructor, in pieces
        -- e.g.
@@ -98,11 +136,23 @@ data DataCon
        --      dcOrigArgTys   = [a,List b]
        --      dcTyCon    = T
 
-       dcTyVars :: [TyVar],            -- Type vars and context for the data type decl
+       dcTyVars :: [TyVar],            -- Type vars for the data type decl
                                        -- These are ALWAYS THE SAME AS THE TYVARS
                                        -- FOR THE PARENT TyCon.  We occasionally rely on
                                        -- this just to avoid redundant instantiation
-       dcTheta  ::  ThetaType,
+
+       dcStupidTheta  ::  ThetaType,   -- This is a "thinned" version of the context of 
+                                       -- the data decl.  
+               -- "Thinned", because the Report says
+               -- to eliminate any constraints that don't mention
+               -- tyvars free in the arg types for this constructor
+               --
+               -- "Stupid", because the dictionaries aren't used for anything.  
+               -- 
+               -- Indeed, [as of March 02] they are no 
+               -- longer in the type of the dataConWrapId, because
+               -- that makes it harder to use the wrap-id to rebuild
+               -- values after record selection or in generics.
 
        dcExTyVars :: [TyVar],          -- Ditto for the context of the constructor,
        dcExTheta  :: ThetaType,        -- the existentially quantified stuff
@@ -114,7 +164,7 @@ data DataCon
        dcRepArgTys :: [Type],          -- Final, representation argument types, after unboxing and flattening,
                                        -- and including existential dictionaries
 
-       dcRepStrictness :: [Demand],    -- One for each representation argument 
+       dcRepStrictness :: [StrictnessMark],    -- One for each representation argument 
 
        dcTyCon  :: TyCon,              -- Result tycon
 
@@ -137,7 +187,7 @@ data DataCon
        --
        -- An entirely separate wrapper function is built in TcTyDecls
 
-       dcId :: Id,             -- The corresponding worker Id
+       dcWorkId :: Id,         -- The corresponding worker Id
                                -- Takes dcRepArgTys as its arguments
 
        dcWrapId :: Id          -- The wrapper Id
@@ -200,7 +250,7 @@ instance Show DataCon where
 
 %************************************************************************
 %*                                                                     *
-\subsection{Consruction}
+\subsection{Construction}
 %*                                                                     *
 %************************************************************************
 
@@ -209,7 +259,7 @@ mkDataCon :: Name
          -> [StrictnessMark] -> [FieldLabel]
          -> [TyVar] -> ThetaType
          -> [TyVar] -> ThetaType
-         -> [TauType] -> TyCon
+         -> [Type] -> TyCon
          -> Id -> Id
          -> DataCon
   -- Can get the tag from the TyCon
@@ -217,20 +267,20 @@ mkDataCon :: Name
 mkDataCon name arg_stricts fields
          tyvars theta ex_tyvars ex_theta orig_arg_tys tycon
          work_id wrap_id
-  = ASSERT(length arg_stricts == length orig_arg_tys)
+  = ASSERT(equalLength arg_stricts orig_arg_tys)
        -- The 'stricts' passed to mkDataCon are simply those for the
        -- source-language arguments.  We add extra ones for the
        -- dictionary arguments right here.
     con
   where
     con = MkData {dcName = name, dcUnique = nameUnique name,
-                 dcTyVars = tyvars, dcTheta = theta,
+                 dcTyVars = tyvars, dcStupidTheta = theta,
                  dcOrigArgTys = orig_arg_tys,
                  dcRepArgTys = rep_arg_tys,
                  dcExTyVars = ex_tyvars, dcExTheta = ex_theta,
-                 dcStrictMarks = real_stricts, dcRepStrictness = rep_arg_demands,
+                 dcStrictMarks = real_stricts, dcRepStrictness = rep_arg_stricts,
                  dcFields = fields, dcTag = tag, dcTyCon = tycon, dcRepType = ty,
-                 dcId = work_id, dcWrapId = wrap_id}
+                 dcWorkId = work_id, dcWrapId = wrap_id}
 
        -- Strictness marks for source-args
        --      *after unboxing choices*, 
@@ -239,16 +289,13 @@ mkDataCon name arg_stricts fields
     real_stricts = (map mk_dict_strict_mark ex_dict_tys) ++
                   zipWithEqual "mkDataCon1" (chooseBoxingStrategy tycon) 
                                orig_arg_tys arg_stricts 
+    real_arg_tys = ex_dict_tys ++ orig_arg_tys
 
        -- Representation arguments and demands
-    (rep_arg_demands, rep_arg_tys) 
-       = unzip $ concat $ 
-         zipWithEqual "mkDataCon2" unbox_strict_arg_ty 
-                      real_stricts 
-                      (ex_dict_tys ++ orig_arg_tys)
+    (rep_arg_stricts, rep_arg_tys) = computeRep real_stricts real_arg_tys
 
     tag = assoc "mkDataCon" (tyConDataCons tycon `zip` [fIRST_TAG..]) con
-    ty  = mkForAllTys (tyvars ++ ex_tyvars)
+    ty  = mkForAllTys (ex_tyvars ++ tyvars)
                      (mkFunTys rep_arg_tys result_ty)
                -- NB: the existential dict args are already in rep_arg_tys
 
@@ -271,8 +318,8 @@ dataConTyCon = dcTyCon
 dataConRepType :: DataCon -> Type
 dataConRepType = dcRepType
 
-dataConId :: DataCon -> Id
-dataConId = dcId
+dataConWorkId :: DataCon -> Id
+dataConWorkId = dcWorkId
 
 dataConWrapId :: DataCon -> Id
 dataConWrapId = dcWrapId
@@ -300,16 +347,16 @@ dataConRepArity (MkData {dcRepArgTys = arg_tys}) = length arg_tys
 
 isNullaryDataCon con  = dataConRepArity con == 0
 
-dataConRepStrictness :: DataCon -> [Demand]
+dataConRepStrictness :: DataCon -> [StrictnessMark]
        -- Give the demands on the arguments of a
        -- Core constructor application (Con dc args)
 dataConRepStrictness dc = dcRepStrictness dc
 
 dataConSig :: DataCon -> ([TyVar], ThetaType,
                          [TyVar], ThetaType,
-                         [TauType], TyCon)
+                         [Type], TyCon)
 
-dataConSig (MkData {dcTyVars = tyvars, dcTheta = theta,
+dataConSig (MkData {dcTyVars = tyvars, dcStupidTheta = theta,
                     dcExTyVars = ex_tyvars, dcExTheta = ex_theta,
                     dcOrigArgTys = arg_tys, dcTyCon = tycon})
   = (tyvars, theta, ex_tyvars, ex_theta, arg_tys, tycon)
@@ -324,17 +371,20 @@ dataConArgTys :: DataCon
 
 dataConArgTys (MkData {dcRepArgTys = arg_tys, dcTyVars = tyvars,
                       dcExTyVars = ex_tyvars}) inst_tys
- = map (substTyWith (tyvars ++ ex_tyvars) inst_tys) arg_tys
+ = map (substTyWith (ex_tyvars ++ tyvars) inst_tys) arg_tys
 
 dataConTheta :: DataCon -> ThetaType
-dataConTheta dc = dcTheta dc
+dataConTheta dc = dcStupidTheta dc
+
+dataConExistentialTyVars :: DataCon -> [TyVar]
+dataConExistentialTyVars dc = dcExTyVars dc
 
 -- And the same deal for the original arg tys:
 
 dataConInstOrigArgTys :: DataCon -> [Type] -> [Type]
 dataConInstOrigArgTys (MkData {dcOrigArgTys = arg_tys, dcTyVars = tyvars,
                       dcExTyVars = ex_tyvars}) inst_tys
- = map (substTyWith (tyvars ++ ex_tyvars) inst_tys) arg_tys
+ = map (substTyWith (ex_tyvars ++ tyvars) inst_tys) arg_tys
 \end{code}
 
 These two functions get the real argument types of the constructor,
@@ -349,7 +399,7 @@ after any flattening has been done.
 dataConOrigArgTys :: DataCon -> [Type]
 dataConOrigArgTys dc = dcOrigArgTys dc
 
-dataConRepArgTys :: DataCon -> [TauType]
+dataConRepArgTys :: DataCon -> [Type]
 dataConRepArgTys dc = dcRepArgTys dc
 \end{code}
 
@@ -403,7 +453,7 @@ splitProductType_maybe ty
                                        -- and for constructors visible
           -> Just (tycon, ty_args, data_con, dataConArgTys data_con ty_args)
           where
-             data_con = head (tyConDataConsIfAvailable tycon)
+             data_con = head (tyConDataCons tycon)
        other -> Nothing
 
 splitProductType str ty
@@ -442,15 +492,18 @@ chooseBoxingStrategy tycon arg_ty strict
                                Nothing -> False
                                Just (arg_tycon, _) -> isProductTyCon arg_tycon
 
-unbox_strict_arg_ty 
-       :: StrictnessMark       -- After strategy choice; can't be MarkedUserStrict
-       -> Type                 -- Source argument type
-       -> [(Demand,Type)]      -- Representation argument types and demamds
+computeRep :: [StrictnessMark]         -- Original arg strictness
+                                       --   [after strategy choice; can't be MarkedUserStrict]
+          -> [Type]                    -- and types
+          -> ([StrictnessMark],        -- Representation arg strictness
+              [Type])                  -- And type
 
-unbox_strict_arg_ty NotMarkedStrict ty = [(lazyDmd, ty)]
-unbox_strict_arg_ty MarkedStrict    ty = [(seqDmd,  ty)]
-unbox_strict_arg_ty MarkedUnboxed   ty 
-  = zipEqual "unbox_strict_arg_ty" (dataConRepStrictness arg_data_con) arg_tys
+computeRep stricts tys
+  = unzip $ concat $ zipWithEqual "computeRep" unbox stricts tys
   where
-    (_, _, arg_data_con, arg_tys) = splitProductType "unbox_strict_arg_ty" (repType ty)
+    unbox NotMarkedStrict ty = [(NotMarkedStrict, ty)]
+    unbox MarkedStrict    ty = [(MarkedStrict,    ty)]
+    unbox MarkedUnboxed   ty = zipEqual "computeRep" (dataConRepStrictness arg_dc) arg_tys
+                            where
+                              (_, _, arg_dc, arg_tys) = splitProductType "unbox_strict_arg_ty" (repType ty)
 \end{code}