-- | Implementation of common command-line arguments using <https://hackage.haskell.org/package/optparse-applicative  optparse-applicative>.
module LibRISCV.CmdLine where

import Data.Word
import Options.Applicative

-- | t'BasicArgs' can be combined/extended with additional parsers using
-- the '<*>' applicative operator provided by "Options.Applicative".
data BasicArgs = BasicArgs
    { BasicArgs -> Word32
memAddr :: Word32
    -- ^ Start address of the general-purpose memory.
    , BasicArgs -> Word32
memSize :: Word32
    -- ^ Size of the memory in bytes.
    , BasicArgs -> Bool
trace :: Bool
    -- ^ Whether to enable instruction tracing.
    , BasicArgs -> Bool
putRegs :: Bool
    -- ^ Whether to print all register values at the end.
    , BasicArgs -> String
file :: String
    -- ^ Path to ELf file which should be executed.
    }

-- TODO: Rename memStart to memSize.

-- | "Options.Applicative" parser for t'BasicArgs'.
basicArgs :: Parser BasicArgs
basicArgs :: Parser BasicArgs
basicArgs =
    Word32 -> Word32 -> Bool -> Bool -> String -> BasicArgs
BasicArgs
        (Word32 -> Word32 -> Bool -> Bool -> String -> BasicArgs)
-> Parser Word32
-> Parser (Word32 -> Bool -> Bool -> String -> BasicArgs)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReadM Word32 -> Mod OptionFields Word32 -> Parser Word32
forall a. ReadM a -> Mod OptionFields a -> Parser a
option
            ReadM Word32
forall a. Read a => ReadM a
auto
            ( String -> Mod OptionFields Word32
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"memory-start"
                Mod OptionFields Word32
-> Mod OptionFields Word32 -> Mod OptionFields Word32
forall a. Semigroup a => a -> a -> a
<> Char -> Mod OptionFields Word32
forall (f :: * -> *) a. HasName f => Char -> Mod f a
short Char
'm'
                Mod OptionFields Word32
-> Mod OptionFields Word32 -> Mod OptionFields Word32
forall a. Semigroup a => a -> a -> a
<> Word32 -> Mod OptionFields Word32
forall (f :: * -> *) a. HasValue f => a -> Mod f a
value Word32
0x10000
            )
        Parser (Word32 -> Bool -> Bool -> String -> BasicArgs)
-> Parser Word32 -> Parser (Bool -> Bool -> String -> BasicArgs)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReadM Word32 -> Mod OptionFields Word32 -> Parser Word32
forall a. ReadM a -> Mod OptionFields a -> Parser a
option
            ReadM Word32
forall a. Read a => ReadM a
auto
            ( String -> Mod OptionFields Word32
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"memory-size"
                Mod OptionFields Word32
-> Mod OptionFields Word32 -> Mod OptionFields Word32
forall a. Semigroup a => a -> a -> a
<> Char -> Mod OptionFields Word32
forall (f :: * -> *) a. HasName f => Char -> Mod f a
short Char
's'
                Mod OptionFields Word32
-> Mod OptionFields Word32 -> Mod OptionFields Word32
forall a. Semigroup a => a -> a -> a
<> Word32 -> Mod OptionFields Word32
forall (f :: * -> *) a. HasValue f => a -> Mod f a
value (Word32
1024 Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
* Word32
1024 Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
* Word32
1) -- 1 MB RAM
                Mod OptionFields Word32
-> Mod OptionFields Word32 -> Mod OptionFields Word32
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields Word32
forall (f :: * -> *) a. String -> Mod f a
help String
"Size of the memory region"
            )
        Parser (Bool -> Bool -> String -> BasicArgs)
-> Parser Bool -> Parser (Bool -> String -> BasicArgs)
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
            ( String -> Mod FlagFields Bool
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"trace"
                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
't'
                Mod FlagFields Bool -> Mod FlagFields Bool -> Mod FlagFields Bool
forall a. Semigroup a => a -> a -> a
<> String -> Mod FlagFields Bool
forall (f :: * -> *) a. String -> Mod f a
help String
"Whether to trace all executed instructions"
            )
        Parser (Bool -> String -> BasicArgs)
-> Parser Bool -> Parser (String -> BasicArgs)
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
            ( String -> Mod FlagFields Bool
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"registers"
                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
'r'
                Mod FlagFields Bool -> Mod FlagFields Bool -> Mod FlagFields Bool
forall a. Semigroup a => a -> a -> a
<> String -> Mod FlagFields Bool
forall (f :: * -> *) a. String -> Mod f a
help String
"Whether to print all register values"
            )
        Parser (String -> BasicArgs) -> Parser String -> Parser BasicArgs
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReadM String -> Mod ArgumentFields String -> Parser String
forall a. ReadM a -> Mod ArgumentFields a -> Parser a
argument ReadM String
forall s. IsString s => ReadM s
str (String -> Mod ArgumentFields String
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"FILE")