Add tuple sections as a new feature
[ghc-hetmet.git] / compiler / typecheck / TcGenDeriv.lhs
index 92a39d9..2192531 100644 (file)
@@ -23,7 +23,9 @@ module TcGenDeriv (
        gen_Show_binds,
        gen_Data_binds,
        gen_Typeable_binds,
-       gen_Functor_binds, functorLikeTraverse, deepSubtypesContaining,
+       gen_Functor_binds, 
+       FFoldType(..), functorLikeTraverse, 
+       deepSubtypesContaining, foldDataConArgs,
        gen_Foldable_binds,
        gen_Traversable_binds,
        genAuxBind
@@ -40,7 +42,6 @@ import Name
 import HscTypes
 import PrelInfo
 import PrelNames
-import MkId
 import PrimOp
 import SrcLoc
 import TyCon
@@ -48,6 +49,7 @@ import TcType
 import TysPrim
 import TysWiredIn
 import Type
+import Var( TyVar )
 import TypeRep
 import VarSet
 import State
@@ -55,9 +57,7 @@ import Util
 import MonadUtils
 import Outputable
 import FastString
-import OccName
 import Bag
-
 import Data.List       ( partition, intersperse )
 \end{code}
 
@@ -718,7 +718,7 @@ gen_Ix_binds loc tycon
 
        mk_qual a b c = noLoc $ mkBindStmt (nlVarPat c)
                                 (nlHsApp (nlHsVar range_RDR) 
-                                       (nlTuple [nlHsVar a, nlHsVar b] Boxed))
+                                         (mkLHsVarTuple [a,b]))
 
     ----------------
     single_con_index
@@ -740,11 +740,11 @@ gen_Ix_binds loc tycon
            ) plus_RDR (
                genOpApp (
                    (nlHsApp (nlHsVar unsafeRangeSize_RDR) 
-                          (nlTuple [nlHsVar l, nlHsVar u] Boxed))
+                            (mkLHsVarTuple [l,u]))
                ) times_RDR (mk_index rest)
           )
        mk_one l u i
-         = nlHsApps unsafeIndex_RDR [nlTuple [nlHsVar l, nlHsVar u] Boxed, nlHsVar i]
+         = nlHsApps unsafeIndex_RDR [mkLHsVarTuple [l,u], nlHsVar i]
 
     ------------------
     single_con_inRange
@@ -753,8 +753,7 @@ gen_Ix_binds loc tycon
                 con_pat cs_needed] $
          foldl1 and_Expr (zipWith3Equal "single_con_inRange" in_range as_needed bs_needed cs_needed)
       where
-       in_range a b c = nlHsApps inRange_RDR [nlTuple [nlHsVar a, nlHsVar b] Boxed,
-                                              nlHsVar c]
+       in_range a b c = nlHsApps inRange_RDR [mkLHsVarTuple [a,b], nlHsVar c]
 \end{code}
 
 %************************************************************************
@@ -832,9 +831,8 @@ gen_Read_binds get_fixity loc tycon
             _     -> [nlHsApp (nlHsVar choose_RDR) 
                              (nlList (map mk_pair nullary_cons))]
     
-    mk_pair con = nlTuple [nlHsLit (mkHsString (data_con_str con)), 
-                          result_expr con []]
-                         Boxed
+    mk_pair con = mkLHsTupleExpr [nlHsLit (mkHsString (data_con_str con)), 
+                                 result_expr con []]
     
     read_non_nullary_con data_con
       | is_infix  = mk_parser infix_prec  infix_stmts  body
@@ -1095,7 +1093,7 @@ gen_Typeable_binds loc tycon
                [nlWildPat] 
                (nlHsApps mkTypeRep_RDR [tycon_rep, nlList []])
   where
-    tycon_rep = nlHsVar mkTyConRep_RDR `nlHsApp` nlHsLit (mkHsString (showSDoc (ppr tycon)))
+    tycon_rep = nlHsVar mkTyConRep_RDR `nlHsApp` nlHsLit (mkHsString (showSDocOneLine (ppr tycon)))
 
 mk_typeOf_RDR :: TyCon -> RdrName
 -- Use the arity of the TyCon to make the right typeOfn function
@@ -1139,13 +1137,18 @@ we generate
     
     dataTypeOf _ = $dT
 
+    dataCast1 = gcast1   -- If T :: * -> *
+    dataCast2 = gcast2   -- if T :: * -> * -> *
+
+    
 \begin{code}
 gen_Data_binds :: SrcSpan
               -> TyCon 
               -> (LHsBinds RdrName,    -- The method bindings
                   DerivAuxBinds)       -- Auxiliary bindings
 gen_Data_binds loc tycon
-  = (listToBag [gfoldl_bind, gunfold_bind, toCon_bind, dataTypeOf_bind],
+  = (listToBag [gfoldl_bind, gunfold_bind, toCon_bind, dataTypeOf_bind]
+     `unionBags` gcast_binds,
                -- Auxiliary definitions: the data type and constructors
      MkTyCon tycon : map MkDataCon data_cons)
   where
@@ -1197,13 +1200,31 @@ gen_Data_binds loc tycon
                        [nlWildPat]
                         (nlHsVar (mk_data_type_name tycon))
 
+       ------------ gcast1/2
+    tycon_kind = tyConKind tycon
+    gcast_binds | tycon_kind `eqKind` kind1 = mk_gcast dataCast1_RDR gcast1_RDR
+               | tycon_kind `eqKind` kind2 = mk_gcast dataCast2_RDR gcast2_RDR
+               | otherwise           = emptyBag
+    mk_gcast dataCast_RDR gcast_RDR 
+      = unitBag (mk_easy_FunBind loc dataCast_RDR [nlVarPat f_RDR] 
+                                 (nlHsVar gcast_RDR `nlHsApp` nlHsVar f_RDR))
+
+
+kind1, kind2 :: Kind
+kind1 = liftedTypeKind `mkArrowKind` liftedTypeKind
+kind2 = liftedTypeKind `mkArrowKind` kind1
 
 gfoldl_RDR, gunfold_RDR, toConstr_RDR, dataTypeOf_RDR, mkConstr_RDR,
-    mkDataType_RDR, conIndex_RDR, prefix_RDR, infix_RDR :: RdrName
+    mkDataType_RDR, conIndex_RDR, prefix_RDR, infix_RDR,
+    dataCast1_RDR, dataCast2_RDR, gcast1_RDR, gcast2_RDR :: RdrName
 gfoldl_RDR     = varQual_RDR gENERICS (fsLit "gfoldl")
 gunfold_RDR    = varQual_RDR gENERICS (fsLit "gunfold")
 toConstr_RDR   = varQual_RDR gENERICS (fsLit "toConstr")
 dataTypeOf_RDR = varQual_RDR gENERICS (fsLit "dataTypeOf")
+dataCast1_RDR  = varQual_RDR gENERICS (fsLit "dataCast1")
+dataCast2_RDR  = varQual_RDR gENERICS (fsLit "dataCast2")
+gcast1_RDR     = varQual_RDR tYPEABLE (fsLit "gcast1")
+gcast2_RDR     = varQual_RDR tYPEABLE (fsLit "gcast2")
 mkConstr_RDR   = varQual_RDR gENERICS (fsLit "mkConstr")
 mkDataType_RDR = varQual_RDR gENERICS (fsLit "mkDataType")
 conIndex_RDR   = varQual_RDR gENERICS (fsLit "constrIndex")
@@ -1215,7 +1236,10 @@ infix_RDR      = dataQual_RDR gENERICS (fsLit "Infix")
 
 %************************************************************************
 %*                                                                     *
-       Functor instances
+                       Functor instances
+
+ see http://www.mail-archive.com/haskell-prime@haskell.org/msg02116.html
+
 %*                                                                     *
 %************************************************************************
 
@@ -1280,27 +1304,27 @@ This is pretty much the same as $fmap, only without the $(cofmap 'a 'a) case:
 \begin{code}
 gen_Functor_binds :: SrcSpan -> TyCon -> (LHsBinds RdrName, DerivAuxBinds)
 gen_Functor_binds loc tycon
-  = (listToBag [fmap_bind], [])
+  = (unitBag fmap_bind, [])
   where
     data_cons = tyConDataCons tycon
-    arg = last (tyConTyVars tycon) -- argument to derive for, 'a in the above description
 
     fmap_bind = L loc $ mkFunBind (L loc fmap_RDR) (map fmap_eqn data_cons)
     fmap_eqn con = evalState (match_for_con [f_Pat] con parts) bs_RDRs
-      where parts = map derive_fmap_type (dataConOrigArgTys con)
-
-    derive_fmap_type :: Type -> LHsExpr RdrName -> State [RdrName] (LHsExpr RdrName)
-    derive_fmap_type = functorLikeTraverse
-        (\     x -> return x)                                         -- fmap f x = x
-        (\     x -> return (nlHsApp f_Expr x))                        -- fmap f x = f x
-        (panic "contravariant")
-        (\g h  x -> mkSimpleLam (\b -> h =<< (nlHsApp x `fmap` g b))) -- fmap f x = \b -> h (x (g b))
-        (mkSimpleTupleCase match_for_con)                             -- fmap f x = case x of (a1,a2,..) -> (g1 a1,g2 a2,..)
-        (\_ g  x -> do gg <- mkSimpleLam g
-                       return $ nlHsApps fmap_RDR [gg,x])             -- fmap f x = fmap g x
-        (panic "in other argument")
-        (\_ g  x -> g x)
-        arg
+      where 
+        parts = foldDataConArgs ft_fmap con
+
+    ft_fmap :: FFoldType (LHsExpr RdrName -> State [RdrName] (LHsExpr RdrName))
+    -- Tricky higher order type; I can't say I fully understand this code :-(
+    ft_fmap = FT { ft_triv = \x -> return x                    -- fmap f x = x
+                , ft_var  = \x -> return (nlHsApp f_Expr x)   -- fmap f x = f x
+                , ft_fun = \g h x -> mkSimpleLam (\b -> h =<< (nlHsApp x `fmap` g b)) 
+                                                              -- fmap f x = \b -> h (x (g b))
+                , ft_tup = mkSimpleTupleCase match_for_con    -- fmap f x = case x of (a1,a2,..) -> (g1 a1,g2 a2,..)
+                , ft_ty_app = \_ g  x -> do gg <- mkSimpleLam g      -- fmap f x = fmap g x
+                                            return $ nlHsApps fmap_RDR [gg,x]        
+                , ft_forall = \_ g  x -> g x
+                , ft_bad_app = panic "in other argument"
+                , ft_co_var = panic "contravariant" }
 
     match_for_con = mkSimpleConMatch $
         \con_name xsM -> do xs <- sequence xsM
@@ -1314,19 +1338,27 @@ This function works like a fold: it makes a value of type 'a' in a bottom up way
 
 \begin{code}
 -- Generic traversal for Functor deriving
-functorLikeTraverse :: a                    -- ^ Case: does not contain variable
-                    -> a                    -- ^ Case: the variable itself
-                    -> a                    -- ^ Case: the variable itself, contravariantly
-                    -> (a -> a -> a)        -- ^ Case: function type
-                    -> (Boxity -> [a] -> a) -- ^ Case: tuple type
-                    -> (Type -> a -> a)     -- ^ Case: type app, variable only in last argument
-                    -> a                    -- ^ Case: type app, variable other than in last argument
-                    -> (TcTyVar -> a -> a)  -- ^ Case: forall type
-                    -> TcTyVar              -- ^ Variable to look for
-                    -> Type                 -- ^ Type to process
-                    -> a
-functorLikeTraverse caseTrivial caseVar caseCoVar caseFun caseTuple caseTyApp caseWrongArg caseForAll var ty
-    = fst (go False ty)
+data FFoldType a      -- Describes how to fold over a Type in a functor like way
+   = FT { ft_triv    :: a                  -- Does not contain variable
+       , ft_var     :: a                   -- The variable itself                             
+       , ft_co_var  :: a                   -- The variable itself, contravariantly            
+       , ft_fun     :: a -> a -> a         -- Function type
+       , ft_tup     :: Boxity -> [a] -> a  -- Tuple type 
+       , ft_ty_app  :: Type -> a -> a      -- Type app, variable only in last argument        
+       , ft_bad_app :: a                   -- Type app, variable other than in last argument  
+       , ft_forall  :: TcTyVar -> a -> a   -- Forall type                                     
+     }
+
+functorLikeTraverse :: TyVar        -- ^ Variable to look for
+                   -> FFoldType a   -- ^ How to fold
+                   -> Type          -- ^ Type to process
+                   -> a
+functorLikeTraverse var (FT { ft_triv = caseTrivial,     ft_var = caseVar
+                            , ft_co_var = caseCoVar,     ft_fun = caseFun
+                            , ft_tup = caseTuple,        ft_ty_app = caseTyApp 
+                           , ft_bad_app = caseWrongArg, ft_forall = caseForAll })
+                   ty
+  = fst (go False ty)
   where -- go returns (result of type a, does type contain var)
         go co ty | Just ty' <- coreView ty = go co ty'
         go co (TyVarTy    v) | v == var = (if co then caseCoVar else caseVar,True)
@@ -1351,20 +1383,31 @@ functorLikeTraverse caseTrivial caseVar caseCoVar caseFun caseTuple caseTyApp ca
 
 -- Return all syntactic subterms of ty that contain var somewhere
 -- These are the things that should appear in instance constraints
-deepSubtypesContaining :: TcTyVar -> TcType -> [TcType]
-deepSubtypesContaining = functorLikeTraverse
-      []
-      []
-      (panic "contravariant")
-      (\x y   -> x ++ y)      -- function
-      (\_  xs -> concat xs)   -- tuple
-      (\ty x  -> ty : x)      -- tyapp
-      (panic "in other argument")
-      (\v x   -> filter (not . (v `elemVarSet`) . tyVarsOfType) x) -- forall v
-
+deepSubtypesContaining :: TyVar -> Type -> [TcType]
+deepSubtypesContaining tv
+  = functorLikeTraverse tv 
+       (FT { ft_triv = []
+           , ft_var = []
+           , ft_fun = (++), ft_tup = \_ xs -> concat xs
+           , ft_ty_app = (:)
+           , ft_bad_app = panic "in other argument"
+           , ft_co_var = panic "contravariant"
+           , ft_forall = \v xs -> filterOut ((v `elemVarSet`) . tyVarsOfType) xs })
+
+
+foldDataConArgs :: FFoldType a -> DataCon -> [a]
+-- Fold over the arguments of the datacon
+foldDataConArgs ft con
+  = map (functorLikeTraverse tv ft) (dataConOrigArgTys con)
+  where
+    tv = last (dataConUnivTyVars con) 
+                   -- Argument to derive for, 'a in the above description
+                   -- The validity checks have ensured that con is
+                   -- a vanilla data constructor
 
 -- Make a HsLam using a fresh variable from a State monad
 mkSimpleLam :: (LHsExpr id -> State [id] (LHsExpr id)) -> State [id] (LHsExpr id)
+-- (mkSimpleLam fn) returns (\x. fn(x))
 mkSimpleLam lam = do
     (n:names) <- get
     put names
@@ -1399,7 +1442,10 @@ mkSimpleTupleCase match_for_con boxity insides x = do
 
 %************************************************************************
 %*                                                                     *
-       Foldable instances
+                       Foldable instances
+
+ see http://www.mail-archive.com/haskell-prime@haskell.org/msg02116.html
+
 %*                                                                     *
 %************************************************************************
 
@@ -1423,27 +1469,25 @@ since (f :: a -> b -> b), while (foldr f :: b -> t a -> b).
 \begin{code}
 gen_Foldable_binds :: SrcSpan -> TyCon -> (LHsBinds RdrName, DerivAuxBinds)
 gen_Foldable_binds loc tycon
-  = (listToBag [foldr_bind], [])
+  = (unitBag foldr_bind, [])
   where
     data_cons = tyConDataCons tycon
-    arg = last (tyConTyVars tycon) -- argument to derive for, 'a in the above description
 
-    foldr_bind = L loc $ mkFunBind (L loc foldr_RDR) (map foldr_eqn data_cons)
+    foldr_bind = L loc $ mkFunBind (L loc foldable_foldr_RDR) (map foldr_eqn data_cons)
     foldr_eqn con = evalState (match_for_con z_Expr [f_Pat,z_Pat] con parts) bs_RDRs
-      where parts = map derive_foldr_type (dataConOrigArgTys con)
-
-    derive_foldr_type :: Type -> LHsExpr RdrName -> LHsExpr RdrName -> State [RdrName] (LHsExpr RdrName)
-    derive_foldr_type = functorLikeTraverse
-        (\     _ z -> return z)                            -- foldr f z x = z
-        (\     x z -> return (nlHsApps f_RDR [x,z]))       -- foldr f z x = f x z
-        (panic "function")
-        (panic "function")
-        (\b gs x z -> mkSimpleTupleCase (match_for_con z) b gs x)
-        (\_ g  x z -> do gg <- mkSimpleLam2 g              -- foldr f z x = foldr (\xx zz -> g xx zz) z x
-                         return $ nlHsApps foldable_foldr_RDR [gg,z,x])
-        (panic "in other argument")
-        (\_ g  x z -> g x z)
-        arg
+      where 
+        parts = foldDataConArgs ft_foldr con
+
+    ft_foldr :: FFoldType (LHsExpr RdrName -> LHsExpr RdrName -> State [RdrName] (LHsExpr RdrName))
+    ft_foldr = FT { ft_triv = \_ z -> return z                        -- foldr f z x = z
+                 , ft_var  = \x z -> return (nlHsApps f_RDR [x,z])   -- foldr f z x = f x z
+                 , ft_tup = \b gs x z -> mkSimpleTupleCase (match_for_con z) b gs x
+                 , ft_ty_app = \_ g  x z -> do gg <- mkSimpleLam2 g   -- foldr f z x = foldr (\xx zz -> g xx zz) z x
+                                               return $ nlHsApps foldable_foldr_RDR [gg,z,x]
+                 , ft_forall = \_ g  x z -> g x z
+                 , ft_co_var = panic "covariant"
+                 , ft_fun = panic "function"
+                 , ft_bad_app = panic "in other argument" }
 
     match_for_con z = mkSimpleConMatch (\_con_name -> foldrM ($) z) -- g1 v1 (g2 v2 (.. z))
 \end{code}
@@ -1451,7 +1495,9 @@ gen_Foldable_binds loc tycon
 
 %************************************************************************
 %*                                                                     *
-       Traversable instances
+                       Traversable instances
+
+ see http://www.mail-archive.com/haskell-prime@haskell.org/msg02116.html
 %*                                                                     *
 %************************************************************************
 
@@ -1474,27 +1520,27 @@ instead of:         traverse f (T x y) = T x <$> f y
 \begin{code}
 gen_Traversable_binds :: SrcSpan -> TyCon -> (LHsBinds RdrName, DerivAuxBinds)
 gen_Traversable_binds loc tycon
-  = (listToBag [traverse_bind], [])
+  = (unitBag traverse_bind, [])
   where
     data_cons = tyConDataCons tycon
-    arg = last (tyConTyVars tycon) -- argument to derive for, 'a in the above description
 
     traverse_bind = L loc $ mkFunBind (L loc traverse_RDR) (map traverse_eqn data_cons)
     traverse_eqn con = evalState (match_for_con [f_Pat] con parts) bs_RDRs
-      where parts = map derive_travese_type (dataConOrigArgTys con)
-
-    derive_travese_type :: Type -> LHsExpr RdrName -> State [RdrName] (LHsExpr RdrName)
-    derive_travese_type = functorLikeTraverse
-        (\     x -> return (nlHsApps pure_RDR [x]))    -- traverse f x = pure x
-        (\     x -> return (nlHsApps f_RDR [x]))       -- travese f x = f x
-        (panic "function")
-        (panic "function")
-        (mkSimpleTupleCase match_for_con)              -- travese f x z = case x of (a1,a2,..) -> (,,) <$> g1 a1 <*> g2 a2 <*> ..
-        (\_ g  x -> do gg <- mkSimpleLam g             -- travese f x = travese (\xx -> g xx) x
-                       return $ nlHsApps traverse_RDR [gg,x])
-        (panic "in other argument")
-        (\_ g  x -> g x)
-        arg
+      where 
+        parts = foldDataConArgs ft_trav con
+
+
+    ft_trav :: FFoldType (LHsExpr RdrName -> State [RdrName] (LHsExpr RdrName))
+    ft_trav = FT { ft_triv = \x -> return (nlHsApps pure_RDR [x])   -- traverse f x = pure x
+                , ft_var = \x -> return (nlHsApps f_RDR [x])       -- travese f x = f x
+                , ft_tup = mkSimpleTupleCase match_for_con         -- travese f x z = case x of (a1,a2,..) -> 
+                                                                   --                   (,,) <$> g1 a1 <*> g2 a2 <*> ..
+                , ft_ty_app = \_ g  x -> do gg <- mkSimpleLam g    -- travese f x = travese (\xx -> g xx) x
+                                            return $ nlHsApps traverse_RDR [gg,x]
+                , ft_forall = \_ g  x -> g x
+                , ft_co_var = panic "covariant"
+                , ft_fun = panic "function"
+                , ft_bad_app = panic "in other argument" }
 
     match_for_con = mkSimpleConMatch $
         \con_name xsM -> do xs <- sequence xsM
@@ -1580,7 +1626,7 @@ genAuxBind loc (GenMaxTag tycon)
 genAuxBind loc (MkTyCon tycon) --  $dT
   = mkVarBind loc (mk_data_type_name tycon)
                  ( nlHsVar mkDataType_RDR 
-                    `nlHsApp` nlHsLit (mkHsString (showSDoc (ppr tycon)))
+                    `nlHsApp` nlHsLit (mkHsString (showSDocOneLine (ppr tycon)))
                     `nlHsApp` nlList constrs )
   where
     constrs = [nlHsVar (mk_constr_name con) | con <- tyConDataCons tycon]