packages feed

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

--------------------------------------------------------------------------