module Main where import System (getArgs) import System.Console.GetOpt import System.FilePath (FilePath, dropExtension, addExtension, takeBaseName) import System.Cmd (rawSystem) import Control.Monad.Trans (liftIO) import Data.Maybe (fromMaybe, isJust) import Parser (parseStr) import LPTypechecker import qualified Compiler as C import Preprocessor import LLVMUtils (writeBitcodeToFile) import Debug.Trace (trace) data Options = Options { libDir :: Maybe FilePath, outputFile :: Maybe FilePath, prelude :: Maybe FilePath, fastArithmetic :: Bool } defaultOptions = Options { libDir = Nothing, outputFile = Nothing, prelude = Nothing, fastArithmetic = False } options = [ Option ['L'] ["libdir"] (ReqArg (\d opts -> opts { libDir = Just d }) "DIR") "Library directory, containing external primitive functions", Option ['o'] ["output"] (ReqArg (\f opts -> opts {outputFile = Just f}) "OUTPUT") "Path to output file", Option [] ["fast-math"] (NoArg (\opts -> opts { fastArithmetic = True })) "Use built-in operators for arithmetic functions", Option ['p'] ["prelude"] (ReqArg (\p opts -> opts {prelude = Just p}) "PRELUDE") "Include a particular prelude file (default is none)" ] main = do args <- getArgs case getOpt Permute options args of (_, f:f':[], []) -> error "multiple source files specified" (opts, [file], []) -> processFile (foldl (flip id) defaultOptions opts) file (_, _, errors) -> error $ unlines errors processFile opts f = do preludeStr <- case prelude opts of Nothing -> return "" Just p -> readFile p fileStr <- readFile f let str = preludeStr ++ fileStr case buildAST f str of Left err -> error err Right prog -> compile opts f prog where buildAST f str = do parseTree <- parseStr f str annotated <- typecheck parseTree return $ createClosures $ preprocess (fastArithmetic opts) annotated -- Take a .lambda file and produce a native executable of the same name. Also -- creates an intermediate .bc file, and links against main.bc for the entry -- point. compile opts fileName prog = do (code, entryPoint) <- C.compile (dropExtension fileName) prog let bitcodeFile = addExtension (dropExtension fileName) ".bc" writeBitcodeToFile bitcodeFile code let executable = fromMaybe (takeBaseName fileName) (outputFile opts) let lib = fromMaybe "./lib" (libDir opts) rawSystem "llvm-ld" [bitcodeFile, lib++"/main.bc", lib++"/fold.o", "-disable-opt", "-native", "-o", executable]