[project @ 2004-05-06 12:30:38 by simonpj]
[ghc-hetmet.git] / ghc / compiler / typecheck / TcGenDeriv.lhs
index e922146..05019c3 100644 (file)
@@ -37,26 +37,22 @@ import DataCon              ( isNullaryDataCon, dataConTag,
                          dataConOrigArgTys, dataConSourceArity, fIRST_TAG,
                          DataCon, dataConName,
                          dataConFieldLabels )
-import Name            ( getOccString, getOccName, getSrcLoc, occNameString, 
-                         occNameUserString, 
-                         Name, NamedThing(..), 
-                         isDataSymOcc, isSymOcc
-                       )
+import Name            ( getOccString, getSrcLoc, Name, NamedThing(..) )
 
 import HscTypes                ( FixityEnv, lookupFixity )
 import PrelInfo
 import PrelNames
-import TysWiredIn
 import MkId            ( eRROR_ID )
 import PrimOp          ( PrimOp(..) )
 import SrcLoc          ( Located(..), noLoc, srcLocSpan )
-import TyCon           ( TyCon, isNewTyCon, tyConDataCons, isEnumerationTyCon,
+import TyCon           ( TyCon, isNewTyCon, tyConDataCons, isEnumerationTyCon, tyConArity,
                          maybeTyConSingleCon, tyConFamilySize, tyConTyVars, tyConName
                        )
 import TcType          ( isUnLiftedType, tcEqType, Type )
 import TysPrim         ( charPrimTy, intPrimTy, wordPrimTy, addrPrimTy, floatPrimTy, doublePrimTy,
                          intPrimTyCon )
-import TysWiredIn      ( charDataCon, intDataCon, floatDataCon, doubleDataCon )
+import TysWiredIn      ( charDataCon, intDataCon, floatDataCon, doubleDataCon,
+                         intDataCon_RDR, true_RDR, false_RDR )
 import Util            ( zipWithEqual, isSingleton,
                          zipWith3Equal, nOfThem, zipEqual )
 import Char            ( isAlpha )
@@ -164,7 +160,7 @@ gen_Eq_binds tycon
                case maybeTyConSingleCon tycon of
                  Just _ -> []
                  Nothing -> -- if cons don't match, then False
-                    [([wildPat, wildPat], false_Expr)]
+                    [([nlWildPat, nlWildPat], false_Expr)]
            else -- calc. and compare the tags
                 [([a_Pat, b_Pat],
                    untag_Expr tycon [(a_RDR,ah_RDR), (b_RDR,bh_RDR)]
@@ -329,13 +325,13 @@ gen_Ord_binds tycon
                           -- Catch this specially to avoid warnings
                           -- about overlapping patterns from the desugarer,
                           -- and to avoid unnecessary pattern-matching
-      = [([wildPat,wildPat], eqTag_Expr)]
+      = [([nlWildPat,nlWildPat], eqTag_Expr)]
       | otherwise
       = map pats_etc nonnullary_cons ++
        (if single_con_type then        -- Omit wildcards when there's just one 
              []                        -- constructor, to silence desugarer
        else
-              [([wildPat, wildPat], default_rhs)])
+              [([nlWildPat, nlWildPat], default_rhs)])
 
       where
        pats_etc data_con
@@ -597,7 +593,7 @@ gen_Ix_binds tycon
     enum_index
       = mk_easy_FunBind tycon_loc index_RDR 
                [noLoc (AsPat (noLoc c_RDR) 
-                          (nlTuplePat [a_Pat, wildPat] Boxed)), 
+                          (nlTuplePat [a_Pat, nlWildPat] Boxed)), 
                                d_Pat] emptyBag (
        nlHsIf (nlHsPar (nlHsVarApps inRange_RDR [c_RDR, d_RDR])) (
           untag_Expr tycon [(a_RDR, ah_RDR)] (
@@ -898,7 +894,7 @@ gen_Show_binds get_fixity tycon
        pats_etc data_con
          | nullary_con =  -- skip the showParen junk...
             ASSERT(null bs_needed)
-            ([wildPat, con_pat], mk_showString_app con_str)
+            ([nlWildPat, con_pat], mk_showString_app con_str)
          | otherwise   =
             ([a_Pat, con_pat],
                  showParen_Expr (nlHsPar (genOpApp a_Expr ge_RDR (nlHsLit (HsInt con_prec_plus_one))))
@@ -993,27 +989,30 @@ From the data type
 
 we generate
 
-       instance (Typeable a, Typeable b) => Typeable (T a b) where
-               typeOf _ = mkTypeRep (mkTyConRep "T")
-                                    [typeOf (undefined::a),
-                                     typeOf (undefined::b)]
+       instance Typeable2 T where
+               typeOf2 _ = mkTyConApp (mkTyConRep "T") []
 
-Notice the use of lexically scoped type variables.
+We are passed the Typeable2 class as well as T
 
 \begin{code}
 gen_Typeable_binds :: TyCon -> LHsBinds RdrName
 gen_Typeable_binds tycon
   = unitBag $
-       mk_easy_FunBind tycon_loc typeOf_RDR [wildPat] emptyBag
-               (nlHsApps mkTypeRep_RDR [tycon_rep, arg_reps])
+       mk_easy_FunBind tycon_loc 
+               (mk_typeOf_RDR tycon)   -- Name of appropriate type0f function
+               [nlWildPat] emptyBag
+               (nlHsApps mkTypeRep_RDR [tycon_rep, nlList []])
   where
     tycon_loc = getSrcSpan tycon
-    tyvars    = tyConTyVars tycon
     tycon_rep = nlHsVar mkTyConRep_RDR `nlHsApp` nlHsLit (mkHsString (showSDoc (ppr tycon)))
-    arg_reps  = nlList (map mk tyvars)
-    mk tyvar  = nlHsApp (nlHsVar typeOf_RDR) 
-                     (noLoc (ExprWithTySig (nlHsVar undefined_RDR)
-                                           (nlHsTyVar (getRdrName tyvar))))
+
+mk_typeOf_RDR :: TyCon -> RdrName
+-- Use the arity of the TyCon to make the right typeOfn function
+mk_typeOf_RDR tycon = varQual_RDR tYPEABLE_Name (mkFastString ("typeOf" ++ suffix))
+               where
+                 arity = tyConArity tycon
+                 suffix | arity == 0 = ""
+                        | otherwise  = show arity
 \end{code}
 
 
@@ -1030,19 +1029,20 @@ From the data type
 
 we generate
 
-  $cT1 = mkConstr 1 "T1" Prefix
-  $cT2 = mkConstr 2 "T2" Prefix
-  $dT  = mkDataType [$con_T1, $con_T2]
+  $cT1 = mkDataCon $dT "T1" Prefix
+  $cT2 = mkDataCon $dT "T2" Prefix
+  $dT  = mkDataType "Module.T" [] [$con_T1, $con_T2]
+  -- the [] is for field labels.
 
   instance (Data a, Data b) => Data (T a b) where
     gfoldl k z (T1 a b) = z T `k` a `k` b
     gfoldl k z T2          = z T2
     -- ToDo: add gmapT,Q,M, gfoldr
-    
-    fromConstr c = case conIndex c of
-                       I# 1# -> T1 undefined undefined
-                       I# 2# -> T2
-    
+    gunfold k z c = case conIndex c of
+                       I# 1# -> k (k (z T1))
+                       I# 2# -> z T2
+
     toConstr (T1 _ _) = $cT1
     toConstr T2              = $cT2
     
@@ -1054,13 +1054,15 @@ gen_Data_binds :: FixityEnv
               -> (LHsBinds RdrName,    -- The method bindings
                   LHsBinds RdrName)    -- Auxiliary bindings
 gen_Data_binds fix_env tycon
-  = (listToBag [gfoldl_bind, fromCon_bind, toCon_bind, dataTypeOf_bind],
+  = (listToBag [gfoldl_bind, gunfold_bind, toCon_bind, dataTypeOf_bind],
                -- Auxiliary definitions: the data type and constructors
      datatype_bind `consBag` listToBag (map mk_con_bind data_cons))
   where
-    tycon_loc = getSrcSpan tycon
+    tycon_loc  = getSrcSpan tycon
     tycon_name = tyConName tycon
-    data_cons = tyConDataCons tycon
+    data_cons  = tyConDataCons tycon
+    n_cons     = length data_cons
+    one_constr = n_cons == 1
 
        ------------ gfoldl
     gfoldl_bind = mk_FunBind tycon_loc gfoldl_RDR (map gfoldl_eqn data_cons)
@@ -1072,50 +1074,81 @@ gen_Data_binds fix_env tycon
                     as_needed = take (dataConSourceArity con) as_RDRs
                     mk_k_app e v = nlHsPar (nlHsOpApp e k_RDR (nlHsVar v))
 
-       ------------ fromConstr
-    fromCon_bind = mk_FunBind tycon_loc fromConstr_RDR [([c_Pat], from_con_rhs)]
-    from_con_rhs = nlHsCase (nlHsVar conIndex_RDR `nlHsApp` c_Expr) 
-                         (map from_con_alt data_cons)
-    from_con_alt dc = mkSimpleHsAlt (nlConPat intDataCon_RDR [nlLitPat (HsIntPrim (toInteger (dataConTag dc)))])
-                                   (nlHsVarApps (getRdrName dc)
-                                                (replicate (dataConSourceArity dc) undefined_RDR))
+       ------------ gunfold
+    gunfold_bind = mk_FunBind tycon_loc
+                              gunfold_RDR
+                              [([k_Pat, z_Pat, if one_constr then nlWildPat else c_Pat], 
+                               gunfold_rhs)]
+
+    gunfold_rhs 
+       | one_constr = mk_unfold_rhs (head data_cons)   -- No need for case
+       | otherwise  = nlHsCase (nlHsVar conIndex_RDR `nlHsApp` c_Expr) 
+                               (map gunfold_alt data_cons)
+
+    gunfold_alt dc = mkSimpleHsAlt (mk_unfold_pat dc) (mk_unfold_rhs dc)
+    mk_unfold_rhs dc = foldr nlHsApp
+                           (nlHsVar z_RDR `nlHsApp` nlHsVar (getRdrName dc))
+                           (replicate (dataConSourceArity dc) (nlHsVar k_RDR))
+
+    mk_unfold_pat dc   -- Last one is a wild-pat, to avoid 
+                       -- redundant test, and annoying warning
+      | tag-fIRST_TAG == n_cons-1 = nlWildPat  -- Last constructor
+      | otherwise = nlConPat intDataCon_RDR [nlLitPat (HsIntPrim (toInteger tag))]
+      where 
+       tag = dataConTag dc
                          
        ------------ toConstr
     toCon_bind = mk_FunBind tycon_loc toConstr_RDR (map to_con_eqn data_cons)
     to_con_eqn dc = ([nlWildConPat dc], nlHsVar (mk_constr_name dc))
     
        ------------ dataTypeOf
-    dataTypeOf_bind = mk_easy_FunBind tycon_loc dataTypeOf_RDR [wildPat] 
-                                         emptyBag (nlHsVar data_type_name)
+    dataTypeOf_bind = mk_easy_FunBind
+                        tycon_loc
+                        dataTypeOf_RDR
+                       [nlWildPat]
+                        emptyBag
+                        (nlHsVar data_type_name)
 
        ------------ $dT
+
     data_type_name = mkDerivedRdrName tycon_name mkDataTOcc
-    datatype_bind  = mkVarBind tycon_loc data_type_name
-                                  (nlHsVar mkDataType_RDR `nlHsApp` 
-                                   nlList constrs)
+    datatype_bind  = mkVarBind
+                       tycon_loc
+                       data_type_name
+                      (           nlHsVar mkDataType_RDR 
+                         `nlHsApp` nlHsLit (mkHsString (showSDoc (ppr tycon)))
+                         `nlHsApp` nlList constrs
+                       )
     constrs = [nlHsVar (mk_constr_name con) | con <- data_cons]
 
 
        ------------ $cT1 etc
     mk_constr_name con = mkDerivedRdrName (dataConName con) mkDataCOcc
-    mk_con_bind dc = mkVarBind tycon_loc (mk_constr_name dc) 
-                                            (nlHsApps mkConstr_RDR (constr_args dc))
-    constr_args dc = [nlHsIntLit (toInteger (dataConTag dc)),          -- Tag
-                     nlHsLit (mkHsString (occNameUserString dc_occ)),  -- String name
-                     nlHsVar fixity]                                   -- Fixity
+    mk_con_bind dc = mkVarBind
+                       tycon_loc
+                       (mk_constr_name dc) 
+                      (nlHsApps mkConstr_RDR (constr_args dc))
+    constr_args dc =
+        [ -- nlHsIntLit (toInteger (dataConTag dc)),           -- Tag
+          nlHsVar data_type_name,                              -- DataType
+          nlHsLit (mkHsString (occNameUserString dc_occ)),     -- String name
+           nlList  labels,                                     -- Field labels
+          nlHsVar fixity]                                      -- Fixity
        where
+          labels   = map (nlHsLit . mkHsString . getOccString . fieldLabelName)
+                         (dataConFieldLabels dc)
          dc_occ   = getOccName dc
          is_infix = isDataSymOcc dc_occ
          fixity | is_infix  = infix_RDR
                 | otherwise = prefix_RDR
 
 gfoldl_RDR     = varQual_RDR gENERICS_Name FSLIT("gfoldl")
-fromConstr_RDR = varQual_RDR gENERICS_Name FSLIT("fromConstr")
+gunfold_RDR    = varQual_RDR gENERICS_Name FSLIT("gunfold")
 toConstr_RDR   = varQual_RDR gENERICS_Name FSLIT("toConstr")
 dataTypeOf_RDR = varQual_RDR gENERICS_Name FSLIT("dataTypeOf")
 mkConstr_RDR   = varQual_RDR gENERICS_Name FSLIT("mkConstr")
 mkDataType_RDR = varQual_RDR gENERICS_Name FSLIT("mkDataType")
-conIndex_RDR   = varQual_RDR gENERICS_Name FSLIT("conIndex")
+conIndex_RDR   = varQual_RDR gENERICS_Name FSLIT("constrIndex")
 prefix_RDR     = dataQual_RDR gENERICS_Name FSLIT("Prefix")
 infix_RDR      = dataQual_RDR gENERICS_Name FSLIT("Infix")
 \end{code}
@@ -1417,6 +1450,8 @@ a_Pat             = nlVarPat a_RDR
 b_Pat          = nlVarPat b_RDR
 c_Pat          = nlVarPat c_RDR
 d_Pat          = nlVarPat d_RDR
+k_Pat          = nlVarPat k_RDR
+z_Pat          = nlVarPat z_RDR
 
 con2tag_RDR, tag2con_RDR, maxtag_RDR :: TyCon ->  RdrName
 -- Generates Orig s RdrName, for the binding positions