    module Mueval.ArgsParse (Options(..), interpreterOpts) where

    import Control.Monad (liftM)
    import System.Console.GetOpt

    import Mueval.Context (defaultModules, defaultPackages)

    -- | See the results of --help for information on what each option means.
    data Options = Options
     { Options -> Int
    timeLimit :: Int
       , Options -> Maybe [String]
    modules :: Maybe [String]
       , Options -> String
    expression :: String
       , Options -> String
    loadFile :: String
       , Options -> String
    user :: String
       , Options -> Bool
    printType :: Bool
       , Options -> Bool
    typeOnly :: Bool
       , Options -> Bool
    extensions :: Bool
       , Options -> [String]
    namedExtensions :: [String]
       , Options -> Bool
    noImports :: Bool
       , Options -> Bool
    rLimits :: Bool
       , Options -> Bool
    packageTrust :: Bool
       , Options -> [String]
    trustedPackages :: [String]
       , Options -> Bool
    help :: Bool
     } deriving Int -> Options -> ShowS
    [Options] -> ShowS
    Options -> String
    (Int -> Options -> ShowS)
    -> (Options -> String) -> ([Options] -> ShowS) -> Show Options
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> Options -> ShowS
    showsPrec :: Int -> Options -> ShowS
    $cshow :: Options -> String
    show :: Options -> String
    $cshowList :: [Options] -> ShowS
    showList :: [Options] -> ShowS
    Show

    defaultOptions :: Options
    defaultOptions :: Options
    defaultOptions = Options { expression :: String
    expression = String
    ""
                               , modules :: Maybe [String]
    modules = [String] -> Maybe [String]
    forall a. a -> Maybe a
    Just [String]
    defaultModules
                               , timeLimit :: Int
    timeLimit = Int
    5
                               , user :: String
    user = String
    ""
                               , loadFile :: String
    loadFile = String
    ""
                               , printType :: Bool
    printType = Bool
    False
                               , typeOnly :: Bool
    typeOnly = Bool
    False
                               , extensions :: Bool
    extensions = Bool
    False
                               , namedExtensions :: [String]
    namedExtensions = []
                               , noImports :: Bool
    noImports = Bool
    False
                               , rLimits :: Bool
    rLimits = Bool
    False
                               , packageTrust :: Bool
    packageTrust = Bool
    False
                               , trustedPackages :: [String]
    trustedPackages = [String]
    defaultPackages
                               , help :: Bool
    help = Bool
    False }

    options :: [OptDescr (Options -> Options)]
    options :: [OptDescr (Options -> Options)]
    options = [String
    -> [String]
    -> ArgDescr (Options -> Options)
    -> String
    -> OptDescr (Options -> Options)
    forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
    Option String
    "p"     [String
    "password"]
                          ((String -> Options -> Options)
    -> String -> ArgDescr (Options -> Options)
    forall a. (String -> a) -> String -> ArgDescr a
    ReqArg (\String
    u Options
    opts -> Options
    opts {user :: String
    user = String
    u}) String
    "PASSWORD")
                          String
    "The password for the mubot account. If this is set, mueval will attempt to setuid to the mubot user. This is optional, as it requires the mubot user to be set up properly. (Currently a null-op.)",
               String
    -> [String]
    -> ArgDescr (Options -> Options)
    -> String
    -> OptDescr (Options -> Options)
    forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
    Option String
    "t"     [String
    "time-limit"]
                          ((String -> Options -> Options)
    -> String -> ArgDescr (Options -> Options)
    forall a. (String -> a) -> String -> ArgDescr a
    ReqArg (\String
    t Options
    opts -> Options
    opts { timeLimit :: Int
    timeLimit = String -> Int
    forall a. Read a => String -> a
    read String
    t :: Int }) String
    "TIME")
                          String
    "Time limit for compilation and evaluation",

               String
    -> [String]
    -> ArgDescr (Options -> Options)
    -> String
    -> OptDescr (Options -> Options)
    forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
    Option String
    "l"     [String
    "load-file"]
                          ((String -> Options -> Options)
    -> String -> ArgDescr (Options -> Options)
    forall a. (String -> a) -> String -> ArgDescr a
    ReqArg (\String
    e Options
    opts -> Options
    opts { loadFile :: String
    loadFile = String
    e}) String
    "FILE")
                          String
    "A local file for Mueval to load, providing definitions. Contents are trusted! Do not put anything dubious in it!",

               String
    -> [String]
    -> ArgDescr (Options -> Options)
    -> String
    -> OptDescr (Options -> Options)
    forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
    Option String
    "m"     [String
    "module"]
                          ((String -> Options -> Options)
    -> String -> ArgDescr (Options -> Options)
    forall a. (String -> a) -> String -> ArgDescr a
    ReqArg (\String
    m Options
    opts -> Options
    opts { modules :: Maybe [String]
    modules = ([String] -> [String]) -> Maybe [String] -> Maybe [String]
    forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
    liftM (String
    mString -> [String] -> [String]
    forall a. a -> [a] -> [a]
    :) (Options -> Maybe [String]
    modules Options
    opts)}) String
    "MODULE")
                          String
    "A module we should import functions from for evaluation. (Can be given multiple times.)",
               String
    -> [String]
    -> ArgDescr (Options -> Options)
    -> String
    -> OptDescr (Options -> Options)
    forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
    Option String
    "n"     [String
    "no-imports"]
                          ((Options -> Options) -> ArgDescr (Options -> Options)
    forall a. a -> ArgDescr a
    NoArg (\Options
    opts -> Options
    opts { noImports :: Bool
    noImports = Bool
    True}))
                          String
    "Whether to import any default modules, such as Prelude; this is useful if you are loading a file which, say, redefines Prelude operators. This can be subverted by using --load-file.",
               String
    -> [String]
    -> ArgDescr (Options -> Options)
    -> String
    -> OptDescr (Options -> Options)
    forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
    Option String
    "E"     [String
    "Extensions"]
                          ((Options -> Options) -> ArgDescr (Options -> Options)
    forall a. a -> ArgDescr a
    NoArg (\Options
    opts -> Options
    opts { extensions :: Bool
    extensions = Bool
    True}))
                          String
    "Whether to enable the Glasgow extensions to Haskell '98. Defaults to false, but enabling is useful for QuickCheck.",
               String
    -> [String]
    -> ArgDescr (Options -> Options)
    -> String
    -> OptDescr (Options -> Options)
    forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
    Option String
    "X"     [String
    "extension"]
                          ((String -> Options -> Options)
    -> String -> ArgDescr (Options -> Options)
    forall a. (String -> a) -> String -> ArgDescr a
    ReqArg (\String
    e Options
    opts -> Options
    opts { namedExtensions :: [String]
    namedExtensions = String
    e String -> [String] -> [String]
    forall a. a -> [a] -> [a]
    : Options -> [String]
    namedExtensions Options
    opts }) String
    "EXTENSION")
                          String
    "Pass additional flags enabling extensions just like you would to ghc. Example: -XViewPatterns",
               String
    -> [String]
    -> ArgDescr (Options -> Options)
    -> String
    -> OptDescr (Options -> Options)
    forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
    Option String
    "e"     [String
    "expression"]
                          ((String -> Options -> Options)
    -> String -> ArgDescr (Options -> Options)
    forall a. (String -> a) -> String -> ArgDescr a
    ReqArg (\String
    e Options
    opts -> Options
    opts { expression :: String
    expression = String
    e}) String
    "EXPRESSION")
                          String
    "The expression to be evaluated.",
               String
    -> [String]
    -> ArgDescr (Options -> Options)
    -> String
    -> OptDescr (Options -> Options)
    forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
    Option String
    "i"     [String
    "inferred-type"]
                          ((Options -> Options) -> ArgDescr (Options -> Options)
    forall a. a -> ArgDescr a
    NoArg (\Options
    opts -> Options
    opts { printType :: Bool
    printType = Bool
    True}))
                          String
    "Whether to enable printing of inferred type and the expression (as Mueval sees it). Defaults to false.",
               String
    -> [String]
    -> ArgDescr (Options -> Options)
    -> String
    -> OptDescr (Options -> Options)
    forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
    Option String
    "T"     [String
    "type-only"]
                          ((Options -> Options) -> ArgDescr (Options -> Options)
    forall a. a -> ArgDescr a
    NoArg (\Options
    opts -> Options
    opts { typeOnly :: Bool
    typeOnly = Bool
    True}))
                          String
    "Only print the expression and type, don't evaluate the expression. Defaults to false.",
               String
    -> [String]
    -> ArgDescr (Options -> Options)
    -> String
    -> OptDescr (Options -> Options)
    forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
    Option String
    "r"     [String
    "resource-limits"]
                          ((Options -> Options) -> ArgDescr (Options -> Options)
    forall a. a -> ArgDescr a
    NoArg (\Options
    opts -> Options
    opts { rLimits :: Bool
    rLimits = Bool
    True}))
                          String
    "Enable resource limits (using POSIX rlimits). Mueval does not by default since rlimits are broken on many systems.",
               String
    -> [String]
    -> ArgDescr (Options -> Options)
    -> String
    -> OptDescr (Options -> Options)
    forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
    Option String
    "S"     [String
    "package-trust"]
                          ((Options -> Options) -> ArgDescr (Options -> Options)
    forall a. a -> ArgDescr a
    NoArg (\Options
    opts -> Options
    opts {packageTrust :: Bool
    packageTrust = Bool
    True, namedExtensions :: [String]
    namedExtensions = String
    "Safe" String -> [String] -> [String]
    forall a. a -> [a] -> [a]
    : Options -> [String]
    namedExtensions Options
    opts}))
                          String
    "Enable Safe-Haskell package trust system",
               String
    -> [String]
    -> ArgDescr (Options -> Options)
    -> String
    -> OptDescr (Options -> Options)
    forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
    Option String
    "s"     [String
    "trust"]
                          ((String -> Options -> Options)
    -> String -> ArgDescr (Options -> Options)
    forall a. (String -> a) -> String -> ArgDescr a
    ReqArg (\String
    e Options
    opts -> Options
    opts {trustedPackages :: [String]
    trustedPackages = String
    e String -> [String] -> [String]
    forall a. a -> [a] -> [a]
    : Options -> [String]
    trustedPackages Options
    opts}) String
    "PACKAGE")
                          String
    "Specify a package to be trusted by Safe Haskell (ignored unless -S also present)",
               String
    -> [String]
    -> ArgDescr (Options -> Options)
    -> String
    -> OptDescr (Options -> Options)
    forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
    Option String
    "h" [String
    "help"]
                           ((Options -> Options) -> ArgDescr (Options -> Options)
    forall a. a -> ArgDescr a
    NoArg (\Options
    opts -> Options
    opts { help :: Bool
    help = Bool
    True}))
                           String
    "Prints out usage info."
              ]

    interpreterOpts :: [String] -> Either (Bool, String) Options
    interpreterOpts :: [String] -> Either (Bool, String) Options
    interpreterOpts [String]
    argv
        | Options -> Bool
    help Options
    opts = (Bool, String) -> Either (Bool, String) Options
    forall a b. a -> Either a b
    Left (Bool
    True,String
    msg)
        | Bool -> Bool
    not ([String] -> Bool
    forall a. [a] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null [String]
    ers) = (Bool, String) -> Either (Bool, String) Options
    forall a b. a -> Either a b
    Left (Bool
    False, [String] -> String
    forall (t :: * -> *) a. Foldable t => t [a] -> [a]
    concat [String]
    ers String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    msg)
        | Bool
    otherwise = Options -> Either (Bool, String) Options
    forall a b. b -> Either a b
    Right Options
    opts
      where ([Options -> Options]
    o,[String]
    _,[String]
    ers) = ArgOrder (Options -> Options)
    -> [OptDescr (Options -> Options)]
    -> [String]
    -> ([Options -> Options], [String], [String])
    forall a.
    ArgOrder a -> [OptDescr a] -> [String] -> ([a], [String], [String])
    getOpt ArgOrder (Options -> Options)
    forall a. ArgOrder a
    Permute [OptDescr (Options -> Options)]
    options [String]
    argv
            msg :: String
    msg = String -> [OptDescr (Options -> Options)] -> String
    forall a. String -> [OptDescr a] -> String
    usageInfo String
    header [OptDescr (Options -> Options)]
    options
            opts :: Options
    opts = (Options -> (Options -> Options) -> Options)
    -> Options -> [Options -> Options] -> Options
    forall b a. (b -> a -> b) -> b -> [a] -> b
    forall (t :: * -> *) b a.
    Foldable t =>
    (b -> a -> b) -> b -> t a -> b
    foldl (((Options -> Options) -> Options -> Options)
    -> Options -> (Options -> Options) -> Options
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip (Options -> Options) -> Options -> Options
    forall a. a -> a
    id) Options
    defaultOptions [Options -> Options]
    o

    header :: String
    header :: String
    header = String
    "Usage: mueval [OPTION...] --expression EXPRESSION..."