{- |
Module : Main.hs
Description : .
Maintainer : (c) Christopher Pockrandt, Nicolas Lehmann, Tobias Kranz
License : MIT
Stability : stable
Entrypoint of the rail2llvm-compiler. Contains main-function.
See also:
--https://www.haskell.org/ghc/docs/7.8.2/html/libraries/base-4.7.0.0/System-Console-GetOpt.html
--http://leiffrenzel.de/papers/commandline-options-in-haskell.html (Outdated!)
-}
module Main( main ) where
-- imports --
import System.Environment
import System.Exit
import System.Console.GetOpt
import Data.Maybe( fromMaybe )
import InterfaceDT as IDT
import qualified Preprocessor as PreProc
import qualified Lexer
import qualified SyntacticalAnalysis as SynAna
import qualified SemanticalAnalysis as SemAna
import qualified IntermediateCode as InterCode
import qualified CodeOptimization as CodeOpt
import qualified Backend
-- defining the option settings for the main-function
data Options = Options {
optInput :: IO String,
optOutput :: String -> IO (),
optASTOutput :: String -> IO (),
compile :: Bool,
impAST :: Bool,
expAST :: Bool
}
-- default Options
defaultOptions :: Options
defaultOptions = Options {
optInput = getContents,
optOutput = putStr,
optASTOutput = putStr,
compile = False,
impAST = False,
expAST = False
}
-- usageInfo
options :: [OptDescr (Options -> IO Options)]
options = [
--Option ['V'] ["version"] (NoArg showVersion) "show version number",
Option "h" ["help" ] (NoArg showHelp ) "display Help Text",
Option "i" ["input" ] (ReqArg setInput "FILE" ) "input file (don't set to use stdin')",
Option "o" ["output" ] (ReqArg setOutput "FILE" ) "output file (don't set to use stdout')",
Option "c" ["compile" ] (NoArg setCompile ) "compile 'rail' to 'llvm'",
Option [ ] ["exportAST"] (OptArg setExpAST "FILE" ) "export frontend AST (don't offer a File to use stdout) \n(dont set with --importAST)",
Option [ ] ["importAST"] (NoArg setImpAST ) "import frontend AST and compile to llvm\nautosets -c \n(set input via -i; (dont set with --exportAST)\n\nset -c with --exportAST and get both: the AST and the llvm code"
]
-- output for the help-function
showHelp _ = do
putStrLn "rail2llvm--haskell-compiler (development version)"
putStr "https://github.com/SWP-Ubau-SoSe2014-Haskell/SWPSoSe14\n\n"
putStr $ usageInfo "Usage: main [OPTION...]" options
exitSuccess
-- options-getter for optional output for exprotAST
getOut (Just arg) = writeFile arg
getOut Nothing = putStr
-- options-setters
setInput arg opt = return opt { optInput = readFile arg }
setOutput arg opt = return opt { optOutput = writeFile arg }
setExpAST arg opt = return opt { optASTOutput = getOut arg, expAST = True}
setImpAST opt = return opt { impAST = True, compile = True }
setCompile opt = return opt { compile = True }
-- main-function --
main = do args <- getArgs
let (actions,nonOpts,msgs) = getOpt RequireOrder options args
-- intercept errors
if msgs /= []
then error $ concat msgs ++ usageInfo "Usage: main [OPTION...]" options
-- unrecognized arguments error
else if nonOpts /= []
then error $ "unrecognized arguments: " ++ unwords nonOpts ++ "\nUsage: For basic information, try the `--help' option."
else do opts <- foldl (>>=) (return defaultOptions) actions
-- option aliases
let Options { optInput = input, optOutput = output, optASTOutput = outputAST, compile = cmpl, impAST = imp, expAST = exp} = opts
inputWithoutIO <- input
-- importAST and exportAST can't be set together (error)
if imp && exp
then do error "No export of the imported AST (Usage: For basic information, try the `--help' option.)'"
exitSuccess
-- compile a file
else if cmpl
then do let transform (IBO x) = x
-- compile an imported AST to a LLVM-file
if imp
then transform (Backend.process . CodeOpt.process . InterCode.process . SemAna.process . SynAna.process . Lexer.toAST $ inputWithoutIO) >>= output
-- compile a RAIL-file to an AST as an export-file
else if exp
then do outputAST (Lexer.fromAST . Lexer.process . PreProc.process $ IIP inputWithoutIO)
transform (Backend.process . CodeOpt.process . InterCode.process . SemAna.process . SynAna.process . Lexer.process . PreProc.process $ IIP inputWithoutIO) >>= output
-- compile a RAIL-file to a LLVM-file
else transform (Backend.process . CodeOpt.process . InterCode.process . SemAna.process . SynAna.process . Lexer.process . PreProc.process $ IIP inputWithoutIO) >>= output
-- exportAST (without compiling it to llvm)
else if exp
then outputAST (Lexer.fromAST . Lexer.process . PreProc.process $ IIP inputWithoutIO)
-- missing argument error
else error "Error. Set atleast -c or --importAST or --exportAST."