X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;ds=sidebyside;f=ghc%2Fcompiler%2FbasicTypes%2FDataCon.lhs;h=2e9f09c0b588d2ac1d392294f79a1b6c2702e658;hb=c883f6969ad957637649f3af1a2b6977555bdd32;hp=61c71d6d7dd17603796fec39ebc1481fb13f01f7;hpb=4e94cbc42227ecb187e5c2d03831ca49549095eb;p=ghc-hetmet.git diff --git a/ghc/compiler/basicTypes/DataCon.lhs b/ghc/compiler/basicTypes/DataCon.lhs index 61c71d6..2e9f09c 100644 --- a/ghc/compiler/basicTypes/DataCon.lhs +++ b/ghc/compiler/basicTypes/DataCon.lhs @@ -5,46 +5,41 @@ \begin{code} module DataCon ( - DataCon, + DataCon, DataConIds(..), ConTag, fIRST_TAG, mkDataCon, dataConRepType, dataConSig, dataConName, dataConTag, dataConTyCon, - dataConArgTys, dataConOrigArgTys, dataConInstOrigArgTys, - dataConRepArgTys, dataConTheta, - dataConFieldLabels, dataConStrictMarks, + dataConTyVars, dataConStupidTheta, + dataConArgTys, dataConOrigArgTys, dataConResTy, + dataConInstOrigArgTys, dataConRepArgTys, + dataConFieldLabels, dataConStrictMarks, dataConExStricts, dataConSourceArity, dataConRepArity, - dataConNumInstArgs, - dataConWorkId, dataConWrapId, dataConWrapId_maybe, + dataConIsInfix, + dataConWorkId, dataConWrapId, dataConWrapId_maybe, dataConImplicitIds, dataConRepStrictness, - isNullaryDataCon, isTupleCon, isUnboxedTupleCon, - isExistentialDataCon, classDataCon, dataConExistentialTyVars, + isNullarySrcDataCon, isNullaryRepDataCon, isTupleCon, isUnboxedTupleCon, + isVanillaDataCon, classDataCon, splitProductType_maybe, splitProductType, ) where #include "HsVersions.h" -import {-# SOURCE #-} Subst( substTyWith ) -import {-# SOURCE #-} PprType( pprType ) - -import Type ( Type, ThetaType, +import Type ( Type, ThetaType, substTyWith, substTy, zipTopTvSubst, mkForAllTys, mkFunTys, mkTyConApp, - mkTyVarTys, splitTyConApp_maybe, repType, - mkPredTys, isStrictType + splitTyConApp_maybe, + mkPredTys, isStrictPred, pprType ) -import TyCon ( TyCon, tyConDataCons, tyConDataCons, isProductTyCon, - isTupleTyCon, isUnboxedTupleTyCon, isRecursiveTyCon ) +import TyCon ( TyCon, FieldLabel, tyConDataCons, tyConDataCons, + isProductTyCon, isTupleTyCon, isUnboxedTupleTyCon ) import Class ( Class, classTyCon ) import Name ( Name, NamedThing(..), nameUnique ) import Var ( TyVar, Id ) -import FieldLabel ( FieldLabel ) import BasicTypes ( Arity, StrictnessMark(..) ) import Outputable import Unique ( Unique, Uniquable(..) ) -import CmdLineOpts ( opt_UnboxStrictFields ) -import Maybes ( orElse ) import ListSetOps ( assoc ) -import Util ( zipEqual, zipWithEqual, notNull ) +import Util ( zipEqual, zipWithEqual ) \end{code} @@ -89,7 +84,7 @@ Each data constructor C has two, and possibly three, Names associated with it: --------------------------------------------------------------------------- * The "source data con" C DataName The DataCon itself * The "real data con" C VarName Its worker Id - * The "wrapper data con" $wC VarName Wrapper Id (optional) + * The "wrapper data con" $WC VarName Wrapper Id (optional) Each of these three has a distinct Unique. The "source data con" name appears in the output of the renamer, and names the Haskell-source @@ -141,17 +136,34 @@ 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). + 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. + + [May 2003: actually I think this decision could evasily be + reversed now, and probably should be. Generics could be + disabled for types with a stupid context; record updates now + (H98) needs the context too; etc. It's an unforced change, so + I'm leaving it for now --- but it does seem odd that the + wrapper doesn't include the stupid context.] -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. +[July 04] With the advent of generalised data types, it's less obvious +what the "stupid context" is. Consider + C :: forall a. Ord a => a -> a -> T (Foo a) +Does the C constructor in Core contain the Ord dictionary? Yes, it must: + f :: T b -> Ordering + f = /\b. \x:T b. + case x of + C a (d:Ord a) (p:a) (q:a) -> compare d p q +Note that (Foo a) might not be an instance of Ord. %************************************************************************ %* * @@ -161,48 +173,41 @@ in an expression or in a pattern. \begin{code} data DataCon - = MkData { -- Used for data constructors only; - -- there *is* no constructor for a newtype - dcName :: Name, - - dcUnique :: Unique, -- Cached from Name + = MkData { + dcName :: Name, -- This is the name of the *source data con* + -- (see "Note [Data Constructor Naming]" above) + dcUnique :: Unique, -- Cached from Name dcTag :: ConTag, -- Running example: -- -- data Eq a => T a = forall b. Ord b => MkT a [b] - dcRepType :: Type, -- Type of the constructor - -- forall a b . 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 *second*. - -- Reason: in a case expression we may find: - -- case (e :: T t) of { MkT b (d:Ord b) (x:t) (xs:[b]) -> ... } - -- It's convenient to apply the rep-type of MkT to 't', to get - -- forall b. Ord b => ... - -- and use that to check the pattern. Mind you, this is really only - -- use in CoreLint. - - -- The next six fields express the type of the constructor, in pieces -- e.g. -- - -- dcTyVars = [a] - -- dcTheta = [Eq a] - -- dcExTyVars = [b] - -- dcExTheta = [Ord b] - -- dcOrigArgTys = [a,List b] - -- dcTyCon = T - - 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 - - dcStupidTheta :: ThetaType, -- This is a "thinned" version of the context of - -- the data decl. + -- dcTyVars = [a,b] + -- dcStupidTheta = [Eq a] + -- dcTheta = [Ord b] + -- dcOrigArgTys = [a,List b] + -- dcTyCon = T + -- dcTyArgs = [a,b] + + dcVanilla :: Bool, -- True <=> This is a vanilla Haskell 98 data constructor + -- Its type is of form + -- forall a1..an . t1 -> ... tm -> T a1..an + -- No existentials, no GADTs, nothing. + + dcTyVars :: [TyVar], -- Universally-quantified type vars + -- for the data constructor. + -- dcVanilla = True <=> The [TyVar] are identical to those of the parent tycon + -- False <=> The [TyVar] are NOT NECESSARILY THE SAME AS THE TYVARS + -- FOR THE PARENT TyCon. (With GADTs the data + -- con might not even have the same number of + -- type variables.) + + 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 @@ -210,52 +215,88 @@ data DataCon -- "Stupid", because the dictionaries aren't used for anything. -- -- Indeed, [as of March 02] they are no - -- longer in the type of the dcWrapId, because + -- longer in the type of the wrapper Id, 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 + dcTheta :: ThetaType, -- The existentially quantified stuff dcOrigArgTys :: [Type], -- Original argument types -- (before unboxing and flattening of -- strict fields) - dcRepArgTys :: [Type], -- Final, representation argument types, after unboxing and flattening, - -- and including existential dictionaries - - dcRepStrictness :: [StrictnessMark], -- One for each representation argument - - dcTyCon :: TyCon, -- Result tycon + -- Result type of constructor is T t1..tn + dcTyCon :: TyCon, -- Result tycon, T + dcResTys :: [Type], -- Result type args, t1..tn -- Now the strictness annotations and field labels of the constructor dcStrictMarks :: [StrictnessMark], - -- Strictness annotations as deduced by the compiler. - -- Has no MarkedUserStrict; they have been changed to MarkedStrict - -- or MarkedUnboxed by the compiler. - -- *Includes the existential dictionaries* - -- length = length dcExTheta + dataConSourceArity dataCon + -- Strictness annotations as decided by the compiler. + -- Does *not* include the existential dictionaries + -- length = dataConSourceArity dataCon dcFields :: [FieldLabel], -- Field labels for this constructor, in the -- same order as the argument types; -- length = 0 (if not a record) or dataConSourceArity. + -- Constructor representation + dcRepArgTys :: [Type], -- Final, representation argument types, + -- after unboxing and flattening, + -- and *including* existential dictionaries + + dcRepStrictness :: [StrictnessMark], -- One for each *representation* argument + + dcRepType :: Type, -- Type of the constructor + -- forall a b . 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 *second*. + -- Reason: in a case expression we may find: + -- case (e :: T t) of { MkT b (d:Ord b) (x:t) (xs:[b]) -> ... } + -- It's convenient to apply the rep-type of MkT to 't', to get + -- forall b. Ord b => ... + -- and use that to check the pattern. Mind you, this is really only + -- use in CoreLint. + + -- Finally, the curried worker function that corresponds to the constructor -- It doesn't have an unfolding; the code generator saturates these Ids -- and allocates a real constructor when it finds one. -- -- An entirely separate wrapper function is built in TcTyDecls + dcIds :: DataConIds, - dcWorkId :: Id, -- The corresponding worker Id - -- Takes dcRepArgTys as its arguments - -- Perhaps this should be a 'Maybe'; not reqd for newtype constructors - - dcWrapId :: Maybe Id -- The wrapper Id, if it's necessary - -- It's deemed unnecessary if it performs the - -- identity function + dcInfix :: Bool -- True <=> declared infix + -- Used for Template Haskell and 'deriving' only + -- The actual fixity is stored elsewhere } +data DataConIds + = NewDC Id -- Newtypes have only a wrapper, but no worker + | AlgDC (Maybe Id) Id -- Algebraic data types always have a worker, and + -- may or may not have a wrapper, depending on whether + -- the wrapper does anything. + + -- *Neither* the worker *nor* the wrapper take the dcStupidTheta dicts as arguments + + -- The wrapper takes dcOrigArgTys as its arguments + -- The worker takes dcRepArgTys as its arguments + -- If the worker is absent, dcRepArgTys is the same as dcOrigArgTys + + -- The 'Nothing' case of AlgDC is important + -- Not only is this efficient, + -- but it also ensures that the wrapper is replaced + -- by the worker (becuase it *is* the wroker) + -- even when there are no args. E.g. in + -- f (:) x + -- the (:) *is* the worker. + -- This is really important in rule matching, + -- (We could match on the wrappers, + -- but that makes it less likely that rules will match + -- when we bring bits of unfoldings together.) + type ConTag = Int fIRST_TAG :: ConTag @@ -319,30 +360,30 @@ instance Show DataCon where \begin{code} mkDataCon :: Name + -> Bool -- Declared infix + -> Bool -- Vanilla (see notes with dcVanilla) -> [StrictnessMark] -> [FieldLabel] - -> [TyVar] -> ThetaType - -> [TyVar] -> ThetaType - -> [Type] -> TyCon - -> Id -> Maybe Id -- Worker and possible wrapper + -> [TyVar] -> ThetaType -> ThetaType + -> [Type] -> TyCon -> [Type] + -> DataConIds -> DataCon -- Can get the tag from the TyCon -mkDataCon name - arg_stricts -- Use [] to mean 'all non-strict' +mkDataCon name declared_infix vanilla + arg_stricts -- Must match orig_arg_tys 1-1 fields - tyvars theta ex_tyvars ex_theta orig_arg_tys tycon - work_id wrap_id + tyvars stupid_theta theta orig_arg_tys tycon res_tys + ids = con where con = MkData {dcName = name, - dcUnique = nameUnique name, - dcTyVars = tyvars, dcStupidTheta = theta, - dcOrigArgTys = orig_arg_tys, + dcUnique = nameUnique name, dcVanilla = vanilla, + dcTyVars = tyvars, dcStupidTheta = stupid_theta, dcTheta = theta, + dcOrigArgTys = orig_arg_tys, dcTyCon = tycon, dcResTys = res_tys, dcRepArgTys = rep_arg_tys, - dcExTyVars = ex_tyvars, dcExTheta = ex_theta, - dcStrictMarks = real_stricts, dcRepStrictness = rep_arg_stricts, - dcFields = fields, dcTag = tag, dcTyCon = tycon, dcRepType = ty, - dcWorkId = work_id, dcWrapId = wrap_id} + dcStrictMarks = arg_stricts, dcRepStrictness = rep_arg_stricts, + dcFields = fields, dcTag = tag, dcRepType = ty, + dcIds = ids, dcInfix = declared_infix} -- Strictness marks for source-args -- *after unboxing choices*, @@ -351,25 +392,21 @@ mkDataCon name -- The 'arg_stricts' passed to mkDataCon are simply those for the -- source-language arguments. We add extra ones for the -- dictionary arguments right here. - ex_dict_tys = mkPredTys ex_theta - real_stricts = map mk_dict_strict_mark ex_dict_tys ++ - zipWith (chooseBoxingStrategy tycon) - orig_arg_tys - (arg_stricts ++ repeat NotMarkedStrict) - real_arg_tys = ex_dict_tys ++ orig_arg_tys + dict_tys = mkPredTys theta + real_arg_tys = dict_tys ++ orig_arg_tys + real_stricts = map mk_dict_strict_mark theta ++ arg_stricts -- Representation arguments and demands (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) - (mkFunTys rep_arg_tys result_ty) + ty = mkForAllTys tyvars (mkFunTys rep_arg_tys result_ty) -- NB: the existential dict args are already in rep_arg_tys - result_ty = mkTyConApp tycon (mkTyVarTys tyvars) + result_ty = mkTyConApp tycon res_tys -mk_dict_strict_mark ty | isStrictType ty = MarkedStrict - | otherwise = NotMarkedStrict +mk_dict_strict_mark pred | isStrictPred pred = MarkedStrict + | otherwise = NotMarkedStrict \end{code} \begin{code} @@ -385,17 +422,34 @@ dataConTyCon = dcTyCon dataConRepType :: DataCon -> Type dataConRepType = dcRepType +dataConIsInfix :: DataCon -> Bool +dataConIsInfix = dcInfix + +dataConTyVars :: DataCon -> [TyVar] +dataConTyVars = dcTyVars + dataConWorkId :: DataCon -> Id -dataConWorkId = dcWorkId +dataConWorkId dc = case dcIds dc of + AlgDC _ wrk_id -> wrk_id + NewDC _ -> pprPanic "dataConWorkId" (ppr dc) dataConWrapId_maybe :: DataCon -> Maybe Id -dataConWrapId_maybe = dcWrapId +dataConWrapId_maybe dc = case dcIds dc of + AlgDC mb_wrap _ -> mb_wrap + NewDC wrap -> Just wrap dataConWrapId :: DataCon -> Id -- Returns an Id which looks like the Haskell-source constructor --- If there is no dcWrapId it's because there is no need for a --- wrapper, so the worker is the Right Thing -dataConWrapId dc = dcWrapId dc `orElse` dcWorkId dc +dataConWrapId dc = case dcIds dc of + AlgDC (Just wrap) _ -> wrap + AlgDC Nothing wrk -> wrk -- worker=wrapper + NewDC wrap -> wrap + +dataConImplicitIds :: DataCon -> [Id] +dataConImplicitIds dc = case dcIds dc of + AlgDC (Just wrap) work -> [wrap,work] + AlgDC Nothing work -> [work] + NewDC wrap -> [wrap] dataConFieldLabels :: DataCon -> [FieldLabel] dataConFieldLabels = dcFields @@ -403,10 +457,10 @@ dataConFieldLabels = dcFields dataConStrictMarks :: DataCon -> [StrictnessMark] dataConStrictMarks = dcStrictMarks --- Number of type-instantiation arguments --- All the remaining arguments of the DataCon are (notionally) --- stored in the DataCon, and are matched in a case expression -dataConNumInstArgs (MkData {dcTyVars = tyvars}) = length tyvars +dataConExStricts :: DataCon -> [StrictnessMark] +-- Strictness of *existential* arguments only +-- Usually empty, so we don't bother to cache this +dataConExStricts dc = map mk_dict_strict_mark (dcTheta dc) dataConSourceArity :: DataCon -> Arity -- Source-level arity of the data constructor @@ -418,7 +472,9 @@ dataConSourceArity dc = length (dcOrigArgTys dc) -- dictionaries dataConRepArity (MkData {dcRepArgTys = arg_tys}) = length arg_tys -isNullaryDataCon con = dataConRepArity con == 0 +isNullarySrcDataCon, isNullaryRepDataCon :: DataCon -> Bool +isNullarySrcDataCon dc = null (dcOrigArgTys dc) +isNullaryRepDataCon dc = null (dcRepArgTys dc) dataConRepStrictness :: DataCon -> [StrictnessMark] -- Give the demands on the arguments of a @@ -426,13 +482,11 @@ dataConRepStrictness :: DataCon -> [StrictnessMark] dataConRepStrictness dc = dcRepStrictness dc dataConSig :: DataCon -> ([TyVar], ThetaType, - [TyVar], ThetaType, - [Type], TyCon) + [Type], TyCon, [Type]) -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) +dataConSig (MkData {dcTyVars = tyvars, dcTheta = theta, + dcOrigArgTys = arg_tys, dcTyCon = tycon, dcResTys = res_tys}) + = (tyvars, theta, arg_tys, tycon, res_tys) dataConArgTys :: DataCon -> [Type] -- Instantiated at these types @@ -441,23 +495,23 @@ dataConArgTys :: DataCon -- NB: these INCLUDE the existentially quantified dict args -- but EXCLUDE the data-decl context which is discarded -- It's all post-flattening etc; this is a representation type +dataConArgTys (MkData {dcRepArgTys = arg_tys, dcTyVars = tyvars}) inst_tys + = map (substTyWith tyvars inst_tys) arg_tys -dataConArgTys (MkData {dcRepArgTys = arg_tys, dcTyVars = tyvars, - dcExTyVars = ex_tyvars}) inst_tys - = map (substTyWith (tyvars ++ ex_tyvars) inst_tys) arg_tys - -dataConTheta :: DataCon -> ThetaType -dataConTheta dc = dcStupidTheta dc - -dataConExistentialTyVars :: DataCon -> [TyVar] -dataConExistentialTyVars dc = dcExTyVars dc - --- And the same deal for the original arg tys: +dataConResTy :: DataCon -> [Type] -> Type +dataConResTy (MkData {dcTyVars = tyvars, dcTyCon = tc, dcResTys = res_tys}) inst_tys + = substTy (zipTopTvSubst tyvars inst_tys) (mkTyConApp tc res_tys) + -- zipTopTvSubst because the res_tys can't contain any foralls +-- And the same deal for the original arg tys +-- This one only works for vanilla DataCons 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 +dataConInstOrigArgTys (MkData {dcOrigArgTys = arg_tys, dcTyVars = tyvars, dcVanilla = is_vanilla}) inst_tys + = ASSERT( is_vanilla ) + map (substTyWith tyvars inst_tys) arg_tys + +dataConStupidTheta :: DataCon -> ThetaType +dataConStupidTheta dc = dcStupidTheta dc \end{code} These two functions get the real argument types of the constructor, @@ -484,8 +538,8 @@ isTupleCon (MkData {dcTyCon = tc}) = isTupleTyCon tc isUnboxedTupleCon :: DataCon -> Bool isUnboxedTupleCon (MkData {dcTyCon = tc}) = isUnboxedTupleTyCon tc -isExistentialDataCon :: DataCon -> Bool -isExistentialDataCon (MkData {dcExTyVars = tvs}) = notNull tvs +isVanillaDataCon :: DataCon -> Bool +isVanillaDataCon dc = dcVanilla dc \end{code} @@ -534,39 +588,8 @@ splitProductType str ty Just stuff -> stuff Nothing -> pprPanic (str ++ ": not a product") (pprType ty) --- We attempt to unbox/unpack a strict field when either: --- (i) The tycon is imported, and the field is marked '! !', or --- (ii) The tycon is defined in this module, the field is marked '!', --- and the -funbox-strict-fields flag is on. --- --- This ensures that if we compile some modules with -funbox-strict-fields and --- some without, the compiler doesn't get confused about the constructor --- representations. - -chooseBoxingStrategy :: TyCon -> Type -> StrictnessMark -> StrictnessMark - -- Transforms any MarkedUserStricts into MarkUnboxed or MarkedStrict -chooseBoxingStrategy tycon arg_ty strict - = case strict of - MarkedUserStrict - | opt_UnboxStrictFields - && unbox arg_ty -> MarkedUnboxed - | otherwise -> MarkedStrict - other -> strict - where - -- beware: repType will go into a loop if we try this on a recursive - -- type (for reasons unknown...), hence the check for recursion below. - unbox ty = - case splitTyConApp_maybe ty of - Nothing -> False - Just (arg_tycon, _) - | isRecursiveTyCon arg_tycon -> False - | otherwise -> - case splitTyConApp_maybe (repType ty) of - Nothing -> False - Just (arg_tycon, _) -> isProductTyCon arg_tycon computeRep :: [StrictnessMark] -- Original arg strictness - -- [after strategy choice; can't be MarkedUserStrict] -> [Type] -- and types -> ([StrictnessMark], -- Representation arg strictness [Type]) -- And type @@ -578,5 +601,5 @@ computeRep stricts tys 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) + (_, _, arg_dc, arg_tys) = splitProductType "unbox_strict_arg_ty" ty \end{code}