module Language.Copilot.Main ( copilotMain, defaultMain ) where import qualified Copilot.Core as C (Spec) import Copilot.Language (interpret, prettyPrint) import Copilot.Language.Reify (reify) import Copilot.Language (Spec) import Options.Applicative import Data.Semigroup ((<>)) import Control.Monad (when) type Interpreter = Integer -> Spec -> IO () type Compiler = FilePath -> C.Spec -> IO () type Printer = Spec -> IO () data CmdArgs = CmdArgs { aoutput :: String , acompile :: Bool , apretty :: Bool , ainterpret :: Int } cmdargs :: Parser CmdArgs cmdargs = CmdArgs <$> strOption (long "output" <> short 'o' <> value "." <> help "Output directory of C files") <*> switch (long "justrun" <> short 'c' <> help "Do NOT produce *.c and *.h files as output") <*> switch (long "print" <> short 'p' <> help "Pretty print the specification") <*> option auto (long "interpret" <> short 'i' <> value 0 <> metavar "INT" <> showDefault <> help "Interpret specification and write result to output") copilotMain :: Interpreter -> Printer -> Compiler -> Spec -> IO () copilotMain interp pretty comp spec = main =<< execParser opts where opts = info (cmdargs <**> helper) fullDesc main :: CmdArgs -> IO () main args = do let iters = ainterpret args when (apretty args) $ pretty spec when (iters Prelude.> 0) $ interp (fromIntegral iters) spec when (not $ acompile args) $ do spec' <- reify spec comp (aoutput args) spec' defaultMain :: Compiler -> Spec -> IO () defaultMain = copilotMain interpret prettyPrint