module Transfer.CompilerAPI where import Transfer.Syntax.Lex import Transfer.Syntax.Par import Transfer.Syntax.Print import Transfer.Syntax.Abs import Transfer.Syntax.Layout import Transfer.ErrM import Transfer.SyntaxToCore import Transfer.PathUtil import Data.List import System.Directory -- | Compile a source module file to a a code file. compileFile :: [FilePath] -- ^ directories to look for imported modules in -> FilePath -- ^ source module file -> IO FilePath -- ^ path to the core file that was written compileFile path f = do ds <- loadModule path f s <- compile ds writeFile coreFile s return coreFile where coreFile = replaceFilenameSuffix f "trc" -- | Compile a self-contained list of declarations to a core program. compile :: Monad m => [Decl] -> m String compile m = return (printTree $ declsToCore m) -- | Load a source module file and all its dependencies. loadModule :: [FilePath] -- ^ directories to look for imported modules in -> FilePath -- ^ source module file -> IO [Decl] loadModule = loadModule_ [] where loadModule_ ms path f = do s <- readFile f Module is ds <- case pModule (myLLexer s) of Bad e -> fail $ "Parse error in " ++ f ++ ": " ++ e Ok m -> return m let load = [ i | Import (Ident i) <- is ] \\ ms let path' = directoryOf f : path files <- mapM (findFile path' . (++".tra")) load dss <- mapM (loadModule_ (load++ms) path) files return $ concat (dss++[ds]) myLLexer :: String -> [Token] myLLexer = resolveLayout True . myLexer -- | Find a file in one of the given directories. -- Fails if the file was not found. findFile :: [FilePath] -- ^ directories to look in -> FilePath -- ^ file name to find -> IO FilePath findFile path f = do mf <- findFileM path f case mf of Nothing -> fail $ f ++ " not found in path: " ++ show path Just f' -> return f' -- | Find a file in one of the given directories. findFileM :: [FilePath] -- ^ directories to look in -> FilePath -- ^ file name to find -> IO (Maybe FilePath) findFileM [] _ = return Nothing findFileM (p:ps) f = do let f' = p ++ "/" ++ f e <- doesFileExist f' if e then return (Just f') else findFileM ps f