{- ---------------------------------------------------------------------------
-- Read and process the interface file of one imported module.
-}
module Import (Flags,ImportState,PackedString,TokenId,IdKind,HideDeclIds
,readFirst,importOne) where
import IO
import SysDeps(PackedString,unpackPS)
import Flags
import Util.Extra
import Util.OsOnly (isPrelude,fixImportNames)
import TokenId(TokenId(..),extractV)
import Parse.ParseCore(parseit)
import Parse.ParseI
import Parse.Lexical(PosToken,lexical)
import Error
import IExtract
import ImportState(ImportState,putModid2IS)
import IdKind(IdKind)
import PreImp(HideDeclIds)
import qualified Data.Map as Map
import qualified Data.Set as Set
import Maybe -- (fromJust)
import Building(Compiler(..),compiler)
{-
Open an interface file for given module name.
Returns unpacked module name, filename of interface file and its content.
-}
openImport :: Flags -> PackedString -> Map.Map String FilePath -> IO (String,String,String)
openImport flags mrps hiDeps
| compiler==Yhc =
do let fstr = hiFile
finput <- tryReadFile "import" fstr
if sImport flags
then hPutStr stderr ("Importing module " ++ mstr ++ " from " ++ fstr ++ ".\n")
else return ()
return (mstr, fstr, finput)
| compiler==Nhc98 =
catch (do
(fstr,finput) <- readFirst filenames
if sImport flags
then hPutStr stderr
("Importing module " ++ mstr ++ " from " ++ fstr ++ ".\n")
else return ()
return (mstr,fstr,finput))
(\ err -> ioError (userError (can'tOpenStr mstr filenames err)))
where
isUnix = sUnix flags
preludes = sPreludes flags
includes = sIncludes flags ++ preludes
mstr = (reverse . unpackPS) mrps
hiFile = fromJust (Map.lookup mstr hiDeps)
filenames = fixImportNames isUnix (sHiSuffix flags) mstr
(if isPrelude mstr then preludes else includes)
{-
Read and process the interface file of one imported module.
-}
importOne :: Flags
-> ImportState
-> Map.Map String FilePath
-> ( PackedString
, (PackedString, PackedString, Set.Set TokenId)
-> [[TokenId]] -> Bool
, HideDeclIds)
-> IO ImportState
importOne flags importState hiDeps (mrps,needFun,hideFun) = do
(mstr,fstr,finput) <- openImport flags mrps hiDeps
let lexdata = lexical (sUnderscore flags) fstr finput
pF (sILex flags) "Lexical Interface"
(mixSpace (map (\ (p,l,_,_) -> strPos p ++ ':':show l) lexdata))
case parseit parseInterface1 lexdata of
Left err -> parseIError fstr err
Right (modid,imports,fixity,rest) -> do
if not (sLib flags || sPart flags) && show modid /= mstr
then hPutStr stderr ("Warning: The module " ++ mstr ++ " is called "
++ show modid
++ " in its interface file (" ++ fstr ++")\n")
else return ()
case parseit (parseInterface2
(needFixity fixity
(putModidIS importState (extractV modid)))
hideFun)
rest of
Left err -> parseIError fstr err
Right (importState,need,rest) ->
importCont' importState needFun hideFun mstr fstr need rest
-- needFun
-- down ((Memo TokenId -> [[TokenId]] -> Bool)
importCont' :: ImportState
-> ((PackedString, PackedString, Set.Set TokenId)
-> [[TokenId]] -> Bool)
-> HideDeclIds
-> a -- module name
-> [Char] -- filename
-> Maybe [[TokenId]] -- need
-> [PosToken] -- lexical input
-> IO ImportState
importCont' importState needFun hideFun modid filename need rest =
importCont (Right (ParseNeed importState need rest))
where
importCont (Left err) = parseIError filename err
importCont (Right (ParseEof importState)) =
return importState :: (IO ImportState)
importCont (Right (ParseNext importState visible (pos,Visible mrps) rest)) =
importCont (parseit (parseUntilNeed
(putModid2IS importState visible mrps)) rest)
importCont (Right (ParseNeed importState (Just needs@(_:_)) rest)) =
if needFun (getNeedIS importState) needs
then importCont (parseit (parseInterface3 importState needs hideFun) rest)
else importCont (parseit (parseUntilNeed importState) rest)
importCont (Right (ParseNeed importState (Just []) rest)) =
importCont (parseit (parseInterface3 importState [] hideFun) rest)
importCont (Right (ParseNeed importState _ rest)) =
importCont2 (parseit (parseInterface4 importState hideFun) rest)
importCont2 (Left err) = parseIError filename err
importCont2 (Right (ParseEof importState)) = return importState
importCont2 (Right (ParseNext importState visible (pos,Visible mrps) rest)) =
importCont (parseit (parseUntilNeed
(putModid2IS importState visible mrps)) rest)
{-
Output an error message that is caused by parsing an interface file.
-}
parseIError :: [Char] -> (Pos,String,[String]) -> IO a
parseIError filename err =
(ioError . userError . showErr filename) err
|