[project @ 2000-10-12 13:44:59 by simonpj]
[ghc-hetmet.git] / ghc / compiler / typecheck / TcDeriv.lhs
index 156a180..75f8d34 100644 (file)
@@ -10,39 +10,35 @@ module TcDeriv ( tcDeriving ) where
 
 #include "HsVersions.h"
 
-import HsSyn           ( HsBinds(..), MonoBinds(..), collectMonoBinders )
+import HsSyn           ( HsBinds(..), MonoBinds(..), collectLocatedMonoBinders )
 import RdrHsSyn                ( RdrNameMonoBinds )
-import RnHsSyn         ( RenamedHsBinds, RenamedMonoBinds )
+import RnHsSyn         ( RenamedHsBinds )
 import CmdLineOpts     ( opt_D_dump_deriv )
 
 import TcMonad
-import Inst            ( InstanceMapper )
-import TcEnv           ( getEnvTyCons )
+import TcEnv           ( InstEnv, getEnvTyCons, tcSetInstEnv, newDFunName )
 import TcGenDeriv      -- Deriv stuff
-import TcInstUtil      ( InstInfo(..), buildInstanceEnvs )
+import TcInstUtil      ( InstInfo(..), pprInstInfo, instInfoClass, simpleInstInfoTyCon, buildInstanceEnv )
 import TcSimplify      ( tcSimplifyThetas )
 
 import RnBinds         ( rnMethodBinds, rnTopMonoBinds )
-import RnEnv           ( newDFunName, bindLocatedLocalsRn )
+import RnEnv           ( bindLocatedLocalsRn )
 import RnMonad         ( RnNameSupply, 
                          renameSourceCode, thenRn, mapRn, returnRn )
 
 import Bag             ( Bag, emptyBag, unionBags, listToBag )
 import Class           ( classKey, Class )
-import ErrUtils                ( dumpIfSet, Message, pprBagOfErrors )
+import ErrUtils                ( dumpIfSet, Message )
 import MkId            ( mkDictFunId )
 import Id              ( mkVanillaId )
 import DataCon         ( dataConArgTys, isNullaryDataCon, isExistentialDataCon )
 import PrelInfo                ( needsDataDeclCtxtClassKeys )
 import Maybes          ( maybeToBool, catMaybes )
-import Module          ( ModuleName )
-import Name            ( isLocallyDefined, getSrcLoc,
-                         Name, NamedThing(..),
-                         OccName, nameOccName
-                       )
+import Module          ( Module )
+import Name            ( isLocallyDefined, getSrcLoc, NamedThing(..) )
 import RdrName         ( RdrName )
-import RnMonad         ( Fixities )
-import SrcLoc          ( mkGeneratedSrcLoc, SrcLoc )
+import RnMonad         ( FixityEnv )
+
 import TyCon           ( tyConTyVars, tyConDataCons, tyConDerivings,
                          tyConTheta, maybeTyConSingleCon, isDataTyCon,
                          isEnumerationTyCon, isAlgTyCon, TyCon
@@ -53,9 +49,10 @@ import Type          ( TauType, mkTyVarTys, mkTyConApp,
                        )
 import TysWiredIn      ( voidTy )
 import Var             ( TyVar )
-import Unique          -- Keys stuff
+import PrelNames
 import Bag             ( bagToList )
-import Util            ( zipWithEqual, sortLt, removeDups,  assoc, thenCmp )
+import Util            ( zipWithEqual, sortLt, thenCmp )
+import ListSetOps      ( removeDups,  assoc )
 import Outputable
 \end{code}
 
@@ -186,14 +183,13 @@ context to the instance decl.  The "offending classes" are
 %************************************************************************
 
 \begin{code}
-tcDeriving  :: ModuleName              -- name of module under scrutiny
-           -> Fixities                 -- for the deriving code (Show/Read.)
-           -> RnNameSupply             -- for "renaming" bits of generated code
+tcDeriving  :: PersistentRenamerState
+           -> Module                   -- name of module under scrutiny
            -> Bag InstInfo             -- What we already know about instances
-           -> TcM s (Bag InstInfo,     -- The generated "instance decls".
+           -> TcM (Bag InstInfo,       -- The generated "instance decls".
                      RenamedHsBinds)   -- Extra generated bindings
 
-tcDeriving modname fixs rn_name_supply inst_decl_infos_in
+tcDeriving prs mod inst_decl_infos_in
   = recoverTc (returnTc (emptyBag, EmptyBinds)) $
 
        -- Fish the "deriving"-related information out of the TcEnv
@@ -217,47 +213,47 @@ tcDeriving modname fixs rn_name_supply inst_decl_infos_in
     gen_taggery_Names new_inst_infos           `thenTc` \ nm_alist_etc ->
 
 
+    tcGetEnv                                   `thenNF_Tc` \ env ->
     let
        extra_mbind_list = map gen_tag_n_con_monobind nm_alist_etc
        extra_mbinds     = foldr AndMonoBinds EmptyMonoBinds extra_mbind_list
-       method_binds_s   = map (gen_bind fixs) new_inst_infos
-       mbinders         = bagToList (collectMonoBinders extra_mbinds)
+       method_binds_s   = map (gen_bind (tcGST env)) new_inst_infos
+       mbinders         = collectLocatedMonoBinders extra_mbinds
        
        -- Rename to get RenamedBinds.
        -- The only tricky bit is that the extra_binds must scope over the
        -- method bindings for the instances.
-       (dfun_names_w_method_binds, rn_extra_binds)
-               = renameSourceCode modname rn_name_supply (
+       (rn_method_binds_s, rn_extra_binds)
+               = renameSourceCode mod prs (
                        bindLocatedLocalsRn (ptext (SLIT("deriving"))) mbinders $ \ _ ->
                        rnTopMonoBinds extra_mbinds []          `thenRn` \ (rn_extra_binds, _) ->
-                       mapRn rn_one method_binds_s             `thenRn` \ dfun_names_w_method_binds ->
-                       returnRn (dfun_names_w_method_binds, rn_extra_binds)
+                       mapRn rn_meths method_binds_s           `thenRn` \ rn_method_binds_s ->
+                       returnRn (rn_method_binds_s, rn_extra_binds)
                  )
-       rn_one (cl_nm, tycon_nm, meth_binds) 
-               = newDFunName (cl_nm, tycon_nm)
-                             mkGeneratedSrcLoc         `thenRn` \ dfun_name ->
-                 rnMethodBinds meth_binds              `thenRn` \ (rn_meth_binds, _) ->
-                 returnRn (dfun_name, rn_meth_binds)
-
-       really_new_inst_infos = zipWith gen_inst_info
-                                       new_inst_infos
-                                       dfun_names_w_method_binds
-
-       ddump_deriv = ddump_deriving really_new_inst_infos rn_extra_binds
     in
-    ioToTc (dumpIfSet opt_D_dump_deriv "Derived instances" ddump_deriv)        `thenTc_`
+    mapNF_Tc gen_inst_info (new_inst_infos `zip` rn_method_binds_s)    `thenNF_Tc` \ really_new_inst_infos ->
+
+    ioToTc (dumpIfSet opt_D_dump_deriv "Derived instances" 
+                     (ddump_deriving really_new_inst_infos rn_extra_binds))    `thenTc_`
 
     returnTc (listToBag really_new_inst_infos, rn_extra_binds)
   where
     ddump_deriving :: [InstInfo] -> RenamedHsBinds -> SDoc
     ddump_deriving inst_infos extra_binds
-      = vcat (map pp_info inst_infos) $$ ppr extra_binds
+      = vcat (map pprInstInfo inst_infos) $$ ppr extra_binds
       where
-       pp_info (InstInfo clas tvs [ty] inst_decl_theta _ mbinds _ _)
-         = ppr (mkSigmaTy tvs inst_decl_theta' (mkDictTy clas [ty]))
-           $$
-           ppr mbinds
-           where inst_decl_theta' = classesToPreds inst_decl_theta
+
+       -- Paste the dfun id and method binds into the InstInfo
+    gen_inst_info (InstInfo clas tyvars tys@(ty:_) inst_decl_theta _ _ locn _, meth_binds)
+      = newDFunName mod clas tys locn  `thenNF_Tc` \ dfun_name ->
+       let
+           dfun_id = mkDictFunId dfun_name clas tyvars tys inst_decl_theta
+       in
+       returnNF_Tc (InstInfo clas tyvars tys inst_decl_theta
+                             dfun_id meth_binds locn [])
+
+    rn_meths meths = rnMethodBinds [] meths `thenRn` \ (meths', _) -> returnRn meths'
+       -- Ignore the free vars returned
 \end{code}
 
 
@@ -283,7 +279,7 @@ or} has just one data constructor (e.g., tuples).
 all those.
 
 \begin{code}
-makeDerivEqns :: TcM s [DerivEqn]
+makeDerivEqns :: TcM [DerivEqn]
 
 makeDerivEqns
   = tcGetEnv                       `thenNF_Tc` \ env ->
@@ -293,7 +289,6 @@ makeDerivEqns
 
        think_about_deriving = need_deriving local_data_tycons
        (derive_these, _)    = removeDups cmp_deriv think_about_deriving
-       eqns                 = map mk_eqn derive_these
     in
     if null local_data_tycons then
        returnTc []     -- Bale out now
@@ -316,7 +311,7 @@ makeDerivEqns
       = (c1 `compare` c2) `thenCmp` (t1 `compare` t2)
 
     ------------------------------------------------------------------
-    mk_eqn :: (Class, TyCon) -> NF_TcM s (Maybe DerivEqn)
+    mk_eqn :: (Class, TyCon) -> NF_TcM (Maybe DerivEqn)
        -- we swizzle the tyvars and datacons out of the tycon
        -- to make the rest of the equation
 
@@ -351,14 +346,12 @@ makeDerivEqns
     ------------------------------------------------------------------
     chk_out :: Class -> TyCon -> Maybe Message
     chk_out clas tycon
-       | clas_key == enumClassKey    && not is_enumeration           = bog_out nullary_why
-       | clas_key == boundedClassKey && not is_enumeration_or_single = bog_out single_nullary_why
-       | clas_key == ixClassKey      && not is_enumeration_or_single = bog_out single_nullary_why
+       | clas `hasKey` enumClassKey    && not is_enumeration         = bog_out nullary_why
+       | clas `hasKey` boundedClassKey && not is_enumeration_or_single = bog_out single_nullary_why
+       | clas `hasKey` ixClassKey      && not is_enumeration_or_single = bog_out single_nullary_why
        | any isExistentialDataCon (tyConDataCons tycon)              = Just (existentialErr clas tycon)
        | otherwise                                                   = Nothing
        where
-           clas_key = classKey clas
-
            is_enumeration = isEnumerationTyCon tycon
            is_single_con  = maybeToBool (maybeTyConSingleCon tycon)
            is_enumeration_or_single = is_enumeration || is_single_con
@@ -392,7 +385,7 @@ ordered by sorting on type varible, tv, (major key) and then class, k,
 \begin{code}
 solveDerivEqns :: Bag InstInfo
               -> [DerivEqn]
-              -> TcM s [InstInfo]      -- Solns in same order as eqns.
+              -> TcM [InstInfo]        -- Solns in same order as eqns.
                                        -- This bunch is Absolutely minimal...
 
 solveDerivEqns inst_decl_infos_in orig_eqns
@@ -409,7 +402,7 @@ solveDerivEqns inst_decl_infos_in orig_eqns
        -- compares it with the current one; finishes if they are the
        -- same, otherwise recurses with the new solutions.
        -- It fails if any iteration fails
-    iterateDeriv :: [DerivSoln] ->TcM s [InstInfo]
+    iterateDeriv :: [DerivSoln] ->TcM [InstInfo]
     iterateDeriv current_solns
       = checkNoErrsTc (iterateOnce current_solns)      `thenTc` \ (new_inst_infos, new_solns) ->
        if (current_solns == new_solns) then
@@ -423,15 +416,15 @@ solveDerivEqns inst_decl_infos_in orig_eqns
            -- with the current set of solutions, giving a
 
        add_solns inst_decl_infos_in orig_eqns current_solns
-                               `thenNF_Tc` \ (new_inst_infos, inst_mapper) ->
-       let
-          class_to_inst_env cls = inst_mapper cls
-       in
+                               `thenNF_Tc` \ (new_inst_infos, inst_env) ->
+
            -- Simplify each RHS
 
-       listTc [ tcAddErrCtxt (derivCtxt tc) $
-                tcSimplifyThetas class_to_inst_env deriv_rhs
-              | (_,tc,_,deriv_rhs) <- orig_eqns ]  `thenTc` \ next_solns ->
+       tcSetInstEnv inst_env (
+         listTc [ tcAddErrCtxt (derivCtxt tc) $
+                  tcSimplifyThetas deriv_rhs
+                | (_,tc,_,deriv_rhs) <- orig_eqns ]  
+       )                                               `thenTc` \ next_solns ->
 
            -- Canonicalise the solutions, so they compare nicely
        let canonicalised_next_solns
@@ -443,19 +436,19 @@ solveDerivEqns inst_decl_infos_in orig_eqns
 \begin{code}
 add_solns :: Bag InstInfo                      -- The global, non-derived ones
          -> [DerivEqn] -> [DerivSoln]
-         -> NF_TcM s ([InstInfo],              -- The new, derived ones
-                      InstanceMapper)
+         -> NF_TcM ([InstInfo],                -- The new, derived ones
+                      InstEnv)
     -- the eqns and solns move "in lockstep"; we have the eqns
     -- because we need the LHS info for addClassInstance.
 
 add_solns inst_infos_in eqns solns
 
-  = discardErrsTc (buildInstanceEnvs all_inst_infos)   `thenNF_Tc` \ inst_mapper ->
+  = discardErrsTc (buildInstanceEnv all_inst_infos)    `thenNF_Tc` \ inst_env ->
        -- We do the discard-errs so that we don't get repeated error messages
        -- about duplicate instances.
-       -- They'll appear later, when we do the top-level buildInstanceEnvs.
+       -- They'll appear later, when we do the top-level buildInstanceEnv.
 
-    returnNF_Tc (new_inst_infos, inst_mapper)
+    returnNF_Tc (new_inst_infos, inst_env)
   where
     new_inst_infos = zipWithEqual "add_solns" mk_deriv_inst_info eqns solns
 
@@ -463,7 +456,7 @@ add_solns inst_infos_in eqns solns
 
     mk_deriv_inst_info (clas, tycon, tyvars, _) theta
       = InstInfo clas tyvars [mkTyConApp tycon (mkTyVarTys tyvars)]
-                theta
+                theta'
                 dummy_dfun_id
                 (my_panic "binds") (getSrcLoc tycon)
                 (my_panic "upragmas")
@@ -554,50 +547,24 @@ the renamer.  What a great hack!
 -- Generate the method bindings for the required instance
 -- (paired with class name, as we need that when generating dict
 --  names.)
-gen_bind :: Fixities -> InstInfo -> ({-class-}OccName, {-tyCon-}OccName, RdrNameMonoBinds)
-gen_bind fixities (InstInfo clas _ [ty] _ _ _ _ _)
-  | not from_here 
-  = (clas_nm, tycon_nm, EmptyMonoBinds)
-  |  ckey == showClassKey 
-  = (clas_nm, tycon_nm, gen_Show_binds fixities tycon)
-  |  ckey == readClassKey 
-  = (clas_nm, tycon_nm, gen_Read_binds fixities tycon)
+gen_bind :: GlobalSymbolTable -> InstInfo -> RdrNameMonoBinds
+gen_bind fixities inst
+  | not (isLocallyDefined tycon) = EmptyMonoBinds
+  | clas `hasKey` showClassKey   = gen_Show_binds fixities tycon
+  | clas `hasKey` readClassKey   = gen_Read_binds fixities tycon
   | otherwise
-  = (clas_nm, tycon_nm,
-     assoc "gen_bind:bad derived class"
+  = assoc "gen_bind:bad derived class"
           [(eqClassKey,      gen_Eq_binds)
           ,(ordClassKey,     gen_Ord_binds)
           ,(enumClassKey,    gen_Enum_binds)
           ,(boundedClassKey, gen_Bounded_binds)
           ,(ixClassKey,      gen_Ix_binds)
           ]
-          ckey
-          tycon)
-  where
-      clas_nm     = nameOccName (getName clas)
-      tycon_nm    = nameOccName (getName tycon)
-      from_here   = isLocallyDefined tycon
-      (tycon,_,_) = splitAlgTyConApp ty        
-      ckey       = classKey clas
-           
-
-gen_inst_info :: InstInfo
-             -> (Name, RenamedMonoBinds)
-             -> InstInfo                               -- the gen'd (filled-in) "instance decl"
-
-gen_inst_info (InstInfo clas tyvars tys@(ty:_) inst_decl_theta _ _ locn _) 
-             (dfun_name, meth_binds)
-  =
-       -- Generate the various instance-related Ids
-    InstInfo clas tyvars tys inst_decl_theta
-              dfun_id
-              meth_binds
-              locn []
+          (classKey clas)
+          tycon
   where
-   dfun_id = mkDictFunId dfun_name clas tyvars tys inst_decl_theta
-
-   from_here = isLocallyDefined tycon
-   (tycon,_,_) = splitAlgTyConApp ty
+      clas  = instInfoClass inst
+      tycon = simpleInstInfoTyCon inst
 \end{code}
 
 
@@ -635,7 +602,7 @@ If we have a @tag2con@ function, we also generate a @maxtag@ constant.
 
 \begin{code}
 gen_taggery_Names :: [InstInfo]
-                 -> TcM s [(RdrName,   -- for an assoc list
+                 -> TcM [(RdrName,     -- for an assoc list
                             TyCon,     -- related tycon
                             TagThingWanted)]
 
@@ -644,11 +611,9 @@ gen_taggery_Names inst_infos
     foldlTc do_con2tag []           tycons_of_interest `thenTc` \ names_so_far ->
     foldlTc do_tag2con names_so_far tycons_of_interest
   where
-    all_CTs = [ (c, get_tycon ty) | (InstInfo c _ [ty] _ _ _ _ _) <- inst_infos ]
+    all_CTs = [ (instInfoClass info, simpleInstInfoTyCon info) | info <- inst_infos ]
                    
-    get_tycon ty = case splitAlgTyConApp ty of { (tc, _, _) -> tc }
-
-    all_tycons = map snd all_CTs
+    all_tycons             = map snd all_CTs
     (tycons_of_interest, _) = removeDups compare all_tycons
     
     do_con2tag acc_Names tycon