[project @ 2000-10-16 08:24:18 by simonpj]
[ghc-hetmet.git] / ghc / compiler / main / MkIface.lhs
index da7b866..1d709ef 100644 (file)
@@ -8,15 +8,14 @@ module MkIface ( writeIface  ) where
 
 #include "HsVersions.h"
 
-import IO              ( Handle, hPutStr, openFile, 
-                         hClose, hPutStrLn, IOMode(..) )
+import IO              ( openFile, hClose, IOMode(..) )
 
 import HsSyn
 import HsCore          ( HsIdInfo(..), toUfExpr )
-import RdrHsSyn                ( RdrNameRuleDecl )
+import RdrHsSyn                ( RdrNameRuleDecl, mkTyData )
 import HsPragmas       ( DataPragmas(..), ClassPragmas(..) )
 import HsTypes         ( toHsTyVars )
-import BasicTypes      ( Fixity(..), FixityDirection(..), NewOrData(..),
+import BasicTypes      ( Fixity(..), NewOrData(..),
                          Version, bumpVersion, initialVersion, isLoopBreaker
                        )
 import RnMonad
@@ -27,21 +26,21 @@ import CmdLineOpts
 import Id              ( Id, idType, idInfo, omitIfaceSigForId, isUserExportedId, hasNoBinding,
                          idSpecialisation
                        )
-import Var             ( isId )
+import Var             ( isId, varName )
 import VarSet
 import DataCon         ( StrictnessMark(..), dataConSig, dataConFieldLabels, dataConStrictMarks )
-import IdInfo          ( IdInfo, StrictnessInfo(..), ArityInfo(..), InlinePragInfo(..), 
+import IdInfo          ( IdInfo, StrictnessInfo(..), ArityInfo(..), 
                          CprInfo(..), CafInfo(..),
                          inlinePragInfo, arityInfo, arityLowerBound,
                          strictnessInfo, isBottomingStrictness,
                          cafInfo, specInfo, cprInfo, 
                          occInfo, isNeverInlinePrag,
-                         workerExists, workerInfo, WorkerInfo(..)
+                         workerInfo, WorkerInfo(..)
                        )
 import CoreSyn         ( CoreExpr, CoreBind, Bind(..), isBuiltinRule, rulesRules, rulesRhsFreeVars )
 import CoreFVs         ( exprSomeFreeVars, ruleSomeLhsFreeVars, ruleSomeFreeVars )
 import CoreUnfold      ( okToUnfoldInHiFile, couldBeSmallEnoughToInline )
-import Module          ( moduleString, pprModule, pprModuleName, moduleUserString )
+import Module          ( pprModuleName, moduleUserString )
 import Name            ( isLocallyDefined, isWiredInName, toRdrName, nameModule,
                          Name, NamedThing(..)
                        )
@@ -49,23 +48,21 @@ import OccName              ( OccName, pprOccName )
 import TyCon           ( TyCon, getSynTyConDefn, isSynTyCon, isNewTyCon, isAlgTyCon,
                          tyConTheta, tyConTyVars, tyConDataCons, tyConFamilySize
                        )
-import Class           ( Class, classExtraBigSig )
-import FieldLabel      ( fieldLabelName, fieldLabelType )
+import Class           ( classExtraBigSig, DefMeth(..) )
+import FieldLabel      ( fieldLabelType )
 import Type            ( mkSigmaTy, splitSigmaTy, mkDictTy, tidyTopType,
-                         deNoteType, classesToPreds,
-                         Type, ThetaType, PredType(..), ClassContext
+                         deNoteType, classesToPreds
                        )
 
-import PprType
-import Rules           ( pprProtoCoreRule, ProtoCoreRule(..) )
+import Rules           ( ProtoCoreRule(..) )
 
-import Bag             ( bagToList, isEmptyBag )
-import Maybes          ( catMaybes, maybeToBool )
+import Bag             ( bagToList )
 import UniqFM          ( lookupUFM, listToUFM )
-import Util            ( sortLt, mapAccumL )
+import Util            ( sortLt )
 import SrcLoc          ( noSrcLoc )
 import Bag
 import Outputable
+import ErrUtils                ( dumpIfSet )
 
 import Maybe           ( isNothing )
 import List            ( partition )
@@ -100,21 +97,22 @@ writeIface this_mod old_iface new_iface
                }}
     in
 
-    case checkIface old_iface full_new_iface of {
-       Nothing -> when opt_D_dump_rn_trace $
-                       putStrLn "Interface file unchanged" ;  -- No need to update .hi file
+    do maybe_final_iface <- checkIface old_iface full_new_iface        
+       case maybe_final_iface of {
+         Nothing -> when opt_D_dump_rn_trace $
+                    putStrLn "Interface file unchanged" ;  -- No need to update .hi file
 
-       Just final_iface ->
+         Just final_iface ->
 
-    do  let mod_vers_unchanged = case old_iface of
-                                  Just iface -> pi_vers iface == pi_vers final_iface
-                                  Nothing -> False
-       when (mod_vers_unchanged && opt_D_dump_rn_trace) $
-            putStrLn "Module version unchanged, but usages differ; hence need new hi file"
+       do  let mod_vers_unchanged = case old_iface of
+                                     Just iface -> pi_vers iface == pi_vers final_iface
+                                     Nothing -> False
+          when (mod_vers_unchanged && opt_D_dump_rn_trace) $
+               putStrLn "Module version unchanged, but usages differ; hence need new hi file"
 
-       if_hdl <- openFile filename WriteMode
-       printForIface if_hdl (pprIface final_iface)
-       hClose if_hdl
+          if_hdl <- openFile filename WriteMode
+          printForIface if_hdl (pprIface final_iface)
+          hClose if_hdl
     }   
   where
     full_new_iface = completeIface new_iface local_tycons local_classes
@@ -132,9 +130,10 @@ writeIface this_mod old_iface new_iface
 \begin{code}
 checkIface :: Maybe ParsedIface                -- The old interface, read from M.hi
           -> ParsedIface               -- The new interface; but with all version numbers = 1
-          -> Maybe ParsedIface         -- Nothing => no change; no need to write new Iface
+          -> IO (Maybe ParsedIface)    -- Nothing => no change; no need to write new Iface
                                        -- Just pi => Here is the new interface to write
                                        --            with correct version numbers
+               -- The I/O part is just so it can print differences
 
 -- NB: the fixities, declarations, rules are all assumed
 -- to be sorted by increasing order of hsDeclName, so that 
@@ -142,29 +141,22 @@ checkIface :: Maybe ParsedIface           -- The old interface, read from M.hi
 
 checkIface Nothing new_iface
 -- No old interface, so definitely write a new one!
-  = Just new_iface
+  = return (Just new_iface)
 
 checkIface (Just iface) new_iface
   | no_output_change && no_usage_change
-  = Nothing
+  = return Nothing
 
   | otherwise          -- Add updated version numbers
-  = 
-{-  pprTrace "checkIface" (
-       vcat [ppr no_decl_changed <+> ppr no_export_change <+> ppr no_usage_change,
-             text "--------",
-             vcat (map ppr (pi_decls iface)),
-             text "--------",
-             vcat (map ppr (pi_decls new_iface))
-       ]) $
--}
-    Just (new_iface { pi_vers = new_mod_vers,
-                     pi_fixity = (new_fixity_vers, new_fixities),
-                     pi_rules  = (new_rules_vers,  new_rules),
-                     pi_decls  = final_decls
-    })
+  = do { dumpIfSet opt_D_dump_hi_diffs "Interface file changes" pp_diffs ;
+        return (Just final_iface )}
        
   where
+    final_iface = new_iface { pi_vers = new_mod_vers,
+                             pi_fixity = (new_fixity_vers, new_fixities),
+                             pi_rules  = (new_rules_vers,  new_rules),
+                             pi_decls  = final_decls }
+
     no_usage_change = pi_usages iface == pi_usages new_iface
 
     no_output_change = no_decl_changed && 
@@ -189,24 +181,29 @@ checkIface (Just iface) new_iface
     new_rules_vers  | rules == new_rules = rules_vers
                    | otherwise          = bumpVersion rules_vers
 
-    (no_decl_changed, final_decls) = merge_decls True [] (pi_decls iface) (pi_decls new_iface)
+    (no_decl_changed, pp_diffs, final_decls) = merge_decls True empty [] (pi_decls iface) (pi_decls new_iface)
 
        -- Fill in the version number on the new declarations
        -- by looking at the old declarations.
        -- Set the flag if anything changes. 
        -- Assumes that the decls are sorted by hsDeclName
-    merge_decls ok_so_far acc []  []        = (ok_so_far, reverse acc)
-    merge_decls ok_so_far acc old []        = (False, reverse acc)
-    merge_decls ok_so_far acc [] (nvd:nvds) = merge_decls False (nvd:acc) [] nvds
-    merge_decls ok_so_far acc (vd@(v,d):vds) (nvd@(_,nd):nvds)
+    merge_decls ok_so_far pp acc []  []        = (ok_so_far, pp, reverse acc)
+    merge_decls ok_so_far pp acc old []        = (False,     pp, reverse acc)
+    merge_decls ok_so_far pp acc [] (nvd:nvds) = merge_decls False (pp $$ only_new nvd) (nvd:acc) [] nvds
+    merge_decls ok_so_far pp acc (vd@(v,d):vds) (nvd@(_,nd):nvds)
        = case d_name `compare` nd_name of
-               LT -> merge_decls False acc       vds      (nvd:nvds)
-               GT -> merge_decls False (nvd:acc) (vd:vds) nvds
-               EQ | d == nd   -> merge_decls ok_so_far (vd:acc) vds nvds
-                  | otherwise -> merge_decls False     ((bumpVersion v, nd):acc) vds nvds
+               LT -> merge_decls False (pp $$ only_old vd)  acc       vds      (nvd:nvds)
+               GT -> merge_decls False (pp $$ only_new nvd) (nvd:acc) (vd:vds) nvds
+               EQ | d == nd   -> merge_decls ok_so_far pp                   (vd:acc)                  vds nvds
+                  | otherwise -> merge_decls False     (pp $$ changed d nd) ((bumpVersion v, nd):acc) vds nvds
        where
          d_name  = hsDeclName d
          nd_name = hsDeclName nd
+
+    only_old (_,d) = ptext SLIT("Only in old iface:") <+> ppr d
+    only_new (_,d) = ptext SLIT("Only in new iface:") <+> ppr d
+    changed d nd   = ptext SLIT("Changed in iface: ") <+> ((ptext SLIT("Old:") <+> ppr d) $$ 
+                                                          (ptext SLIT("New:") <+> ppr nd))
 \end{code}
 
 
@@ -393,8 +390,7 @@ ifaceInstances inst_infos
                --      instance Foo Tibble where ...
                -- and this instance decl wouldn't get imported into a module
                -- that mentioned T but not Tibble.
-           forall_ty     = mkSigmaTy tvs (classesToPreds theta)
-                                     (deNoteType (mkDictTy clas tys))
+           forall_ty     = mkSigmaTy tvs theta (deNoteType (mkDictTy clas tys))
            tidy_ty = tidyTopType forall_ty
        in                       
        InstDecl (toHsType tidy_ty) EmptyMonoBinds [] (Just (toRdrName dfun_id)) noSrcLoc 
@@ -412,7 +408,7 @@ ifaceTyCon tycon
 
 ifaceTyCon tycon
   | isAlgTyCon tycon
-  = TyClD (TyData new_or_data (toHsContext (tyConTheta tycon))
+  = TyClD (mkTyData new_or_data (toHsContext (tyConTheta tycon))
                  (toRdrName tycon)
                  (toHsTyVars tyvars)
                  (map ifaceConDecl (tyConDataCons tycon))
@@ -457,24 +453,28 @@ ifaceClass clas
                     (toHsFDs clas_fds)
                     (map toClassOpSig op_stuff)
                     EmptyMonoBinds NoClassPragmas
-                    bogus bogus bogus [] noSrcLoc
+                    [] noSrcLoc
     )
   where
      bogus = error "ifaceClass"
      (clas_tyvars, clas_fds, sc_theta, _, op_stuff) = classExtraBigSig clas
 
-     toClassOpSig (sel_id, dm_id, explicit_dm)
-       = ASSERT( sel_tyvars == clas_tyvars)
-         ClassOpSig (toRdrName sel_id) (Just (bogus, explicit_dm)) (toHsType op_ty) noSrcLoc
+     toClassOpSig (sel_id, def_meth) = 
+       ASSERT(sel_tyvars == clas_tyvars)
+         ClassOpSig (toRdrName sel_id) (Just def_meth') (toHsType op_ty) noSrcLoc
        where
          (sel_tyvars, _, op_ty) = splitSigmaTy (idType sel_id)
+         def_meth' = case def_meth of
+                        NoDefMeth  -> NoDefMeth
+                        GenDefMeth -> GenDefMeth
+                        DefMeth id -> DefMeth (toRdrName id)
 \end{code}
 
 
 %************************************************************************
 %*                                                                     *
 \subsection{Value bindings}
-%*                                                                     *
+%*                                                                     * 
 %************************************************************************
 
 \begin{code}
@@ -668,14 +668,6 @@ ifaceId get_idinfo is_rec id rhs
 
     find_fvs expr = exprSomeFreeVars interestingId expr
 
-    ------------ Sanity checking --------------
-       -- The arity of a wrapper function should match its strictness,
-       -- or else an importing module will get very confused indeed.
-    arity_matches_strictness 
-       = case work_info of
-            HasWorker _ wrap_arity -> wrap_arity == arityLowerBound arity_info
-            other                  -> True
-    
 interestingId id = isId id && isLocallyDefined id && not (hasNoBinding id)
 \end{code}