module Main where import Control.Monad import Control.Monad.Except import Data.Either import System.Environment import System.Exit import qualified Data.ByteString as BS import qualified LLVM.General as General import qualified LLVM.General.Context as General import qualified LLVM.General.Target as General import Check import Codegen import Parser import PShow fromLeft :: Either a b -> a fromLeft (Left a) = a fromLeft (Right _) = error "Either is not a Left" fromRight :: Either a b -> b fromRight (Right b) = b fromRight (Left _) = error "Either is not a Right" dieShow :: (Show a) => a -> IO () dieShow = die . show assert :: ExceptT String IO a -> IO a assert ex = do e <- runExceptT ex either die return e >> (return $ (\(Right r) -> r) e) main :: IO () main = do args <- getArgs when (length args /= 1) $ die "Pass NL file name as a command-line parameter" let fname = args !! 0 parseResult <- (\file -> parseProgram file fname) <$> readFile fname when (isLeft parseResult) $ dieShow $ fromLeft parseResult let ast = fromRight parseResult putStrLn $ pshow ast checked <- either die return $ checkProgram ast putStrLn "After checking:" putStrLn $ pshow checked llvmMod <- either die return $ codegen checked "Module" fname putStrLn "Module:" print llvmMod putStrLn "Calling withContext:" General.withContext $ \context -> do putStrLn "Calling withModuleFromAST:" assert $ General.withModuleFromAST context llvmMod $ \genmod -> do putStrLn "Calling moduleLLVMAssembly:" llvmasm <- General.moduleLLVMAssembly genmod putStr llvmasm putStrLn "" assert $ General.withHostTargetMachine $ \machine -> do General.getTargetMachineTriple machine >>= putStrLn putStrLn "" assert (General.moduleTargetAssembly machine genmod) >>= putStr bs <- assert $ General.moduleObject machine genmod BS.writeFile "output_gen.o" bs