module Main (main) where

import Data.Default
import Options.Applicative (
    Parser,
    auto,
    execParser,
    fullDesc,
    help,
    helper,
    info,
    long,
    metavar,
    option,
    progDesc,
    short,
    showDefault,
    simpleVersioner,
    strArgument,
    strOption,
    switch,
    value,
 )
import Relude
import Wrench.Misc (wrenchVersion)
import Wrench.Wrench (Options (..), runWrenchIO)

options :: Parser Options
options :: Parser Options
options =
    FilePath
-> Maybe FilePath
-> Maybe FilePath
-> Bool
-> Bool
-> Bool
-> Int
-> Int
-> Int
-> AddrFormat
-> DumpSize
-> Options
Options
        (FilePath
 -> Maybe FilePath
 -> Maybe FilePath
 -> Bool
 -> Bool
 -> Bool
 -> Int
 -> Int
 -> Int
 -> AddrFormat
 -> DumpSize
 -> Options)
-> Parser FilePath
-> Parser
     (Maybe FilePath
      -> Maybe FilePath
      -> Bool
      -> Bool
      -> Bool
      -> Int
      -> Int
      -> Int
      -> AddrFormat
      -> DumpSize
      -> Options)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Mod ArgumentFields FilePath -> Parser FilePath
forall s. IsString s => Mod ArgumentFields s -> Parser s
strArgument
            ( FilePath -> Mod ArgumentFields FilePath
forall (f :: * -> *) a. HasMetavar f => FilePath -> Mod f a
metavar FilePath
"INPUT"
                Mod ArgumentFields FilePath
-> Mod ArgumentFields FilePath -> Mod ArgumentFields FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod ArgumentFields FilePath
forall (f :: * -> *) a. FilePath -> Mod f a
help FilePath
"Input assembler file (.s)"
            )
        Parser
  (Maybe FilePath
   -> Maybe FilePath
   -> Bool
   -> Bool
   -> Bool
   -> Int
   -> Int
   -> Int
   -> AddrFormat
   -> DumpSize
   -> Options)
-> Parser (Maybe FilePath)
-> Parser
     (Maybe FilePath
      -> Bool
      -> Bool
      -> Bool
      -> Int
      -> Int
      -> Int
      -> AddrFormat
      -> DumpSize
      -> Options)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser FilePath -> Parser (Maybe FilePath)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional
            ( Mod OptionFields FilePath -> Parser FilePath
forall s. IsString s => Mod OptionFields s -> Parser s
strOption
                ( FilePath -> Mod OptionFields FilePath
forall (f :: * -> *) a. HasName f => FilePath -> Mod f a
long FilePath
"isa"
                    Mod OptionFields FilePath
-> Mod OptionFields FilePath -> Mod OptionFields FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields FilePath
forall (f :: * -> *) a. HasMetavar f => FilePath -> Mod f a
metavar FilePath
"ISA"
                    Mod OptionFields FilePath
-> Mod OptionFields FilePath -> Mod OptionFields FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields FilePath
forall (f :: * -> *) a. FilePath -> Mod f a
help FilePath
"ISA (risc-iv-32, f32a, acc32, m68k, vliw-iv, wasm32); detected from the source if omitted"
                )
            )
        Parser
  (Maybe FilePath
   -> Bool
   -> Bool
   -> Bool
   -> Int
   -> Int
   -> Int
   -> AddrFormat
   -> DumpSize
   -> Options)
-> Parser (Maybe FilePath)
-> Parser
     (Bool
      -> Bool
      -> Bool
      -> Int
      -> Int
      -> Int
      -> AddrFormat
      -> DumpSize
      -> Options)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser FilePath -> Parser (Maybe FilePath)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional
            ( Mod OptionFields FilePath -> Parser FilePath
forall s. IsString s => Mod OptionFields s -> Parser s
strOption
                ( FilePath -> Mod OptionFields FilePath
forall (f :: * -> *) a. HasName f => FilePath -> Mod f a
long FilePath
"conf"
                    Mod OptionFields FilePath
-> Mod OptionFields FilePath -> Mod OptionFields FilePath
forall a. Semigroup a => a -> a -> a
<> Char -> Mod OptionFields FilePath
forall (f :: * -> *) a. HasName f => Char -> Mod f a
short Char
'c'
                    Mod OptionFields FilePath
-> Mod OptionFields FilePath -> Mod OptionFields FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields FilePath
forall (f :: * -> *) a. FilePath -> Mod f a
help FilePath
"Configuration file (.yaml)"
                    Mod OptionFields FilePath
-> Mod OptionFields FilePath -> Mod OptionFields FilePath
forall a. Semigroup a => a -> a -> a
<> Mod OptionFields FilePath
forall a (f :: * -> *). Show a => Mod f a
showDefault
                    Mod OptionFields FilePath
-> Mod OptionFields FilePath -> Mod OptionFields FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields FilePath
forall (f :: * -> *) a. HasMetavar f => FilePath -> Mod f a
metavar FilePath
"CONF"
                )
            )
        Parser
  (Bool
   -> Bool
   -> Bool
   -> Int
   -> Int
   -> Int
   -> AddrFormat
   -> DumpSize
   -> Options)
-> Parser Bool
-> Parser
     (Bool
      -> Bool -> Int -> Int -> Int -> AddrFormat -> DumpSize -> Options)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Mod FlagFields Bool -> Parser Bool
switch
            ( Char -> Mod FlagFields Bool
forall (f :: * -> *) a. HasName f => Char -> Mod f a
short Char
'S'
                Mod FlagFields Bool -> Mod FlagFields Bool -> Mod FlagFields Bool
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod FlagFields Bool
forall (f :: * -> *) a. FilePath -> Mod f a
help FilePath
"Only run preprocess and translation steps"
            )
        Parser
  (Bool
   -> Bool -> Int -> Int -> Int -> AddrFormat -> DumpSize -> Options)
-> Parser Bool
-> Parser
     (Bool -> Int -> Int -> Int -> AddrFormat -> DumpSize -> Options)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Mod FlagFields Bool -> Parser Bool
switch
            ( FilePath -> Mod FlagFields Bool
forall (f :: * -> *) a. HasName f => FilePath -> Mod f a
long FilePath
"stats"
                Mod FlagFields Bool -> Mod FlagFields Bool -> Mod FlagFields Bool
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod FlagFields Bool
forall (f :: * -> *) a. FilePath -> Mod f a
help FilePath
"Append a built-in `Overview` report"
            )
        Parser
  (Bool -> Int -> Int -> Int -> AddrFormat -> DumpSize -> Options)
-> Parser Bool
-> Parser (Int -> Int -> Int -> AddrFormat -> DumpSize -> Options)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Mod FlagFields Bool -> Parser Bool
switch
            ( FilePath -> Mod FlagFields Bool
forall (f :: * -> *) a. HasName f => FilePath -> Mod f a
long FilePath
"verbose"
                Mod FlagFields Bool -> Mod FlagFields Bool -> Mod FlagFields Bool
forall a. Semigroup a => a -> a -> a
<> Char -> Mod FlagFields Bool
forall (f :: * -> *) a. HasName f => Char -> Mod f a
short Char
'v'
                Mod FlagFields Bool -> Mod FlagFields Bool -> Mod FlagFields Bool
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod FlagFields Bool
forall (f :: * -> *) a. FilePath -> Mod f a
help FilePath
"Verbose output"
            )
        Parser (Int -> Int -> Int -> AddrFormat -> DumpSize -> Options)
-> Parser Int
-> Parser (Int -> Int -> AddrFormat -> DumpSize -> Options)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReadM Int -> Mod OptionFields Int -> Parser Int
forall a. ReadM a -> Mod OptionFields a -> Parser a
option
            ReadM Int
forall a. Read a => ReadM a
auto
            ( FilePath -> Mod OptionFields Int
forall (f :: * -> *) a. HasName f => FilePath -> Mod f a
long FilePath
"instruction-limit"
                Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields Int
forall (f :: * -> *) a. HasMetavar f => FilePath -> Mod f a
metavar FilePath
"LIMIT"
                Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields Int
forall (f :: * -> *) a. FilePath -> Mod f a
help FilePath
"Maximum number of instructions to execute"
                Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Semigroup a => a -> a -> a
<> Int -> Mod OptionFields Int
forall (f :: * -> *) a. HasValue f => a -> Mod f a
value (Options -> Int
maxInstructionLimit Options
forall a. Default a => a
def)
                Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Semigroup a => a -> a -> a
<> Mod OptionFields Int
forall a (f :: * -> *). Show a => Mod f a
showDefault
            )
        Parser (Int -> Int -> AddrFormat -> DumpSize -> Options)
-> Parser Int -> Parser (Int -> AddrFormat -> DumpSize -> Options)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReadM Int -> Mod OptionFields Int -> Parser Int
forall a. ReadM a -> Mod OptionFields a -> Parser a
option
            ReadM Int
forall a. Read a => ReadM a
auto
            ( FilePath -> Mod OptionFields Int
forall (f :: * -> *) a. HasName f => FilePath -> Mod f a
long FilePath
"memory-limit"
                Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields Int
forall (f :: * -> *) a. HasMetavar f => FilePath -> Mod f a
metavar FilePath
"SIZE"
                Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields Int
forall (f :: * -> *) a. FilePath -> Mod f a
help FilePath
"Maximum memory size in bytes"
                Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Semigroup a => a -> a -> a
<> Int -> Mod OptionFields Int
forall (f :: * -> *) a. HasValue f => a -> Mod f a
value (Options -> Int
maxMemoryLimit Options
forall a. Default a => a
def)
                Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Semigroup a => a -> a -> a
<> Mod OptionFields Int
forall a (f :: * -> *). Show a => Mod f a
showDefault
            )
        Parser (Int -> AddrFormat -> DumpSize -> Options)
-> Parser Int -> Parser (AddrFormat -> DumpSize -> Options)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReadM Int -> Mod OptionFields Int -> Parser Int
forall a. ReadM a -> Mod OptionFields a -> Parser a
option
            ReadM Int
forall a. Read a => ReadM a
auto
            ( FilePath -> Mod OptionFields Int
forall (f :: * -> *) a. HasName f => FilePath -> Mod f a
long FilePath
"state-log-limit"
                Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields Int
forall (f :: * -> *) a. HasMetavar f => FilePath -> Mod f a
metavar FilePath
"LIMIT"
                Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields Int
forall (f :: * -> *) a. FilePath -> Mod f a
help FilePath
"Maximum number of state records to log"
                Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Semigroup a => a -> a -> a
<> Int -> Mod OptionFields Int
forall (f :: * -> *) a. HasValue f => a -> Mod f a
value (Options -> Int
maxStateLogLimit Options
forall a. Default a => a
def)
                Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Semigroup a => a -> a -> a
<> Mod OptionFields Int
forall a (f :: * -> *). Show a => Mod f a
showDefault
            )
        Parser (AddrFormat -> DumpSize -> Options)
-> Parser AddrFormat -> Parser (DumpSize -> Options)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReadM AddrFormat
-> Mod OptionFields AddrFormat -> Parser AddrFormat
forall a. ReadM a -> Mod OptionFields a -> Parser a
option
            ReadM AddrFormat
forall a. Read a => ReadM a
auto
            ( FilePath -> Mod OptionFields AddrFormat
forall (f :: * -> *) a. HasName f => FilePath -> Mod f a
long FilePath
"dump-addr-format"
                Mod OptionFields AddrFormat
-> Mod OptionFields AddrFormat -> Mod OptionFields AddrFormat
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields AddrFormat
forall (f :: * -> *) a. HasMetavar f => FilePath -> Mod f a
metavar FilePath
"FORMAT"
                Mod OptionFields AddrFormat
-> Mod OptionFields AddrFormat -> Mod OptionFields AddrFormat
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields AddrFormat
forall (f :: * -> *) a. FilePath -> Mod f a
help FilePath
"Numeral format for -S dump addresses: hex or dec (default: hex)"
                Mod OptionFields AddrFormat
-> Mod OptionFields AddrFormat -> Mod OptionFields AddrFormat
forall a. Semigroup a => a -> a -> a
<> AddrFormat -> Mod OptionFields AddrFormat
forall (f :: * -> *) a. HasValue f => a -> Mod f a
value (Options -> AddrFormat
dumpAddrFormat Options
forall a. Default a => a
def)
            )
        Parser (DumpSize -> Options) -> Parser DumpSize -> Parser Options
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReadM DumpSize -> Mod OptionFields DumpSize -> Parser DumpSize
forall a. ReadM a -> Mod OptionFields a -> Parser a
option
            ReadM DumpSize
forall a. Read a => ReadM a
auto
            ( FilePath -> Mod OptionFields DumpSize
forall (f :: * -> *) a. HasName f => FilePath -> Mod f a
long FilePath
"dump-size"
                Mod OptionFields DumpSize
-> Mod OptionFields DumpSize -> Mod OptionFields DumpSize
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields DumpSize
forall (f :: * -> *) a. HasMetavar f => FilePath -> Mod f a
metavar FilePath
"MODE"
                Mod OptionFields DumpSize
-> Mod OptionFields DumpSize -> Mod OptionFields DumpSize
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields DumpSize
forall (f :: * -> *) a. FilePath -> Mod f a
help FilePath
"Show or hide the (N B) byte-count suffix on -S dump address ranges: show or hide (default: show)"
                Mod OptionFields DumpSize
-> Mod OptionFields DumpSize -> Mod OptionFields DumpSize
forall a. Semigroup a => a -> a -> a
<> DumpSize -> Mod OptionFields DumpSize
forall (f :: * -> *) a. HasValue f => a -> Mod f a
value (Options -> DumpSize
dumpSize Options
forall a. Default a => a
def)
            )

main :: IO ()
IO ()
main = Options -> IO ()
runWrenchIO (Options -> IO ()) -> IO Options -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< ParserInfo Options -> IO Options
forall a. ParserInfo a -> IO a
execParser ParserInfo Options
opts
    where
        opts :: ParserInfo Options
opts =
            Parser Options -> InfoMod Options -> ParserInfo Options
forall a. Parser a -> InfoMod a -> ParserInfo a
info
                (Parser Options
options Parser Options -> Parser (Options -> Options) -> Parser Options
forall (f :: * -> *) a b. Applicative f => f a -> f (a -> b) -> f b
<**> Parser (Options -> Options)
forall a. Parser (a -> a)
helper Parser Options -> Parser (Options -> Options) -> Parser Options
forall (f :: * -> *) a b. Applicative f => f a -> f (a -> b) -> f b
<**> FilePath -> Parser (Options -> Options)
forall a. FilePath -> Parser (a -> a)
simpleVersioner (Text -> FilePath
forall a. ToString a => a -> FilePath
toString Text
wrenchVersion))
                (InfoMod Options
forall a. InfoMod a
fullDesc InfoMod Options -> InfoMod Options -> InfoMod Options
forall a. Semigroup a => a -> a -> a
<> FilePath -> InfoMod Options
forall a. FilePath -> InfoMod a
progDesc FilePath
"App for laboratory course of computer architecture.")