{-# LANGUAGE NamedFieldPuns #-} module Main where import qualified Compiler (main) import Context (CodePath(..), Context (..), Path(..)) import Control.Applicative (many, optional) import Control.Monad.RWS (evalRWST) import qualified Data.Map as Map (empty) import Data.Text (Text) import qualified Data.Text as Text (unpack) import Data.Version (showVersion) import qualified Module (parse) import Options.Applicative ( Parser, execParser, fullDesc, info, header, help, helper, long, metavar , option, short, str, strArgument, strOption, value ) import qualified Paths_SJW as SJW (version) import System.IO (stderr, hPutStrLn) data Config = Config { includes :: [FilePath] , mainIs :: String , outputFile :: FilePath , target :: FilePath } deriving (Show) configParser :: Parser Config configParser = Config <$> many (strOption ( long "include" <> short 'I' <> metavar "PACKAGE" <> help "Include this package during compilation" )) <*> strOption ( long "main-is" <> short 'm' <> metavar "MODULE_NAME" <> help "The name of the main module containing the code to run" <> value "Main" ) <*> strOption ( long "output" <> short 'o' <> metavar "OUTPUT_PATH" <> help "The path where to create the compiled script (stdout if \"-\" or if the option is missing)" <> value "-" ) <*> strArgument ( metavar "SOURCE_DIR" <> help "The path where to look for the sources" ) getConfig :: IO Config getConfig = execParser $ info (helper <*> configParser) (fullDesc <> header ("SJW v" ++ showVersion SJW.version)) runCompiler :: Config -> IO (Text, [String]) runCompiler (Config {includes, mainIs, target}) = flip (evalRWST Compiler.main) Map.empty $ Context { codePaths = CodePath (target : includes) , mainModule = read mainIs } main :: IO () main = do config@(Config {outputFile}) <- getConfig (sourceCode, logs) <- runCompiler config mapM_ (hPutStrLn stderr) logs output outputFile . Text.unpack $ sourceCode where output "-" = putStr output fileName = writeFile fileName