[project @ 2005-03-22 17:13:12 by simonmar]
[ghc-hetmet.git] / ghc / compiler / iface / LoadIface.lhs
index 142d86f..ab11421 100644 (file)
@@ -5,12 +5,11 @@
 
 \begin{code}
 module LoadIface (
-       loadHomeInterface, loadInterface,
+       loadHomeInterface, loadInterface, loadDecls,
        loadSrcInterface, loadOrphanModules, loadHiBootInterface,
        readIface,      -- Used when reading the module's old interface
        predInstGates, ifaceInstGates, ifaceStats, discardDeclPrags,
-       initExternalPackageState,
-       noIfaceErr,   -- used by CompManager too
+       initExternalPackageState
    ) where
 
 #include "HsVersions.h"
@@ -18,25 +17,20 @@ module LoadIface (
 import {-# SOURCE #-}  TcIface( tcIfaceDecl )
 
 import Packages                ( PackageState(..), PackageIdH(..), isHomePackage )
-import DriverState     ( v_GhcMode, isCompManagerMode )
-import DriverUtil      ( replaceFilenameSuffix )
-import CmdLineOpts     ( DynFlags(..), DynFlag( Opt_IgnoreInterfacePragmas ) )
-import Parser          ( parseIface )
-
+import DynFlags                ( DynFlags(..), DynFlag( Opt_IgnoreInterfacePragmas ),
+                         isOneShot )
 import IfaceSyn                ( IfaceDecl(..), IfaceConDecl(..), IfaceClassOp(..),
                          IfaceConDecls(..), IfaceInst(..), IfaceRule(..),
                          IfaceExpr(..), IfaceTyCon(..), IfaceIdInfo(..), 
                          IfaceType(..), IfacePredType(..), IfaceExtName,
                          mkIfaceExtName )
-import IfaceEnv                ( newGlobalBinder, lookupIfaceExt, lookupIfaceTc,
-                         lookupOrig )
+import IfaceEnv                ( newGlobalBinder, lookupIfaceExt, lookupIfaceTc, lookupAvail )
 import HscTypes                ( ModIface(..), TyThing, emptyModIface, EpsStats(..),
                          addEpsInStats, ExternalPackageState(..),
-                         PackageTypeEnv, emptyTypeEnv,  
+                         PackageTypeEnv, emptyTypeEnv,  HscEnv(..),
                          lookupIfaceByModule, emptyPackageIfaceTable,
                          IsBootInterface, mkIfaceFixCache, Gated,
-                         implicitTyThings, addRulesToPool, addInstsToPool,
-                         availNames
+                         implicitTyThings, addRulesToPool, addInstsToPool
                         )
 
 import BasicTypes      ( Version, Fixity(..), FixityDirection(..),
@@ -55,28 +49,24 @@ import Name         ( Name {-instance NamedThing-}, getOccName,
 import NameEnv
 import MkId            ( seqId )
 import Module          ( Module, ModLocation(ml_hi_file), emptyModuleEnv, 
+                         addBootSuffix_maybe,
                          extendModuleEnv, lookupModuleEnv, moduleUserString
                        )
 import OccName         ( OccName, mkOccEnv, lookupOccEnv, mkClassTyConOcc, mkClassDataConOcc,
                          mkSuperDictSelOcc, mkDataConWrapperOcc, mkDataConWorkerOcc )
 import Class           ( Class, className )
 import TyCon           ( tyConName )
-import SrcLoc          ( mkSrcLoc, importedSrcLoc )
+import SrcLoc          ( importedSrcLoc )
 import Maybes          ( mapCatMaybes, MaybeErr(..) )
-import StringBuffer     ( hGetStringBuffer )
 import FastString      ( mkFastString )
-import ErrUtils         ( Message, mkLocMessage )
-import Finder          ( findModule, findPackageModule,  FindResult(..),
-                         hiBootFilePath )
-import Lexer
+import ErrUtils         ( Message )
+import Finder          ( findModule, findPackageModule,  FindResult(..), cantFindError )
 import Outputable
 import BinIface                ( readBinIface )
 import Panic           ( ghcError, tryMost, showException, GhcException(..) )
 import List            ( nub )
 
 import DATA_IOREF      ( readIORef )
-
-import Directory
 \end{code}
 
 
@@ -128,9 +118,10 @@ loadHiBootInterface
 
     do {       -- Load it (into the PTE), and return the exported names
          iface <- loadSrcInterface (mk_doc mod_nm) mod_nm True
-       ; sequenceM [ lookupOrig mod_nm occ
-                   | (mod,avails) <- mi_exports iface, 
-                     avail <- avails, occ <- availNames avail]
+       ; ns_s <-  sequenceM [ lookupAvail mod_nm avail
+                            | (mod,avails) <- mi_exports iface, 
+                              avail <- avails ]
+       ; return (concat ns_s)
     }}}
   where
     mk_doc mod = ptext SLIT("Need the hi-boot interface for") <+> ppr mod
@@ -270,8 +261,8 @@ loadInterface doc_str mod from
        --      explicitly tag each export which seems a bit of a bore)
 
        ; ignore_prags <- doptM Opt_IgnoreInterfacePragmas
-       ; new_eps_decls <- mapM (loadDecl ignore_prags) (mi_decls iface)
-       ; new_eps_insts <- mapM loadInst                (mi_insts iface)
+       ; new_eps_decls <- loadDecls ignore_prags (mi_decls iface)
+       ; new_eps_insts <- mapM loadInst (mi_insts iface)
        ; new_eps_rules <- if ignore_prags 
                           then return []
                           else mapM loadRule (mi_rules iface)
@@ -305,21 +296,35 @@ badDepMsg mod
 -- the declaration itself, will find the fully-glorious Name
 -----------------------------------------------------
 
-addDeclsToPTE :: PackageTypeEnv -> [[(Name,TyThing)]] -> PackageTypeEnv
-addDeclsToPTE pte things = foldl extendNameEnvList pte things
+addDeclsToPTE :: PackageTypeEnv -> [(Name,TyThing)] -> PackageTypeEnv
+addDeclsToPTE pte things = extendNameEnvList pte things
+
+loadDecls :: Bool
+         -> [(Version, IfaceDecl)]
+         -> IfL [(Name,TyThing)]
+loadDecls ignore_prags ver_decls
+   = do { mod <- getIfModule
+       ; thingss <- mapM (loadDecl ignore_prags mod) ver_decls
+       ; return (concat thingss)
+       }
 
 loadDecl :: Bool                       -- Don't load pragmas into the decl pool
+        -> Module
          -> (Version, IfaceDecl)
          -> IfL [(Name,TyThing)]       -- The list can be poked eagerly, but the
                                        -- TyThings are forkM'd thunks
-loadDecl ignore_prags (_version, decl)
+loadDecl ignore_prags mod (_version, decl)
   = do         {       -- Populate the name cache with final versions of all 
                -- the names associated with the decl
-         mod <- getIfModule
-       ; main_name      <- mk_new_bndr mod Nothing (ifName decl)
+         main_name      <- mk_new_bndr mod Nothing (ifName decl)
        ; implicit_names <- mapM (mk_new_bndr mod (Just main_name)) (ifaceDeclSubBndrs decl)
 
        -- Typecheck the thing, lazily
+       -- NB. firstly, the laziness is there in case we never need the
+       -- declaration (in one-shot mode), and secondly it is there so that 
+       -- we don't look up the occurrence of a name before calling mk_new_bndr
+       -- on the binder.  This is important because we must get the right name
+       -- which includes its nameParent.
        ; thing <- forkM doc (bumpDeclStats main_name >> tcIfaceDecl stripped_decl)
        ; let mini_env = mkOccEnv [(getOccName t, t) | t <- implicitTyThings thing]
              lookup n = case lookupOccEnv mini_env (getOccName n) of
@@ -511,11 +516,11 @@ ifaceInstGates :: IfaceType -> (IfaceExtName, [IfaceTyCon])
 
 ifaceInstGates (IfaceForAllTy _ t)                = ifaceInstGates t
 ifaceInstGates (IfaceFunTy _ t)                   = ifaceInstGates t
-ifaceInstGates (IfacePredTy (IfaceClassP cls tys)) = instHeadGates cls tys
+ifaceInstGates (IfacePredTy (IfaceClassP cls tys)) = (cls, instHeadTyconGates tys)
 ifaceInstGates other = pprPanic "ifaceInstGates" (ppr other)
        -- The other cases should not happen
 
-instHeadGates cls tys = (cls, mapCatMaybes root_tycon tys)
+instHeadTyconGates tys = mapCatMaybes root_tycon tys
   where
     root_tycon (IfaceFunTy _ _)      = Just (IfaceTc funTyConExtName)
     root_tycon (IfaceTyConApp tc _)  = Just tc
@@ -571,12 +576,13 @@ findAndReadIface explicit doc_str mod_name hi_boot_file
          else do
 
        -- Look for the file
-       ; mb_found <- ioToIOEnv (findHiFile dflags explicit mod_name hi_boot_file)
+       ; hsc_env <- getTopEnv
+       ; mb_found <- ioToIOEnv (findHiFile hsc_env explicit mod_name hi_boot_file)
        ; case mb_found of {
              Failed err -> do
                { traceIf (ptext SLIT("...not found"))
                ; dflags <- getDOpts
-               ; returnM (Failed (noIfaceErr dflags mod_name err)) } ;
+               ; returnM (Failed (cantFindError dflags mod_name err)) } ;
 
              Succeeded (file_path, pkg) -> do 
 
@@ -593,28 +599,26 @@ findAndReadIface explicit doc_str mod_name hi_boot_file
                        -- Don't forget to fill in the package name...
        }}}
 
-findHiFile :: DynFlags -> Bool -> Module -> IsBootInterface
+findHiFile :: HscEnv -> Bool -> Module -> IsBootInterface
           -> IO (MaybeErr FindResult (FilePath, PackageIdH))
-findHiFile dflags explicit mod_name hi_boot_file
+findHiFile hsc_env explicit mod_name hi_boot_file
  = do { 
        -- In interactive or --make mode, we are *not allowed* to demand-load
        -- a home package .hi file.  So don't even look for them.
        -- This helps in the case where you are sitting in eg. ghc/lib/std
        -- and start up GHCi - it won't complain that all the modules it tries
        -- to load are found in the home location.
-       ghci_mode <- readIORef v_GhcMode ;
-       let { home_allowed = hi_boot_file || 
-                            not (isCompManagerMode ghci_mode) } ;
+       let { home_allowed = isOneShot (ghcMode (hsc_dflags hsc_env)) } ;
        maybe_found <-  if home_allowed 
-                       then findModule dflags mod_name explicit
-                       else findPackageModule dflags mod_name explicit;
+                       then findModule        hsc_env mod_name explicit
+                       else findPackageModule hsc_env mod_name explicit;
 
        case maybe_found of
-         Found loc pkg 
-               | hi_boot_file -> do { hi_boot_path <- hiBootFilePath loc
-                                    ; return (Succeeded (hi_boot_path, pkg)) }
-               | otherwise    -> return (Succeeded (ml_hi_file loc, pkg)) ;
-         err                  -> return (Failed err)
+         Found loc pkg -> return (Succeeded (path, pkg))
+                       where
+                          path = addBootSuffix_maybe hi_boot_file (ml_hi_file loc)
+
+         err -> return (Failed err)
        }
 \end{code}
 
@@ -626,33 +630,20 @@ readIface :: Module -> String -> IsBootInterface
        -- Failed err    <=> file not found, or unreadable, or illegible
        -- Succeeded iface <=> successfully found and parsed 
 
-readIface wanted_mod_name file_path is_hi_boot_file
+readIface wanted_mod file_path is_hi_boot_file
   = do { dflags <- getDOpts
-       ; ioToIOEnv (read_iface dflags wanted_mod_name file_path is_hi_boot_file) }
-
-read_iface dflags wanted_mod file_path is_hi_boot_file
- | is_hi_boot_file             -- Read ascii
- = do { res <- tryMost (hGetStringBuffer file_path) ;
-       case res of {
-         Left exn     -> return (Failed (text (showException exn))) ;
-         Right buffer -> 
-        case unP parseIface (mkPState buffer loc dflags) of
-         PFailed span err -> return (Failed (mkLocMessage span err))
-         POk _ iface 
-            | wanted_mod == actual_mod -> return (Succeeded iface)
-            | otherwise                -> return (Failed err) 
-            where
-               actual_mod = mi_module iface
-               err = hiModuleNameMismatchWarn wanted_mod actual_mod
-     }}
-
- | otherwise           -- Read binary
- = do  { res <- tryMost (readBinIface file_path)
+       ; ioToIOEnv $ do
+       { res <- tryMost (readBinIface file_path)
        ; case res of
-           Right iface -> return (Succeeded iface)
-           Left exn    -> return (Failed (text (showException exn))) }
- where
-    loc  = mkSrcLoc (mkFastString file_path) 1 0
+           Right iface 
+               | wanted_mod == actual_mod -> return (Succeeded iface)
+               | otherwise                -> return (Failed err)
+               where
+                 actual_mod = mi_module iface
+                 err = hiModuleNameMismatchWarn wanted_mod actual_mod
+
+           Left exn    -> return (Failed (text (showException exn)))
+    }}
 \end{code}
 
 
@@ -748,27 +739,6 @@ hiModuleNameMismatchWarn requested_mod read_mod =
         , ppr read_mod
         ]
 
-noIfaceErr :: DynFlags -> Module -> FindResult -> SDoc
-noIfaceErr dflags mod_name (PackageHidden pkg)
-  = ptext SLIT("Could not import") <+> quotes (ppr mod_name) <> colon
-    $$ ptext SLIT("it is a member of package") <+> ppr pkg <> comma
-        <+> ptext SLIT("which is hidden")
-
-noIfaceErr dflags mod_name (ModuleHidden pkg)
-  = ptext SLIT("Could not import") <+> quotes (ppr mod_name) <> colon
-    $$ ptext SLIT("it is hidden") 
-       <+> parens (ptext SLIT("in package") <+> ppr pkg)
-
-noIfaceErr dflags mod_name (NotFound files)
-  = ptext SLIT("Could not find interface file for") <+> quotes (ppr mod_name)
-    $$ extra files
-  where 
-  extra files
-    | verbosity dflags < 3 = 
-        text "(use -v to see a list of the files searched for)"
-    | otherwise =
-        hang (ptext SLIT("locations searched:")) 4 (vcat (map text files))
-
 wrongIfaceModErr iface mod_name file_path 
   = sep [ptext SLIT("Interface file") <+> iface_file,
          ptext SLIT("contains module") <+> quotes (ppr (mi_module iface)) <> comma,