KiCS-0.8.9: src/lib/Curry/Module/FlatCurryRead.curry
------------------------------------------------------------------------------
--- This library defines operations to read a FlatCurry programs or interfaces
--- together with all its imported modules in the current load path.
---
--- @author Michael Hanus
--- @version August 2005
------------------------------------------------------------------------------
module FlatCurryRead(readFlatCurryWithImports,readFlatCurryWithImportsInPath,
readFlatCurryIntWithImports,readFlatCurryIntWithImportsInPath)
where
import FlatCurry
import Directory
import FileGoodies
import System
import Distribution
import List(intersperse)
import Time(clockTimeToInt)
--------------------------------------------------------------------------
--- Reads a FlatCurry program together with all its imported modules.
--- The argument is the name of the main module (possibly with a directory prefix).
readFlatCurryWithImports :: String -> IO [Prog]
readFlatCurryWithImports modname = do
loadpath <- getLoadPathForFile (flatCurryFileName modname)
readFlatCurryFileWithImports loadpath (baseName modname) [".fcy"]
--- Reads a FlatCurry program together with all its imported modules in a given
--- load path.
--- The arguments are a load path and the name of the main module.
readFlatCurryWithImportsInPath :: [String] -> String -> IO [Prog]
readFlatCurryWithImportsInPath loadpath modname =
readFlatCurryFileWithImports loadpath modname [".fcy"]
--- Reads a FlatCurry interface together with all its imported module interfaces.
--- The argument is the name of the main module (possibly with a directory prefix).
--- If there is no interface file but a FlatCurry file (suffix ".fcy"),
--- the FlatCurry file is read instead of the interface.
readFlatCurryIntWithImports :: String -> IO [Prog]
readFlatCurryIntWithImports modname = do
loadpath <- getLoadPathForFile (flatCurryIntName modname)
readFlatCurryFileWithImports loadpath (baseName modname) [".fint",".fcy"]
--- Reads a FlatCurry interface together with all its imported module interfaces
--- in a given load path.
--- The arguments are a load path and the name of the main module.
--- If there is no interface file but a FlatCurry file (suffix ".fcy"),
--- the FlatCurry file is read instead of the interface.
readFlatCurryIntWithImportsInPath :: [String] -> String -> IO [Prog]
readFlatCurryIntWithImportsInPath loadpath modname =
readFlatCurryFileWithImports loadpath modname [".fint",".fcy"]
-- Read a FlatCurry file together with its imported modules.
-- The argument is the loadpath, the name of the main module, and the
-- possible suffixes of the FlatCurry file (e.g., [".fint",".fcy"]).
readFlatCurryFileWithImports :: [String] -> String -> [String] -> IO [Prog]
readFlatCurryFileWithImports loadpath mod suffixes = do
putStr "Reading FlatCurry files "
-- try to read the interface files directly:
mbaimps <- tryReadFlatCurryFileWithImports loadpath mod suffixes
maybe (parseFlatCurryFileWithImports loadpath mod suffixes) return mbaimps
parseFlatCurryFileWithImports loadpath modname suffixes = do
putStrLn $ ">>>>> FlatCurry files not up-to-date, parsing module \""++modname++"\"..."
callFrontendWithParams FCY
(setQuiet True (setFullPath loadpath defaultParams)) modname
putStr "Reading FlatCurry files "
collectMods [modname] []
where
collectMods [] _ = putStrLn "done" >> return []
collectMods (mod:mods) implist =
if mod `elem` implist
then collectMods mods implist
else lookupFileInPath mod suffixes loadpath >>= \mbfname ->
maybe (error $ "FlatCurry file for module \""++mod++"\" not found!")
(\filename ->
putStr (filename++" ") >>
readFlatCurryFile filename >>= \prog ->
collectMods (mods++importsOf prog) (mod:implist) >>= \results ->
return (prog : results))
mbfname
-- Read and process the imported interfaces of a module.
-- First argument is a processing action and second argument
-- is a module to be processed.
-- Nothing is returned if some interface files do not exists or are not
-- up-to-date
tryReadFlatCurryFileWithImports :: [String] -> String -> [String] -> IO (Maybe [Prog])
tryReadFlatCurryFileWithImports loadpath modname suffixes =
collectMods [modname] []
where
collectMods [] _ = putStrLn "done" >> return (Just [])
collectMods (mod:mods) implist =
if mod `elem` implist
then collectMods mods implist
else
readFlatCurryIfPossible loadpath mod suffixes >>= \mbprog ->
maybe (return Nothing)
(\prog->collectMods (mods++importsOf prog) (mod:implist) >>=
\mbresults -> return (maybe Nothing
(\results->Just (prog : results))
mbresults))
mbprog
importsOf :: Prog -> [String]
importsOf (Prog _ imps _ _ _) = imps
-- Read a FlatCurry file for a module if it exists and is up-to-date
-- w.r.t. the source program. If no source exists, it is always assumed
-- to be up-to-date.
readFlatCurryIfPossible :: [String] -> String -> [String] -> IO (Maybe Prog)
readFlatCurryIfPossible loadpath modname suffixes = do
mbfname <- lookupFileInPath modname [".lcurry",".curry"] loadpath
maybe (lookupFileInPath modname suffixes loadpath >>= \fname ->
maybe (return Nothing)
(\progname -> readFlatCurryFile progname >>= return . Just)
fname)
(\sname -> do
let moddir = dirName sname
pathofmod = [moddir,addCurrySubdir moddir]
mbflatfile <- lookupFileInPath modname suffixes pathofmod
maybe (return Nothing)
(\flatfile -> do
ctime <- getModificationTime sname
ftime <- getModificationTime flatfile
if clockTimeToInt ctime > clockTimeToInt ftime
then return Nothing
else putStr (flatfile++" ") >>
readFlatCurryFile flatfile >>= return . Just )
mbflatfile)
mbfname
--------------------------------------------------------------------------