{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE RecordWildCards #-}

-- | Common option parsers for executables
module PlutusCore.Executable.Parsers where

import PlutusCore.AstSize (AstSize (..))
import PlutusCore.Default (BuiltinSemanticsVariant (..), DefaultFun)
import PlutusCore.Executable.Types
import UntypedPlutusCore qualified as UPLC

import Control.Lens ((^.))
import Data.List (intercalate)
import Data.Maybe
import Options.Applicative
import System.FilePath (takeExtension)

{-| Parser for an input stream. If none is specified,
default to stdin for ease of use in pipeline. -}
input :: Parser Input
input :: Parser Input
input = Parser Input
fileInput Parser Input -> Parser Input -> Parser Input
forall a. Parser a -> Parser a -> Parser a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Input
stdInput Parser Input -> Parser Input -> Parser Input
forall a. Parser a -> Parser a -> Parser a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Input -> Parser Input
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Input
StdInput

fileInput :: Parser Input
fileInput :: Parser Input
fileInput =
  String -> Input
FileInput
    (String -> Input) -> Parser String -> Parser Input
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Mod OptionFields String -> Parser String
forall s. IsString s => Mod OptionFields s -> Parser s
strOption
      ( String -> Mod OptionFields String
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"input"
          Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Semigroup a => a -> a -> a
<> Char -> Mod OptionFields String
forall (f :: * -> *) a. HasName f => Char -> Mod f a
short Char
'i'
          Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields String
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"FILENAME"
          Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields String
forall (f :: * -> *) a. HasCompleter f => String -> Mod f a
action String
"file"
          Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields String
forall (f :: * -> *) a. String -> Mod f a
help String
"Input file"
      )

stdInput :: Parser Input
stdInput :: Parser Input
stdInput =
  Input -> Mod FlagFields Input -> Parser Input
forall a. a -> Mod FlagFields a -> Parser a
flag'
    Input
StdInput
    ( String -> Mod FlagFields Input
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"stdin"
        Mod FlagFields Input
-> Mod FlagFields Input -> Mod FlagFields Input
forall a. Semigroup a => a -> a -> a
<> String -> Mod FlagFields Input
forall (f :: * -> *) a. String -> Mod f a
help String
"Read from stdin (default)"
    )

{-| Parser for an output stream. If none is specified,
default to stdout for ease of use in pipeline. -}
output :: Parser Output
output :: Parser Output
output = Parser Output
fileOutput Parser Output -> Parser Output -> Parser Output
forall a. Parser a -> Parser a -> Parser a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Output
stdOutput Parser Output -> Parser Output -> Parser Output
forall a. Parser a -> Parser a -> Parser a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Output
noOutput Parser Output -> Parser Output -> Parser Output
forall a. Parser a -> Parser a -> Parser a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Output -> Parser Output
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Output
StdOutput

fileOutput :: Parser Output
fileOutput :: Parser Output
fileOutput =
  String -> Output
FileOutput
    (String -> Output) -> Parser String -> Parser Output
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Mod OptionFields String -> Parser String
forall s. IsString s => Mod OptionFields s -> Parser s
strOption
      ( String -> Mod OptionFields String
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"output"
          Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Semigroup a => a -> a -> a
<> Char -> Mod OptionFields String
forall (f :: * -> *) a. HasName f => Char -> Mod f a
short Char
'o'
          Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields String
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"FILENAME"
          Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields String
forall (f :: * -> *) a. HasCompleter f => String -> Mod f a
action String
"file"
          Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields String
forall (f :: * -> *) a. String -> Mod f a
help String
"Output file"
      )

stdOutput :: Parser Output
stdOutput :: Parser Output
stdOutput =
  Output -> Mod FlagFields Output -> Parser Output
forall a. a -> Mod FlagFields a -> Parser a
flag'
    Output
StdOutput
    ( String -> Mod FlagFields Output
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"stdout"
        Mod FlagFields Output
-> Mod FlagFields Output -> Mod FlagFields Output
forall a. Semigroup a => a -> a -> a
<> String -> Mod FlagFields Output
forall (f :: * -> *) a. String -> Mod f a
help String
"Write to stdout (default)"
    )

noOutput :: Parser Output
noOutput :: Parser Output
noOutput =
  Output -> Mod FlagFields Output -> Parser Output
forall a. a -> Mod FlagFields a -> Parser a
flag'
    Output
NoOutput
    ( String -> Mod FlagFields Output
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"silent"
        Mod FlagFields Output
-> Mod FlagFields Output -> Mod FlagFields Output
forall a. Semigroup a => a -> a -> a
<> Char -> Mod FlagFields Output
forall (f :: * -> *) a. HasName f => Char -> Mod f a
short Char
's'
        Mod FlagFields Output
-> Mod FlagFields Output -> Mod FlagFields Output
forall a. Semigroup a => a -> a -> a
<> String -> Mod FlagFields Output
forall (f :: * -> *) a. String -> Mod f a
help String
"Don't output the evaluation result"
    )

-- Reverse lookup in a name/value option table for 'showDefaultWith', so the
-- displayed default is exactly a string the option's reader accepts. Keyed on
-- 'show' rather than value equality because not every option value type has
-- an 'Eq' instance.
showByTable :: Show a => [(String, a)] -> a -> String
showByTable :: forall a. Show a => [(String, a)] -> a -> String
showByTable [(String, a)]
table a
v = String -> Maybe String -> String
forall a. a -> Maybe a -> a
fromMaybe String
"" (Maybe String -> String) -> Maybe String -> String
forall a b. (a -> b) -> a -> b
$ String -> [(String, String)] -> Maybe String
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup (a -> String
forall a. Show a => a -> String
show a
v) [(a -> String
forall a. Show a => a -> String
show a
v', String
name) | (String
name, a
v') <- [(String, a)]
table]

-- The single source of truth for each format's name, description (shown in
-- --help), and value; the reader and shell completion are derived from it.
formatTable :: [(String, Maybe String, Format)]
formatTable :: [(String, Maybe String, Format)]
formatTable =
  [ (String
"textual", Maybe String
forall a. Maybe a
Nothing, Format
Textual)
  , (String
"serialised", String -> Maybe String
forall a. a -> Maybe a
Just String
"cbor + flat, with de Bruijn indices", Format
Serialised)
  , (String
"hex", String -> Maybe String
forall a. a -> Maybe a
Just String
"hex + cbor + flat", Format
Hex)
  , (String
"flat-named", String -> Maybe String
forall a. a -> Maybe a
Just String
"names", AstNameType -> Format
Flat AstNameType
Named)
  , (String
"flat", String -> Maybe String
forall a. a -> Maybe a
Just String
"de Bruijn indices", AstNameType -> Format
Flat AstNameType
DeBruijn)
  , (String
"flat-deBruijn", String -> Maybe String
forall a. a -> Maybe a
Just String
"alias for flat", AstNameType -> Format
Flat AstNameType
DeBruijn)
  , (String
"flat-namedDeBruijn", String -> Maybe String
forall a. a -> Maybe a
Just String
"names and de Bruijn indices", AstNameType -> Format
Flat AstNameType
NamedDeBruijn)
  , (String
"blueprint", Maybe String
forall a. Maybe a
Nothing, Format
Blueprint)
  ]

formatHelp :: String
formatHelp :: String
formatHelp =
  String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate
    String
", "
    [String -> (String -> String) -> Maybe String -> String
forall b a. b -> (a -> b) -> Maybe a -> b
maybe String
name (\String
d -> String
name String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
" (" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
d String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
")") Maybe String
mdesc | (String
name, Maybe String
mdesc, Format
_) <- [(String, Maybe String, Format)]
formatTable]

formatReader :: String -> Maybe Format
formatReader :: String -> Maybe Format
formatReader String
s = [Format] -> Maybe Format
forall a. [a] -> Maybe a
listToMaybe [Format
v | (String
name, Maybe String
_, Format
v) <- [(String, Maybe String, Format)]
formatTable, String
name String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
s]

formatNames :: [String]
formatNames :: [String]
formatNames = [String
name | (String
name, Maybe String
_, Format
_) <- [(String, Maybe String, Format)]
formatTable]

inputformat :: Parser Format
inputformat :: Parser Format
inputformat =
  ReadM Format -> Mod OptionFields Format -> Parser Format
forall a. ReadM a -> Mod OptionFields a -> Parser a
option
    ((String -> Maybe Format) -> ReadM Format
forall a. (String -> Maybe a) -> ReadM a
maybeReader String -> Maybe Format
formatReader)
    ( String -> Mod OptionFields Format
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"if"
        Mod OptionFields Format
-> Mod OptionFields Format -> Mod OptionFields Format
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields Format
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"input-format"
        Mod OptionFields Format
-> Mod OptionFields Format -> Mod OptionFields Format
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields Format
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"FORMAT"
        Mod OptionFields Format
-> Mod OptionFields Format -> Mod OptionFields Format
forall a. Semigroup a => a -> a -> a
<> Format -> Mod OptionFields Format
forall (f :: * -> *) a. HasValue f => a -> Mod f a
value Format
Textual
        Mod OptionFields Format
-> Mod OptionFields Format -> Mod OptionFields Format
forall a. Semigroup a => a -> a -> a
<> Mod OptionFields Format
forall a (f :: * -> *). Show a => Mod f a
showDefault
        Mod OptionFields Format
-> Mod OptionFields Format -> Mod OptionFields Format
forall a. Semigroup a => a -> a -> a
<> [String] -> Mod OptionFields Format
forall (f :: * -> *) a. HasCompleter f => [String] -> Mod f a
completeWith [String]
formatNames
        Mod OptionFields Format
-> Mod OptionFields Format -> Mod OptionFields Format
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields Format
forall (f :: * -> *) a. String -> Mod f a
help (String
"Input format: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
formatHelp)
    )

-- File extensions that imply a non-textual format, common to every language
-- (UPLC, PLC, PIR all share the same flat/hex/cbor conventions).
nonTextualExtensionTable :: [(String, Format)]
nonTextualExtensionTable :: [(String, Format)]
nonTextualExtensionTable =
  [ (String
".flat", AstNameType -> Format
Flat AstNameType
DeBruijn)
  , (String
".hex", Format
Hex)
  , (String
".cbor", Format
Serialised)
  ]

{-| Guess the format from a file name's extension, given the extension that
denotes /this/ language's own textual format (@.uplc@ for UPLC, @.plc@ for
PLC). Returns 'Nothing' for an unrecognised extension, in which case callers
fall back to 'Textual'. -}
formatFromExtension :: String -> FilePath -> Maybe Format
formatFromExtension :: String -> String -> Maybe Format
formatFromExtension String
textualExt String
path
  | String -> String
takeExtension String
path String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
textualExt = Format -> Maybe Format
forall a. a -> Maybe a
Just Format
Textual
  | Bool
otherwise = String -> [(String, Format)] -> Maybe Format
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup (String -> String
takeExtension String
path) [(String, Format)]
nonTextualExtensionTable

{-| Describe, for the @--if@/@--of@ help text, which extensions are deduced to
which format for this language's @textualExt@, restricted to the formats in
the given table (an extension whose format isn't in @table@ is omitted, since
it falls back to textual instead). -}
extensionHelp :: String -> [(String, Maybe String, Format)] -> String
extensionHelp :: String -> [(String, Maybe String, Format)] -> String
extensionHelp String
textualExt [(String, Maybe String, Format)]
table =
  String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
", " (((String, Format) -> Maybe String)
-> [(String, Format)] -> [String]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (String, Format) -> Maybe String
describe ((String
textualExt, Format
Textual) (String, Format) -> [(String, Format)] -> [(String, Format)]
forall a. a -> [a] -> [a]
: [(String, Format)]
nonTextualExtensionTable))
  where
    describe :: (String, Format) -> Maybe String
describe (String
ext, Format
fmt) =
      (\String
name -> String
ext String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
" -> " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
name) (String -> String) -> Maybe String -> Maybe String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [String] -> Maybe String
forall a. [a] -> Maybe a
listToMaybe [String
name | (String
name, Maybe String
_, Format
fmt') <- [(String, Maybe String, Format)]
table, Format
fmt Format -> Format -> Bool
forall a. Eq a => a -> a -> Bool
== Format
fmt']

{-| The shared wording every language's @--if@/@--of@ "default:" help text is
built from, wrapped around that language's own @ext -> format@ list. -}
extensionDeductionSentence :: String -> String
extensionDeductionSentence :: String -> String
extensionDeductionSentence String
extList =
  String
"deduced from the file extension ("
    String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
extList
    String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"); any other extension, or reading from stdin/writing to stdout, defaults to textual"

-- The explanation of the default embedded in the @--if@/@--of@ help text,
-- shared between the input and output variants.
extensionDeductionNote :: String -> [(String, Maybe String, Format)] -> String
extensionDeductionNote :: String -> [(String, Maybe String, Format)] -> String
extensionDeductionNote String
textualExt [(String, Maybe String, Format)]
table = String -> String
extensionDeductionSentence (String -> [(String, Maybe String, Format)] -> String
extensionHelp String
textualExt [(String, Maybe String, Format)]
table)

{-| Build the full @--if@/@--of@ help text for a format option: @kind@ (e.g.
@"Input"@ or @"Output"@), the list of allowed values, and a note on how the
default is chosen. Kept as two separate sentences, so the note (e.g. "deduced
from the file extension") doesn't read as if it's parenthetically attached to
the last format in the list (e.g. @blueprint@). -}
formatOptionHelp :: String -> String -> String -> String
formatOptionHelp :: String -> String -> String -> String
formatOptionHelp String
kind String
formats String
note = String
kind String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" format: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
formats String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
". Default: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
note String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"."

-- | The formats named in a format table.
supportedFormats :: [(String, Maybe String, Format)] -> [Format]
supportedFormats :: [(String, Maybe String, Format)] -> [Format]
supportedFormats [(String, Maybe String, Format)]
table = [Format
v | (String
_, Maybe String
_, Format
v) <- [(String, Maybe String, Format)]
table]

{-| Generic extension-based format deduction, shared by every language's
input-format resolver: an explicit @--if@ always wins; otherwise look up the
input file's extension with @fromExt@, falling back to @deflt@ for stdin or an
extension @fromExt@ doesn't recognise. -}
deduceInputFormat :: (FilePath -> Maybe fmt) -> fmt -> Maybe fmt -> Input -> fmt
deduceInputFormat :: forall fmt.
(String -> Maybe fmt) -> fmt -> Maybe fmt -> Input -> fmt
deduceInputFormat String -> Maybe fmt
_ fmt
_ (Just fmt
fmt) Input
_ = fmt
fmt
deduceInputFormat String -> Maybe fmt
fromExt fmt
deflt Maybe fmt
Nothing (FileInput String
path) = fmt -> Maybe fmt -> fmt
forall a. a -> Maybe a -> a
fromMaybe fmt
deflt (String -> Maybe fmt
fromExt String
path)
deduceInputFormat String -> Maybe fmt
_ fmt
deflt Maybe fmt
Nothing Input
StdInput = fmt
deflt

{-| The output-format counterpart of 'deduceInputFormat': an explicit @--of@
always wins; otherwise look up the output file's extension with @fromExt@,
falling back to @deflt@ for stdout, the silent sink, or an unrecognised
extension. -}
deduceOutputFormat :: (FilePath -> Maybe fmt) -> fmt -> Maybe fmt -> Output -> fmt
deduceOutputFormat :: forall fmt.
(String -> Maybe fmt) -> fmt -> Maybe fmt -> Output -> fmt
deduceOutputFormat String -> Maybe fmt
_ fmt
_ (Just fmt
fmt) Output
_ = fmt
fmt
deduceOutputFormat String -> Maybe fmt
fromExt fmt
deflt Maybe fmt
Nothing (FileOutput String
path) = fmt -> Maybe fmt -> fmt
forall a. a -> Maybe a -> a
fromMaybe fmt
deflt (String -> Maybe fmt
fromExt String
path)
deduceOutputFormat String -> Maybe fmt
_ fmt
deflt Maybe fmt
Nothing Output
_ = fmt
deflt

{-| Work out which input format to use, deducing from the input file's
extension (using @textualExt@ as this language's own textual extension)
restricted to @supported@ (eg @.hex@ isn't deduced for the @plc@ command,
which only handles textual and Flat). -}
resolveInputFormat :: String -> [Format] -> Maybe Format -> Input -> Format
resolveInputFormat :: String -> [Format] -> Maybe Format -> Input -> Format
resolveInputFormat String
textualExt [Format]
supported =
  (String -> Maybe Format)
-> Format -> Maybe Format -> Input -> Format
forall fmt.
(String -> Maybe fmt) -> fmt -> Maybe fmt -> Input -> fmt
deduceInputFormat (String -> [Format] -> String -> Maybe Format
supportedFormatFromExtension String
textualExt [Format]
supported) Format
Textual

-- | The output-format counterpart of 'resolveInputFormat'.
resolveOutputFormat :: String -> [Format] -> Maybe Format -> Output -> Format
resolveOutputFormat :: String -> [Format] -> Maybe Format -> Output -> Format
resolveOutputFormat String
textualExt [Format]
supported =
  (String -> Maybe Format)
-> Format -> Maybe Format -> Output -> Format
forall fmt.
(String -> Maybe fmt) -> fmt -> Maybe fmt -> Output -> fmt
deduceOutputFormat (String -> [Format] -> String -> Maybe Format
supportedFormatFromExtension String
textualExt [Format]
supported) Format
Textual

-- | 'formatFromExtension', restricted to the formats in @supported@.
supportedFormatFromExtension :: String -> [Format] -> FilePath -> Maybe Format
supportedFormatFromExtension :: String -> [Format] -> String -> Maybe Format
supportedFormatFromExtension String
textualExt [Format]
supported String
path =
  case String -> String -> Maybe Format
formatFromExtension String
textualExt String
path of
    Just Format
fmt | Format
fmt Format -> [Format] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Format]
supported -> Format -> Maybe Format
forall a. a -> Maybe a
Just Format
fmt
    Maybe Format
_ -> Maybe Format
forall a. Maybe a
Nothing

{-| The @--if@/@--input-format@ option without a default, so we can tell whether
the user supplied it and deduce the format from the file extension if not. -}
inputformatOptional :: Parser (Maybe Format)
inputformatOptional :: Parser (Maybe Format)
inputformatOptional =
  Parser Format -> Parser (Maybe Format)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (Parser Format -> Parser (Maybe Format))
-> Parser Format -> Parser (Maybe Format)
forall a b. (a -> b) -> a -> b
$
    ReadM Format -> Mod OptionFields Format -> Parser Format
forall a. ReadM a -> Mod OptionFields a -> Parser a
option
      ((String -> Maybe Format) -> ReadM Format
forall a. (String -> Maybe a) -> ReadM a
maybeReader String -> Maybe Format
formatReader)
      ( String -> Mod OptionFields Format
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"if"
          Mod OptionFields Format
-> Mod OptionFields Format -> Mod OptionFields Format
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields Format
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"input-format"
          Mod OptionFields Format
-> Mod OptionFields Format -> Mod OptionFields Format
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields Format
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"FORMAT"
          Mod OptionFields Format
-> Mod OptionFields Format -> Mod OptionFields Format
forall a. Semigroup a => a -> a -> a
<> [String] -> Mod OptionFields Format
forall (f :: * -> *) a. HasCompleter f => [String] -> Mod f a
completeWith [String]
formatNames
          Mod OptionFields Format
-> Mod OptionFields Format -> Mod OptionFields Format
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields Format
forall (f :: * -> *) a. String -> Mod f a
help (String -> String -> String -> String
formatOptionHelp String
"Input" String
formatHelp (String -> [(String, Maybe String, Format)] -> String
extensionDeductionNote String
".uplc" [(String, Maybe String, Format)]
formatTable))
      )

{-| An input stream together with its format, deducing the format from the
file extension when @--if@ is not given. See 'resolveInputFormat'. -}
inputWithFormat :: Parser (Input, Format)
inputWithFormat :: Parser (Input, Format)
inputWithFormat =
  (\Input
inp Maybe Format
mfmt -> (Input
inp, String -> [Format] -> Maybe Format -> Input -> Format
resolveInputFormat String
".uplc" ([(String, Maybe String, Format)] -> [Format]
supportedFormats [(String, Maybe String, Format)]
formatTable) Maybe Format
mfmt Input
inp))
    (Input -> Maybe Format -> (Input, Format))
-> Parser Input -> Parser (Maybe Format -> (Input, Format))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Input
input
    Parser (Maybe Format -> (Input, Format))
-> Parser (Maybe Format) -> Parser (Input, Format)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser (Maybe Format)
inputformatOptional

{-| Like 'inputWithFormat' but for commands taking a list of input files: each
file is paired with the format to read it with. When @--if@ is given it forces
that format for every file; otherwise each file's format is deduced
independently from its own extension. -}
filesWithFormats :: Parser [(FilePath, Format)]
filesWithFormats :: Parser [(String, Format)]
filesWithFormats =
  ( \[String]
fs Maybe Format
mfmt -> [(String
f, String -> [Format] -> Maybe Format -> Input -> Format
resolveInputFormat String
".uplc" ([(String, Maybe String, Format)] -> [Format]
supportedFormats [(String, Maybe String, Format)]
formatTable) Maybe Format
mfmt (String -> Input
FileInput String
f)) | String
f <- [String]
fs]
  )
    ([String] -> Maybe Format -> [(String, Format)])
-> Parser [String] -> Parser (Maybe Format -> [(String, Format)])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser [String]
files
    Parser (Maybe Format -> [(String, Format)])
-> Parser (Maybe Format) -> Parser [(String, Format)]
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser (Maybe Format)
inputformatOptional

outputformat :: Parser Format
outputformat :: Parser Format
outputformat =
  ReadM Format -> Mod OptionFields Format -> Parser Format
forall a. ReadM a -> Mod OptionFields a -> Parser a
option
    ((String -> Maybe Format) -> ReadM Format
forall a. (String -> Maybe a) -> ReadM a
maybeReader String -> Maybe Format
formatReader)
    ( String -> Mod OptionFields Format
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"of"
        Mod OptionFields Format
-> Mod OptionFields Format -> Mod OptionFields Format
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields Format
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"output-format"
        Mod OptionFields Format
-> Mod OptionFields Format -> Mod OptionFields Format
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields Format
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"FORMAT"
        Mod OptionFields Format
-> Mod OptionFields Format -> Mod OptionFields Format
forall a. Semigroup a => a -> a -> a
<> Format -> Mod OptionFields Format
forall (f :: * -> *) a. HasValue f => a -> Mod f a
value Format
Textual
        Mod OptionFields Format
-> Mod OptionFields Format -> Mod OptionFields Format
forall a. Semigroup a => a -> a -> a
<> Mod OptionFields Format
forall a (f :: * -> *). Show a => Mod f a
showDefault
        Mod OptionFields Format
-> Mod OptionFields Format -> Mod OptionFields Format
forall a. Semigroup a => a -> a -> a
<> [String] -> Mod OptionFields Format
forall (f :: * -> *) a. HasCompleter f => [String] -> Mod f a
completeWith [String]
formatNames
        Mod OptionFields Format
-> Mod OptionFields Format -> Mod OptionFields Format
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields Format
forall (f :: * -> *) a. String -> Mod f a
help (String
"Output format: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
formatHelp)
    )

{-| The @--of@/@--output-format@ option without a default, so we can tell
whether the user supplied it and deduce the format from the @-o@ file extension
if not. -}
outputformatOptional :: Parser (Maybe Format)
outputformatOptional :: Parser (Maybe Format)
outputformatOptional =
  Parser Format -> Parser (Maybe Format)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (Parser Format -> Parser (Maybe Format))
-> Parser Format -> Parser (Maybe Format)
forall a b. (a -> b) -> a -> b
$
    ReadM Format -> Mod OptionFields Format -> Parser Format
forall a. ReadM a -> Mod OptionFields a -> Parser a
option
      ((String -> Maybe Format) -> ReadM Format
forall a. (String -> Maybe a) -> ReadM a
maybeReader String -> Maybe Format
formatReader)
      ( String -> Mod OptionFields Format
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"of"
          Mod OptionFields Format
-> Mod OptionFields Format -> Mod OptionFields Format
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields Format
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"output-format"
          Mod OptionFields Format
-> Mod OptionFields Format -> Mod OptionFields Format
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields Format
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"FORMAT"
          Mod OptionFields Format
-> Mod OptionFields Format -> Mod OptionFields Format
forall a. Semigroup a => a -> a -> a
<> [String] -> Mod OptionFields Format
forall (f :: * -> *) a. HasCompleter f => [String] -> Mod f a
completeWith [String]
formatNames
          Mod OptionFields Format
-> Mod OptionFields Format -> Mod OptionFields Format
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields Format
forall (f :: * -> *) a. String -> Mod f a
help (String -> String -> String -> String
formatOptionHelp String
"Output" String
formatHelp (String -> [(String, Maybe String, Format)] -> String
extensionDeductionNote String
".uplc" [(String, Maybe String, Format)]
formatTable))
      )

{-| An output stream together with its format, deducing the format from the
file extension when @--of@ is not given. See 'resolveOutputFormat'. -}
outputWithFormat :: Parser (Output, Format)
outputWithFormat :: Parser (Output, Format)
outputWithFormat =
  (\Output
outp Maybe Format
mfmt -> (Output
outp, String -> [Format] -> Maybe Format -> Output -> Format
resolveOutputFormat String
".uplc" ([(String, Maybe String, Format)] -> [Format]
supportedFormats [(String, Maybe String, Format)]
formatTable) Maybe Format
mfmt Output
outp))
    (Output -> Maybe Format -> (Output, Format))
-> Parser Output -> Parser (Maybe Format -> (Output, Format))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Output
output
    Parser (Maybe Format -> (Output, Format))
-> Parser (Maybe Format) -> Parser (Output, Format)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser (Maybe Format)
outputformatOptional

tracemode :: Parser TraceMode
tracemode :: Parser TraceMode
tracemode =
  ReadM TraceMode -> Mod OptionFields TraceMode -> Parser TraceMode
forall a. ReadM a -> Mod OptionFields a -> Parser a
option
    ReadM TraceMode
forall a. Read a => ReadM a
auto
    ( String -> Mod OptionFields TraceMode
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"trace-mode"
        Mod OptionFields TraceMode
-> Mod OptionFields TraceMode -> Mod OptionFields TraceMode
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields TraceMode
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"MODE"
        Mod OptionFields TraceMode
-> Mod OptionFields TraceMode -> Mod OptionFields TraceMode
forall a. Semigroup a => a -> a -> a
<> TraceMode -> Mod OptionFields TraceMode
forall (f :: * -> *) a. HasValue f => a -> Mod f a
value TraceMode
None
        Mod OptionFields TraceMode
-> Mod OptionFields TraceMode -> Mod OptionFields TraceMode
forall a. Semigroup a => a -> a -> a
<> Mod OptionFields TraceMode
forall a (f :: * -> *). Show a => Mod f a
showDefault
        Mod OptionFields TraceMode
-> Mod OptionFields TraceMode -> Mod OptionFields TraceMode
forall a. Semigroup a => a -> a -> a
<> [String] -> Mod OptionFields TraceMode
forall (f :: * -> *) a. HasCompleter f => [String] -> Mod f a
completeWith ((TraceMode -> String) -> [TraceMode] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map TraceMode -> String
forall a. Show a => a -> String
show [(TraceMode
forall a. Bounded a => a
minBound :: TraceMode) .. TraceMode
forall a. Bounded a => a
maxBound])
        Mod OptionFields TraceMode
-> Mod OptionFields TraceMode -> Mod OptionFields TraceMode
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields TraceMode
forall (f :: * -> *) a. String -> Mod f a
help String
"Mode for trace output."
    )

files :: Parser Files
files :: Parser [String]
files =
  Parser String -> Parser [String]
forall a. Parser a -> Parser [a]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
some
    ( 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
"[FILES...]"
            Mod ArgumentFields String
-> Mod ArgumentFields String -> Mod ArgumentFields String
forall a. Semigroup a => a -> a -> a
<> String -> Mod ArgumentFields String
forall (f :: * -> *) a. HasCompleter f => String -> Mod f a
action String
"file"
            Mod ArgumentFields String
-> Mod ArgumentFields String -> Mod ArgumentFields String
forall a. Semigroup a => a -> a -> a
<> String -> Mod ArgumentFields String
forall (f :: * -> *) a. String -> Mod f a
help String
"Input files; each file's format is deduced from its own extension unless --if is given"
        )
    )

applyOpts :: Parser ApplyOptions
applyOpts :: Parser ApplyOptions
applyOpts =
  (\[(String, Format)]
fps (Output
outp, Format
ofmt) PrintMode
mode -> [(String, Format)] -> Output -> Format -> PrintMode -> ApplyOptions
ApplyOptions [(String, Format)]
fps Output
outp Format
ofmt PrintMode
mode)
    ([(String, Format)]
 -> (Output, Format) -> PrintMode -> ApplyOptions)
-> Parser [(String, Format)]
-> Parser ((Output, Format) -> PrintMode -> ApplyOptions)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser [(String, Format)]
filesWithFormats
    Parser ((Output, Format) -> PrintMode -> ApplyOptions)
-> Parser (Output, Format) -> Parser (PrintMode -> ApplyOptions)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser (Output, Format)
outputWithFormat
    Parser (PrintMode -> ApplyOptions)
-> Parser PrintMode -> Parser ApplyOptions
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser PrintMode
printmode

printmode :: Parser PrintMode
printmode :: Parser PrintMode
printmode =
  ReadM PrintMode -> Mod OptionFields PrintMode -> Parser PrintMode
forall a. ReadM a -> Mod OptionFields a -> Parser a
option
    ReadM PrintMode
forall a. Read a => ReadM a
auto
    ( String -> Mod OptionFields PrintMode
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"print-mode"
        Mod OptionFields PrintMode
-> Mod OptionFields PrintMode -> Mod OptionFields PrintMode
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields PrintMode
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"MODE"
        Mod OptionFields PrintMode
-> Mod OptionFields PrintMode -> Mod OptionFields PrintMode
forall a. Semigroup a => a -> a -> a
<> PrintMode -> Mod OptionFields PrintMode
forall (f :: * -> *) a. HasValue f => a -> Mod f a
value PrintMode
Classic
        Mod OptionFields PrintMode
-> Mod OptionFields PrintMode -> Mod OptionFields PrintMode
forall a. Semigroup a => a -> a -> a
<> Mod OptionFields PrintMode
forall a (f :: * -> *). Show a => Mod f a
showDefault
        Mod OptionFields PrintMode
-> Mod OptionFields PrintMode -> Mod OptionFields PrintMode
forall a. Semigroup a => a -> a -> a
<> [String] -> Mod OptionFields PrintMode
forall (f :: * -> *) a. HasCompleter f => [String] -> Mod f a
completeWith ((PrintMode -> String) -> [PrintMode] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map PrintMode -> String
forall a. Show a => a -> String
show [(PrintMode
forall a. Bounded a => a
minBound :: PrintMode) .. PrintMode
forall a. Bounded a => a
maxBound])
        Mod OptionFields PrintMode
-> Mod OptionFields PrintMode -> Mod OptionFields PrintMode
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields PrintMode
forall (f :: * -> *) a. String -> Mod f a
help
          ( String
"Print mode for textual output (ignored elsewhere): Classic -> plcPrettyClassic, "
              String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"Simple -> plcPrettyClassicSimple, "
              String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"Readable -> prettyPlcReadable, ReadableSimple -> prettyPlcReadableSimple"
          )
    )

nameformat :: Parser NameFormat
nameformat :: Parser NameFormat
nameformat =
  NameFormat
-> NameFormat -> Mod FlagFields NameFormat -> Parser NameFormat
forall a. a -> a -> Mod FlagFields a -> Parser a
flag
    NameFormat
IdNames
    NameFormat
DeBruijnNames
    ( String -> Mod FlagFields NameFormat
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"debruijn"
        Mod FlagFields NameFormat
-> Mod FlagFields NameFormat -> Mod FlagFields NameFormat
forall a. Semigroup a => a -> a -> a
<> Char -> Mod FlagFields NameFormat
forall (f :: * -> *) a. HasName f => Char -> Mod f a
short Char
'j'
        Mod FlagFields NameFormat
-> Mod FlagFields NameFormat -> Mod FlagFields NameFormat
forall a. Semigroup a => a -> a -> a
<> String -> Mod FlagFields NameFormat
forall (f :: * -> *) a. String -> Mod f a
help String
"Output evaluation result with de Bruijn indices (default: show textual names)"
    )

certifier :: Parser Certifier
certifier :: Parser (Maybe String)
certifier =
  Parser String -> Parser (Maybe String)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (Parser String -> Parser (Maybe String))
-> Parser String -> Parser (Maybe String)
forall a b. (a -> b) -> a -> b
$
    Mod OptionFields String -> Parser String
forall s. IsString s => Mod OptionFields s -> Parser s
strOption
      ( String -> Mod OptionFields String
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"certify"
          Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields String
forall (f :: * -> *) a. String -> Mod f a
help
            ( String
"[EXPERIMENTAL] Produce a certificate ARG.agda proving that the program"
                String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
" transformaton is correct; the certificate is an Agda proof object, which"
                String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
" can be checked using the Agda proof assistant"
            )
      )

printOpts :: Parser PrintOptions
printOpts :: Parser PrintOptions
printOpts = Input -> Output -> PrintMode -> PrintOptions
PrintOptions (Input -> Output -> PrintMode -> PrintOptions)
-> Parser Input -> Parser (Output -> PrintMode -> PrintOptions)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Input
input Parser (Output -> PrintMode -> PrintOptions)
-> Parser Output -> Parser (PrintMode -> PrintOptions)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Output
output Parser (PrintMode -> PrintOptions)
-> Parser PrintMode -> Parser PrintOptions
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser PrintMode
printmode

convertOpts :: Parser ConvertOptions
convertOpts :: Parser ConvertOptions
convertOpts =
  (\(Input
inp, Format
ifmt) (Output
outp, Format
ofmt) PrintMode
mode -> Input -> Format -> Output -> Format -> PrintMode -> ConvertOptions
ConvertOptions Input
inp Format
ifmt Output
outp Format
ofmt PrintMode
mode)
    ((Input, Format)
 -> (Output, Format) -> PrintMode -> ConvertOptions)
-> Parser (Input, Format)
-> Parser ((Output, Format) -> PrintMode -> ConvertOptions)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser (Input, Format)
inputWithFormat
    Parser ((Output, Format) -> PrintMode -> ConvertOptions)
-> Parser (Output, Format) -> Parser (PrintMode -> ConvertOptions)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser (Output, Format)
outputWithFormat
    Parser (PrintMode -> ConvertOptions)
-> Parser PrintMode -> Parser ConvertOptions
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser PrintMode
printmode

certifierOutputMode :: Parser CertifierOutputMode
certifierOutputMode :: Parser CertifierOutputMode
certifierOutputMode =
  [Parser CertifierOutputMode] -> Parser CertifierOutputMode
forall (t :: * -> *) (f :: * -> *) a.
(Foldable t, Alternative f) =>
t (f a) -> f a
asum
    [ CertifierOutputMode
-> Mod FlagFields CertifierOutputMode -> Parser CertifierOutputMode
forall a. a -> Mod FlagFields a -> Parser a
flag'
        CertifierOutputMode
CertBasic
        ( String -> Mod FlagFields CertifierOutputMode
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"certifier-basic"
            Mod FlagFields CertifierOutputMode
-> Mod FlagFields CertifierOutputMode
-> Mod FlagFields CertifierOutputMode
forall a. Semigroup a => a -> a -> a
<> String -> Mod FlagFields CertifierOutputMode
forall (f :: * -> *) a. String -> Mod f a
help String
"Certifier produces basic output"
        )
    , String -> CertifierOutputMode
CertReport
        (String -> CertifierOutputMode)
-> Parser String -> Parser CertifierOutputMode
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Mod OptionFields String -> Parser String
forall s. IsString s => Mod OptionFields s -> Parser s
strOption
          ( String -> Mod OptionFields String
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"certifier-report"
              Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields String
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"REPORT_FILE"
              Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields String
forall (f :: * -> *) a. HasCompleter f => String -> Mod f a
action String
"file"
              Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields String
forall (f :: * -> *) a. String -> Mod f a
help String
"Certifier writes a report to the given file"
          )
    , CertifierOutputMode
-> CertifierOutputMode
-> Mod FlagFields CertifierOutputMode
-> Parser CertifierOutputMode
forall a. a -> a -> Mod FlagFields a -> Parser a
flag
        CertifierOutputMode
CertProject
        CertifierOutputMode
CertProject
        ( String -> Mod FlagFields CertifierOutputMode
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"certifier-project"
            Mod FlagFields CertifierOutputMode
-> Mod FlagFields CertifierOutputMode
-> Mod FlagFields CertifierOutputMode
forall a. Semigroup a => a -> a -> a
<> String -> Mod FlagFields CertifierOutputMode
forall (f :: * -> *) a. String -> Mod f a
help String
"Certifier produces an Agda project that can be type checked (default)"
        )
    ]

cseWhichSubtermsTable :: [(String, UPLC.CseWhichSubterms)]
cseWhichSubtermsTable :: [(String, CseWhichSubterms)]
cseWhichSubtermsTable =
  [ (String
"all", CseWhichSubterms
UPLC.AllSubterms)
  , (String
"exclude-work-free", CseWhichSubterms
UPLC.ExcludeWorkFree)
  ]

optimizeOpts :: Parser (UPLC.OptimizeOpts name a)
optimizeOpts :: forall name a. Parser (OptimizeOpts name a)
optimizeOpts = do
  Int
_ooMaxSimplifierIterations <-
    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
      ( String -> Mod OptionFields Int
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"opt-simplifier-iterations"
          Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields Int
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"INT"
          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 (OptimizeOpts Any Any
forall name a. OptimizeOpts name a
UPLC.defaultOptimizeOpts OptimizeOpts Any Any
-> Getting Int (OptimizeOpts Any Any) Int -> Int
forall s a. s -> Getting a s a -> a
^. Getting Int (OptimizeOpts Any Any) Int
forall name a (f :: * -> *).
Functor f =>
(Int -> f Int) -> OptimizeOpts name a -> f (OptimizeOpts name a)
UPLC.ooMaxSimplifierIterations)
          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
          Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields Int
forall (f :: * -> *) a. String -> Mod f a
help String
"Number of simplifier iterations"
      )
  Int
_ooMaxCseIterations <-
    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
      ( String -> Mod OptionFields Int
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"opt-cse-iterations"
          Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields Int
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"INT"
          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 (OptimizeOpts Any Any
forall name a. OptimizeOpts name a
UPLC.defaultOptimizeOpts OptimizeOpts Any Any
-> Getting Int (OptimizeOpts Any Any) Int -> Int
forall s a. s -> Getting a s a -> a
^. Getting Int (OptimizeOpts Any Any) Int
forall name a (f :: * -> *).
Functor f =>
(Int -> f Int) -> OptimizeOpts name a -> f (OptimizeOpts name a)
UPLC.ooMaxCseIterations)
          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
          Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields Int
forall (f :: * -> *) a. String -> Mod f a
help String
"Number of CSE iterations"
      )
  CseWhichSubterms
_ooCseWhichSubterms <-
    ReadM CseWhichSubterms
-> Mod OptionFields CseWhichSubterms -> Parser CseWhichSubterms
forall a. ReadM a -> Mod OptionFields a -> Parser a
option
      ((String -> Maybe CseWhichSubterms) -> ReadM CseWhichSubterms
forall a. (String -> Maybe a) -> ReadM a
maybeReader (String -> [(String, CseWhichSubterms)] -> Maybe CseWhichSubterms
forall a b. Eq a => a -> [(a, b)] -> Maybe b
`lookup` [(String, CseWhichSubterms)]
cseWhichSubtermsTable))
      ( String -> Mod OptionFields CseWhichSubterms
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"opt-cse-which-subterms"
          Mod OptionFields CseWhichSubterms
-> Mod OptionFields CseWhichSubterms
-> Mod OptionFields CseWhichSubterms
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields CseWhichSubterms
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"MODE"
          Mod OptionFields CseWhichSubterms
-> Mod OptionFields CseWhichSubterms
-> Mod OptionFields CseWhichSubterms
forall a. Semigroup a => a -> a -> a
<> CseWhichSubterms -> Mod OptionFields CseWhichSubterms
forall (f :: * -> *) a. HasValue f => a -> Mod f a
value CseWhichSubterms
UPLC.ExcludeWorkFree
          Mod OptionFields CseWhichSubterms
-> Mod OptionFields CseWhichSubterms
-> Mod OptionFields CseWhichSubterms
forall a. Semigroup a => a -> a -> a
<> (CseWhichSubterms -> String) -> Mod OptionFields CseWhichSubterms
forall a (f :: * -> *). (a -> String) -> Mod f a
showDefaultWith ([(String, CseWhichSubterms)] -> CseWhichSubterms -> String
forall a. Show a => [(String, a)] -> a -> String
showByTable [(String, CseWhichSubterms)]
cseWhichSubtermsTable)
          Mod OptionFields CseWhichSubterms
-> Mod OptionFields CseWhichSubterms
-> Mod OptionFields CseWhichSubterms
forall a. Semigroup a => a -> a -> a
<> [String] -> Mod OptionFields CseWhichSubterms
forall (f :: * -> *) a. HasCompleter f => [String] -> Mod f a
completeWith (((String, CseWhichSubterms) -> String)
-> [(String, CseWhichSubterms)] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String, CseWhichSubterms) -> String
forall a b. (a, b) -> a
fst [(String, CseWhichSubterms)]
cseWhichSubtermsTable)
          Mod OptionFields CseWhichSubterms
-> Mod OptionFields CseWhichSubterms
-> Mod OptionFields CseWhichSubterms
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields CseWhichSubterms
forall (f :: * -> *) a. String -> Mod f a
help (String
"CSE subterm selection: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
" | " (((String, CseWhichSubterms) -> String)
-> [(String, CseWhichSubterms)] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String, CseWhichSubterms) -> String
forall a b. (a, b) -> a
fst [(String, CseWhichSubterms)]
cseWhichSubtermsTable))
      )
  Bool
_ooConservativeOpts <-
    Mod FlagFields Bool -> Parser Bool
switch
      ( String -> Mod FlagFields Bool
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"opt-conservative"
          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
"Use conservative optimisation options. May result in less optimized code."
      )
  let _ooInlineHints :: InlineHints name a
_ooInlineHints = OptimizeOpts name a
forall name a. OptimizeOpts name a
UPLC.defaultOptimizeOpts OptimizeOpts name a
-> Getting
     (InlineHints name a) (OptimizeOpts name a) (InlineHints name a)
-> InlineHints name a
forall s a. s -> Getting a s a -> a
^. Getting
  (InlineHints name a) (OptimizeOpts name a) (InlineHints name a)
forall name1 a1 name2 a2 (f :: * -> *).
Functor f =>
(InlineHints name1 a1 -> f (InlineHints name2 a2))
-> OptimizeOpts name1 a1 -> f (OptimizeOpts name2 a2)
UPLC.ooInlineHints
  Bool
_ooInlineConstants <-
    Bool -> Bool -> Mod FlagFields Bool -> Parser Bool
forall a. a -> a -> Mod FlagFields a -> Parser a
flag
      Bool
True
      Bool
False
      ( String -> Mod FlagFields Bool
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"opt-no-inline-constants"
          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
"Disable constant inlining"
      )
  AstSize
_ooInlineUnconditionalGrowth <-
    ReadM AstSize -> Mod OptionFields AstSize -> Parser AstSize
forall a. ReadM a -> Mod OptionFields a -> Parser a
option
      (Integer -> AstSize
AstSize (Integer -> AstSize) -> ReadM Integer -> ReadM AstSize
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReadM Integer
forall a. Read a => ReadM a
auto)
      ( String -> Mod OptionFields AstSize
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"opt-inline-unconditional-growth"
          Mod OptionFields AstSize
-> Mod OptionFields AstSize -> Mod OptionFields AstSize
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields AstSize
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"INT"
          Mod OptionFields AstSize
-> Mod OptionFields AstSize -> Mod OptionFields AstSize
forall a. Semigroup a => a -> a -> a
<> AstSize -> Mod OptionFields AstSize
forall (f :: * -> *) a. HasValue f => a -> Mod f a
value (OptimizeOpts Any Any
forall name a. OptimizeOpts name a
UPLC.defaultOptimizeOpts OptimizeOpts Any Any
-> Getting AstSize (OptimizeOpts Any Any) AstSize -> AstSize
forall s a. s -> Getting a s a -> a
^. Getting AstSize (OptimizeOpts Any Any) AstSize
forall name a (f :: * -> *).
Functor f =>
(AstSize -> f AstSize)
-> OptimizeOpts name a -> f (OptimizeOpts name a)
UPLC.ooInlineUnconditionalGrowth)
          Mod OptionFields AstSize
-> Mod OptionFields AstSize -> Mod OptionFields AstSize
forall a. Semigroup a => a -> a -> a
<> Mod OptionFields AstSize
forall a (f :: * -> *). Show a => Mod f a
showDefault
          Mod OptionFields AstSize
-> Mod OptionFields AstSize -> Mod OptionFields AstSize
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields AstSize
forall (f :: * -> *) a. String -> Mod f a
help String
"Maximum allowed AST growth for unconditional inlining"
      )
  AstSize
_ooInlineCallsiteGrowth <-
    ReadM AstSize -> Mod OptionFields AstSize -> Parser AstSize
forall a. ReadM a -> Mod OptionFields a -> Parser a
option
      (Integer -> AstSize
AstSize (Integer -> AstSize) -> ReadM Integer -> ReadM AstSize
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReadM Integer
forall a. Read a => ReadM a
auto)
      ( String -> Mod OptionFields AstSize
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"opt-inline-callsite-growth"
          Mod OptionFields AstSize
-> Mod OptionFields AstSize -> Mod OptionFields AstSize
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields AstSize
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"INT"
          Mod OptionFields AstSize
-> Mod OptionFields AstSize -> Mod OptionFields AstSize
forall a. Semigroup a => a -> a -> a
<> AstSize -> Mod OptionFields AstSize
forall (f :: * -> *) a. HasValue f => a -> Mod f a
value (OptimizeOpts Any Any
forall name a. OptimizeOpts name a
UPLC.defaultOptimizeOpts OptimizeOpts Any Any
-> Getting AstSize (OptimizeOpts Any Any) AstSize -> AstSize
forall s a. s -> Getting a s a -> a
^. Getting AstSize (OptimizeOpts Any Any) AstSize
forall name a (f :: * -> *).
Functor f =>
(AstSize -> f AstSize)
-> OptimizeOpts name a -> f (OptimizeOpts name a)
UPLC.ooInlineCallsiteGrowth)
          Mod OptionFields AstSize
-> Mod OptionFields AstSize -> Mod OptionFields AstSize
forall a. Semigroup a => a -> a -> a
<> Mod OptionFields AstSize
forall a (f :: * -> *). Show a => Mod f a
showDefault
          Mod OptionFields AstSize
-> Mod OptionFields AstSize -> Mod OptionFields AstSize
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields AstSize
forall (f :: * -> *) a. String -> Mod f a
help String
"Maximum allowed AST growth for callsite inlining"
      )
  Bool
_ooPreserveLogging <-
    Mod FlagFields Bool -> Parser Bool
switch
      ( String -> Mod FlagFields Bool
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"opt-preserve-logging"
          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
"Prevent optimizations from removing or reordering log messages."
                String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
" May result in less optimized code."
            )
      )
  Bool
_ooApplyToCase <-
    Bool -> Bool -> Mod FlagFields Bool -> Parser Bool
forall a. a -> a -> Mod FlagFields a -> Parser a
flag
      Bool
True
      Bool
False
      ( String -> Mod FlagFields Bool
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"opt-no-apply-to-case"
          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
"Disable apply-to-case optimization"
      )
  Bool
_ooHoistPolyBuiltins <-
    Bool -> Bool -> Mod FlagFields Bool -> Parser Bool
forall a. a -> a -> Mod FlagFields a -> Parser a
flag
      Bool
True
      Bool
False
      ( String -> Mod FlagFields Bool
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"opt-no-hoist-polymorphic-builtins"
          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
"Disable hoist-polymorphic-builtins optimization"
      )
  Bool
_ooCertifiedOptsOnly <-
    Bool -> Bool -> Mod FlagFields Bool -> Parser Bool
forall a. a -> a -> Mod FlagFields a -> Parser a
flag
      Bool
False
      Bool
True
      ( String -> Mod FlagFields Bool
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"certified-opts-only"
          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
"Run only those optimisation passes which are certified to preserve the functional behavior of the original program."
      )
  pure UPLC.OptimizeOpts {Bool
Int
InlineHints name a
AstSize
CseWhichSubterms
_ooMaxSimplifierIterations :: Int
_ooMaxCseIterations :: Int
_ooCseWhichSubterms :: CseWhichSubterms
_ooConservativeOpts :: Bool
_ooInlineHints :: InlineHints name a
_ooInlineConstants :: Bool
_ooInlineUnconditionalGrowth :: AstSize
_ooInlineCallsiteGrowth :: AstSize
_ooPreserveLogging :: Bool
_ooApplyToCase :: Bool
_ooHoistPolyBuiltins :: Bool
_ooCertifiedOptsOnly :: Bool
_ooMaxSimplifierIterations :: Int
_ooMaxCseIterations :: Int
_ooCseWhichSubterms :: CseWhichSubterms
_ooConservativeOpts :: Bool
_ooInlineHints :: InlineHints name a
_ooInlineConstants :: Bool
_ooInlineUnconditionalGrowth :: AstSize
_ooInlineCallsiteGrowth :: AstSize
_ooPreserveLogging :: Bool
_ooApplyToCase :: Bool
_ooHoistPolyBuiltins :: Bool
_ooCertifiedOptsOnly :: Bool
..}

evalArgKindTable :: [(String, EvalArgKind)]
evalArgKindTable :: [(String, EvalArgKind)]
evalArgKindTable =
  [ (String
"prog", EvalArgKind
ArgProg)
  , (String
"data", EvalArgKind
ArgData)
  ]

optimiseEvalOpts :: Parser OptimiseEvalOpts
optimiseEvalOpts :: Parser OptimiseEvalOpts
optimiseEvalOpts =
  Bool -> [String] -> EvalArgKind -> Maybe String -> OptimiseEvalOpts
mkOpts
    (Bool
 -> [String] -> EvalArgKind -> Maybe String -> OptimiseEvalOpts)
-> Parser Bool
-> Parser
     ([String] -> EvalArgKind -> Maybe String -> OptimiseEvalOpts)
forall (f :: * -> *) a b. Functor 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
"eval"
          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
"Evaluate the program (using the CEK machine) at every stage of \
            \the optimization pipeline.  CPU and memory costs are then shown \
            \in the optimization report, alongside AST sizes, for every pass. \
            \With --certify, the same costs and sizes are also recorded in the \
            \certifier report.  Use --eval-apply or --eval-args-dir to supply \
            \arguments, if any."
      )
    Parser
  ([String] -> EvalArgKind -> Maybe String -> OptimiseEvalOpts)
-> Parser [String]
-> Parser (EvalArgKind -> Maybe String -> OptimiseEvalOpts)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser String -> Parser [String]
forall a. Parser a -> Parser [a]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many
      ( Mod OptionFields String -> Parser String
forall s. IsString s => Mod OptionFields s -> Parser s
strOption
          ( String -> Mod OptionFields String
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"eval-apply"
              Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields String
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"FILE"
              Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields String
forall (f :: * -> *) a. HasCompleter f => String -> Mod f a
action String
"file"
              Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields String
forall (f :: * -> *) a. String -> Mod f a
help
                String
"Apply program to this argument file before evaluating \
                \(repeatable).  Implies --eval."
          )
      )
    Parser (EvalArgKind -> Maybe String -> OptimiseEvalOpts)
-> Parser EvalArgKind -> Parser (Maybe String -> OptimiseEvalOpts)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReadM EvalArgKind
-> Mod OptionFields EvalArgKind -> Parser EvalArgKind
forall a. ReadM a -> Mod OptionFields a -> Parser a
option
      ((String -> Maybe EvalArgKind) -> ReadM EvalArgKind
forall a. (String -> Maybe a) -> ReadM a
maybeReader (String -> [(String, EvalArgKind)] -> Maybe EvalArgKind
forall a b. Eq a => a -> [(a, b)] -> Maybe b
`lookup` [(String, EvalArgKind)]
evalArgKindTable))
      ( String -> Mod OptionFields EvalArgKind
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"eval-arg-kind"
          Mod OptionFields EvalArgKind
-> Mod OptionFields EvalArgKind -> Mod OptionFields EvalArgKind
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields EvalArgKind
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar (String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
"|" (((String, EvalArgKind) -> String)
-> [(String, EvalArgKind)] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String, EvalArgKind) -> String
forall a b. (a, b) -> a
fst [(String, EvalArgKind)]
evalArgKindTable))
          Mod OptionFields EvalArgKind
-> Mod OptionFields EvalArgKind -> Mod OptionFields EvalArgKind
forall a. Semigroup a => a -> a -> a
<> EvalArgKind -> Mod OptionFields EvalArgKind
forall (f :: * -> *) a. HasValue f => a -> Mod f a
value EvalArgKind
ArgData
          Mod OptionFields EvalArgKind
-> Mod OptionFields EvalArgKind -> Mod OptionFields EvalArgKind
forall a. Semigroup a => a -> a -> a
<> (EvalArgKind -> String) -> Mod OptionFields EvalArgKind
forall a (f :: * -> *). (a -> String) -> Mod f a
showDefaultWith ([(String, EvalArgKind)] -> EvalArgKind -> String
forall a. Show a => [(String, a)] -> a -> String
showByTable [(String, EvalArgKind)]
evalArgKindTable)
          Mod OptionFields EvalArgKind
-> Mod OptionFields EvalArgKind -> Mod OptionFields EvalArgKind
forall a. Semigroup a => a -> a -> a
<> [String] -> Mod OptionFields EvalArgKind
forall (f :: * -> *) a. HasCompleter f => [String] -> Mod f a
completeWith (((String, EvalArgKind) -> String)
-> [(String, EvalArgKind)] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String, EvalArgKind) -> String
forall a b. (a, b) -> a
fst [(String, EvalArgKind)]
evalArgKindTable)
          Mod OptionFields EvalArgKind
-> Mod OptionFields EvalArgKind -> Mod OptionFields EvalArgKind
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields EvalArgKind
forall (f :: * -> *) a. String -> Mod f a
help
            String
"Whether --eval-apply arguments are UPLC programs or Data objects"
      )
    Parser (Maybe String -> OptimiseEvalOpts)
-> Parser (Maybe String) -> Parser OptimiseEvalOpts
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser String -> Parser (Maybe String)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional
      ( Mod OptionFields String -> Parser String
forall s. IsString s => Mod OptionFields s -> Parser s
strOption
          ( String -> Mod OptionFields String
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"eval-args-dir"
              Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields String
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"DIR"
              Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields String
forall (f :: * -> *) a. HasCompleter f => String -> Mod f a
action String
"directory"
              Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields String
forall (f :: * -> *) a. String -> Mod f a
help
                String
"Directory with per-validator argument files for blueprint \
                \optimisation.  For each validator titled T, it looks for \
                \files DIR/T/0, DIR/T/1, ... containing arguments to apply. \
                \Implies --eval."
          )
      )
  where
    -- If the user supplied any --eval-apply or --eval-args-dir,
    -- treat --eval as implied even if they didn't pass it explicitly.
    mkOpts :: Bool -> [String] -> EvalArgKind -> Maybe String -> OptimiseEvalOpts
mkOpts Bool
eval [String]
argFiles EvalArgKind
argKind Maybe String
argsDir =
      OptimiseEvalOpts
        { oeEval :: Bool
oeEval =
            Bool
eval
              Bool -> Bool -> Bool
|| Bool -> Bool
not ([String] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [String]
argFiles)
              Bool -> Bool -> Bool
|| Maybe String -> Bool
forall a. Maybe a -> Bool
isJust Maybe String
argsDir
        , oeArgFiles :: [String]
oeArgFiles = [String]
argFiles
        , oeArgKind :: EvalArgKind
oeArgKind = EvalArgKind
argKind
        , oeBlueprintArgsDir :: Maybe String
oeBlueprintArgsDir = Maybe String
argsDir
        }

optimiseOpts :: Parser (OptimiseOptions name a)
optimiseOpts :: forall name a. Parser (OptimiseOptions name a)
optimiseOpts =
  ( \(Input
inp, Format
ifmt) (Output
outp, Format
ofmt) PrintMode
mode Maybe String
cert CertifierOutputMode
certOut OptimizeOpts name a
sopts OptimiseEvalOpts
eopts ->
      Input
-> Format
-> Output
-> Format
-> PrintMode
-> Maybe String
-> CertifierOutputMode
-> OptimizeOpts name a
-> OptimiseEvalOpts
-> OptimiseOptions name a
forall name a.
Input
-> Format
-> Output
-> Format
-> PrintMode
-> Maybe String
-> CertifierOutputMode
-> OptimizeOpts name a
-> OptimiseEvalOpts
-> OptimiseOptions name a
OptimiseOptions Input
inp Format
ifmt Output
outp Format
ofmt PrintMode
mode Maybe String
cert CertifierOutputMode
certOut OptimizeOpts name a
sopts OptimiseEvalOpts
eopts
  )
    ((Input, Format)
 -> (Output, Format)
 -> PrintMode
 -> Maybe String
 -> CertifierOutputMode
 -> OptimizeOpts name a
 -> OptimiseEvalOpts
 -> OptimiseOptions name a)
-> Parser (Input, Format)
-> Parser
     ((Output, Format)
      -> PrintMode
      -> Maybe String
      -> CertifierOutputMode
      -> OptimizeOpts name a
      -> OptimiseEvalOpts
      -> OptimiseOptions name a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser (Input, Format)
inputWithFormat
    Parser
  ((Output, Format)
   -> PrintMode
   -> Maybe String
   -> CertifierOutputMode
   -> OptimizeOpts name a
   -> OptimiseEvalOpts
   -> OptimiseOptions name a)
-> Parser (Output, Format)
-> Parser
     (PrintMode
      -> Maybe String
      -> CertifierOutputMode
      -> OptimizeOpts name a
      -> OptimiseEvalOpts
      -> OptimiseOptions name a)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser (Output, Format)
outputWithFormat
    Parser
  (PrintMode
   -> Maybe String
   -> CertifierOutputMode
   -> OptimizeOpts name a
   -> OptimiseEvalOpts
   -> OptimiseOptions name a)
-> Parser PrintMode
-> Parser
     (Maybe String
      -> CertifierOutputMode
      -> OptimizeOpts name a
      -> OptimiseEvalOpts
      -> OptimiseOptions name a)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser PrintMode
printmode
    Parser
  (Maybe String
   -> CertifierOutputMode
   -> OptimizeOpts name a
   -> OptimiseEvalOpts
   -> OptimiseOptions name a)
-> Parser (Maybe String)
-> Parser
     (CertifierOutputMode
      -> OptimizeOpts name a
      -> OptimiseEvalOpts
      -> OptimiseOptions name a)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser (Maybe String)
certifier
    Parser
  (CertifierOutputMode
   -> OptimizeOpts name a
   -> OptimiseEvalOpts
   -> OptimiseOptions name a)
-> Parser CertifierOutputMode
-> Parser
     (OptimizeOpts name a -> OptimiseEvalOpts -> OptimiseOptions name a)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser CertifierOutputMode
certifierOutputMode
    Parser
  (OptimizeOpts name a -> OptimiseEvalOpts -> OptimiseOptions name a)
-> Parser (OptimizeOpts name a)
-> Parser (OptimiseEvalOpts -> OptimiseOptions name a)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser (OptimizeOpts name a)
forall name a. Parser (OptimizeOpts name a)
optimizeOpts
    Parser (OptimiseEvalOpts -> OptimiseOptions name a)
-> Parser OptimiseEvalOpts -> Parser (OptimiseOptions name a)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser OptimiseEvalOpts
optimiseEvalOpts

exampleMode :: Parser ExampleMode
exampleMode :: Parser ExampleMode
exampleMode = Parser ExampleMode
exampleAvailable Parser ExampleMode -> Parser ExampleMode -> Parser ExampleMode
forall a. Parser a -> Parser a -> Parser a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser ExampleMode
exampleSingle

exampleAvailable :: Parser ExampleMode
exampleAvailable :: Parser ExampleMode
exampleAvailable =
  ExampleMode -> Mod FlagFields ExampleMode -> Parser ExampleMode
forall a. a -> Mod FlagFields a -> Parser a
flag'
    ExampleMode
ExampleAvailable
    ( String -> Mod FlagFields ExampleMode
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"available"
        Mod FlagFields ExampleMode
-> Mod FlagFields ExampleMode -> Mod FlagFields ExampleMode
forall a. Semigroup a => a -> a -> a
<> Char -> Mod FlagFields ExampleMode
forall (f :: * -> *) a. HasName f => Char -> Mod f a
short Char
'a'
        Mod FlagFields ExampleMode
-> Mod FlagFields ExampleMode -> Mod FlagFields ExampleMode
forall a. Semigroup a => a -> a -> a
<> String -> Mod FlagFields ExampleMode
forall (f :: * -> *) a. String -> Mod f a
help String
"Show available examples"
    )

exampleName :: Parser ExampleName
exampleName :: Parser ExampleName
exampleName =
  Mod OptionFields ExampleName -> Parser ExampleName
forall s. IsString s => Mod OptionFields s -> Parser s
strOption
    ( String -> Mod OptionFields ExampleName
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"single"
        Mod OptionFields ExampleName
-> Mod OptionFields ExampleName -> Mod OptionFields ExampleName
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields ExampleName
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"NAME"
        Mod OptionFields ExampleName
-> Mod OptionFields ExampleName -> Mod OptionFields ExampleName
forall a. Semigroup a => a -> a -> a
<> Char -> Mod OptionFields ExampleName
forall (f :: * -> *) a. HasName f => Char -> Mod f a
short Char
's'
        Mod OptionFields ExampleName
-> Mod OptionFields ExampleName -> Mod OptionFields ExampleName
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields ExampleName
forall (f :: * -> *) a. String -> Mod f a
help String
"Show a single example"
    )

exampleSingle :: Parser ExampleMode
exampleSingle :: Parser ExampleMode
exampleSingle = ExampleName -> ExampleMode
ExampleSingle (ExampleName -> ExampleMode)
-> Parser ExampleName -> Parser ExampleMode
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser ExampleName
exampleName

exampleOpts :: Parser ExampleOptions
exampleOpts :: Parser ExampleOptions
exampleOpts = ExampleMode -> ExampleOptions
ExampleOptions (ExampleMode -> ExampleOptions)
-> Parser ExampleMode -> Parser ExampleOptions
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser ExampleMode
exampleMode

builtinSemanticsVariantTable :: [(String, BuiltinSemanticsVariant DefaultFun)]
builtinSemanticsVariantTable :: [(String, BuiltinSemanticsVariant DefaultFun)]
builtinSemanticsVariantTable =
  [ (String
"A", BuiltinSemanticsVariant DefaultFun
DefaultFunSemanticsVariantA)
  , (String
"B", BuiltinSemanticsVariant DefaultFun
DefaultFunSemanticsVariantB)
  , (String
"C", BuiltinSemanticsVariant DefaultFun
DefaultFunSemanticsVariantC)
  , (String
"D", BuiltinSemanticsVariant DefaultFun
DefaultFunSemanticsVariantD)
  , (String
"E", BuiltinSemanticsVariant DefaultFun
DefaultFunSemanticsVariantE)
  ]

builtinSemanticsVariantReader :: String -> Maybe (BuiltinSemanticsVariant DefaultFun)
builtinSemanticsVariantReader :: String -> Maybe (BuiltinSemanticsVariant DefaultFun)
builtinSemanticsVariantReader = (String
-> [(String, BuiltinSemanticsVariant DefaultFun)]
-> Maybe (BuiltinSemanticsVariant DefaultFun)
forall a b. Eq a => a -> [(a, b)] -> Maybe b
`lookup` [(String, BuiltinSemanticsVariant DefaultFun)]
builtinSemanticsVariantTable)

-- This is used to make the help message show you what you actually need to type.
showBuiltinSemanticsVariant :: BuiltinSemanticsVariant DefaultFun -> String
showBuiltinSemanticsVariant :: BuiltinSemanticsVariant DefaultFun -> String
showBuiltinSemanticsVariant = [(String, BuiltinSemanticsVariant DefaultFun)]
-> BuiltinSemanticsVariant DefaultFun -> String
forall a. Show a => [(String, a)] -> a -> String
showByTable [(String, BuiltinSemanticsVariant DefaultFun)]
builtinSemanticsVariantTable

builtinSemanticsVariant :: Parser (BuiltinSemanticsVariant DefaultFun)
builtinSemanticsVariant :: Parser (BuiltinSemanticsVariant DefaultFun)
builtinSemanticsVariant =
  ReadM (BuiltinSemanticsVariant DefaultFun)
-> Mod OptionFields (BuiltinSemanticsVariant DefaultFun)
-> Parser (BuiltinSemanticsVariant DefaultFun)
forall a. ReadM a -> Mod OptionFields a -> Parser a
option
    ((String -> Maybe (BuiltinSemanticsVariant DefaultFun))
-> ReadM (BuiltinSemanticsVariant DefaultFun)
forall a. (String -> Maybe a) -> ReadM a
maybeReader String -> Maybe (BuiltinSemanticsVariant DefaultFun)
builtinSemanticsVariantReader)
    ( String -> Mod OptionFields (BuiltinSemanticsVariant DefaultFun)
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"builtin-semantics-variant"
        Mod OptionFields (BuiltinSemanticsVariant DefaultFun)
-> Mod OptionFields (BuiltinSemanticsVariant DefaultFun)
-> Mod OptionFields (BuiltinSemanticsVariant DefaultFun)
forall a. Semigroup a => a -> a -> a
<> Char -> Mod OptionFields (BuiltinSemanticsVariant DefaultFun)
forall (f :: * -> *) a. HasName f => Char -> Mod f a
short Char
'S'
        Mod OptionFields (BuiltinSemanticsVariant DefaultFun)
-> Mod OptionFields (BuiltinSemanticsVariant DefaultFun)
-> Mod OptionFields (BuiltinSemanticsVariant DefaultFun)
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields (BuiltinSemanticsVariant DefaultFun)
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"VARIANT"
        Mod OptionFields (BuiltinSemanticsVariant DefaultFun)
-> Mod OptionFields (BuiltinSemanticsVariant DefaultFun)
-> Mod OptionFields (BuiltinSemanticsVariant DefaultFun)
forall a. Semigroup a => a -> a -> a
<> BuiltinSemanticsVariant DefaultFun
-> Mod OptionFields (BuiltinSemanticsVariant DefaultFun)
forall (f :: * -> *) a. HasValue f => a -> Mod f a
value BuiltinSemanticsVariant DefaultFun
DefaultFunSemanticsVariantE
        Mod OptionFields (BuiltinSemanticsVariant DefaultFun)
-> Mod OptionFields (BuiltinSemanticsVariant DefaultFun)
-> Mod OptionFields (BuiltinSemanticsVariant DefaultFun)
forall a. Semigroup a => a -> a -> a
<> (BuiltinSemanticsVariant DefaultFun -> String)
-> Mod OptionFields (BuiltinSemanticsVariant DefaultFun)
forall a (f :: * -> *). (a -> String) -> Mod f a
showDefaultWith BuiltinSemanticsVariant DefaultFun -> String
showBuiltinSemanticsVariant
        Mod OptionFields (BuiltinSemanticsVariant DefaultFun)
-> Mod OptionFields (BuiltinSemanticsVariant DefaultFun)
-> Mod OptionFields (BuiltinSemanticsVariant DefaultFun)
forall a. Semigroup a => a -> a -> a
<> [String] -> Mod OptionFields (BuiltinSemanticsVariant DefaultFun)
forall (f :: * -> *) a. HasCompleter f => [String] -> Mod f a
completeWith (((String, BuiltinSemanticsVariant DefaultFun) -> String)
-> [(String, BuiltinSemanticsVariant DefaultFun)] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String, BuiltinSemanticsVariant DefaultFun) -> String
forall a b. (a, b) -> a
fst [(String, BuiltinSemanticsVariant DefaultFun)]
builtinSemanticsVariantTable)
        Mod OptionFields (BuiltinSemanticsVariant DefaultFun)
-> Mod OptionFields (BuiltinSemanticsVariant DefaultFun)
-> Mod OptionFields (BuiltinSemanticsVariant DefaultFun)
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields (BuiltinSemanticsVariant DefaultFun)
forall (f :: * -> *) a. String -> Mod f a
help
          ( String
"Builtin semantics variant: "
              String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
", " [String
name String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
" -> " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> BuiltinSemanticsVariant DefaultFun -> String
forall a. Show a => a -> String
show BuiltinSemanticsVariant DefaultFun
v | (String
name, BuiltinSemanticsVariant DefaultFun
v) <- [(String, BuiltinSemanticsVariant DefaultFun)]
builtinSemanticsVariantTable]
          )
    )

-- Specialised parsers for PLC (TPLC), which only supports textual and Flat
-- formats. The @serialised@, @hex@ and @blueprint@ formats are not implemented
-- for TPLC (the 'ProgramLike PlcProg' instance's
-- 'loadASTfromSerialised'/'loadASTfromHex'/'serialiseAST' are unimplemented, and
-- 'runErase'/'runOptimisations' reject them), so we must not offer them.

plcFormatTable :: [(String, Maybe String, Format)]
plcFormatTable :: [(String, Maybe String, Format)]
plcFormatTable =
  [ (String
"textual", Maybe String
forall a. Maybe a
Nothing, Format
Textual)
  , (String
"flat-named", String -> Maybe String
forall a. a -> Maybe a
Just String
"names", AstNameType -> Format
Flat AstNameType
Named)
  , (String
"flat", String -> Maybe String
forall a. a -> Maybe a
Just String
"de Bruijn indices", AstNameType -> Format
Flat AstNameType
DeBruijn)
  , (String
"flat-deBruijn", String -> Maybe String
forall a. a -> Maybe a
Just String
"alias for flat", AstNameType -> Format
Flat AstNameType
DeBruijn)
  , (String
"flat-namedDeBruijn", String -> Maybe String
forall a. a -> Maybe a
Just String
"names and de Bruijn indices", AstNameType -> Format
Flat AstNameType
NamedDeBruijn)
  ]

plcFormatHelp :: String
plcFormatHelp :: String
plcFormatHelp =
  String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate
    String
", "
    [String -> (String -> String) -> Maybe String -> String
forall b a. b -> (a -> b) -> Maybe a -> b
maybe String
name (\String
d -> String
name String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
" (" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
d String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
")") Maybe String
mdesc | (String
name, Maybe String
mdesc, Format
_) <- [(String, Maybe String, Format)]
plcFormatTable]

plcFormatReader :: String -> Maybe Format
plcFormatReader :: String -> Maybe Format
plcFormatReader String
s = [Format] -> Maybe Format
forall a. [a] -> Maybe a
listToMaybe [Format
v | (String
name, Maybe String
_, Format
v) <- [(String, Maybe String, Format)]
plcFormatTable, String
name String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
s]

plcFormatNames :: [String]
plcFormatNames :: [String]
plcFormatNames = [String
name | (String
name, Maybe String
_, Format
_) <- [(String, Maybe String, Format)]
plcFormatTable]

{-| The @--if@ option for @plc@, without a default so the format can be deduced
from the file extension when it isn't given. -}
plcInputFormatOptional :: Parser (Maybe Format)
plcInputFormatOptional :: Parser (Maybe Format)
plcInputFormatOptional =
  Parser Format -> Parser (Maybe Format)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (Parser Format -> Parser (Maybe Format))
-> Parser Format -> Parser (Maybe Format)
forall a b. (a -> b) -> a -> b
$
    ReadM Format -> Mod OptionFields Format -> Parser Format
forall a. ReadM a -> Mod OptionFields a -> Parser a
option
      ((String -> Maybe Format) -> ReadM Format
forall a. (String -> Maybe a) -> ReadM a
maybeReader String -> Maybe Format
plcFormatReader)
      ( String -> Mod OptionFields Format
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"if"
          Mod OptionFields Format
-> Mod OptionFields Format -> Mod OptionFields Format
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields Format
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"input-format"
          Mod OptionFields Format
-> Mod OptionFields Format -> Mod OptionFields Format
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields Format
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"FORMAT"
          Mod OptionFields Format
-> Mod OptionFields Format -> Mod OptionFields Format
forall a. Semigroup a => a -> a -> a
<> [String] -> Mod OptionFields Format
forall (f :: * -> *) a. HasCompleter f => [String] -> Mod f a
completeWith [String]
plcFormatNames
          Mod OptionFields Format
-> Mod OptionFields Format -> Mod OptionFields Format
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields Format
forall (f :: * -> *) a. String -> Mod f a
help (String -> String -> String -> String
formatOptionHelp String
"Input" String
plcFormatHelp (String -> [(String, Maybe String, Format)] -> String
extensionDeductionNote String
".plc" [(String, Maybe String, Format)]
plcFormatTable))
      )

{-| The @--of@ option for @plc@, without a default so the format can be deduced
from the file extension when it isn't given. -}
plcOutputFormatOptional :: Parser (Maybe Format)
plcOutputFormatOptional :: Parser (Maybe Format)
plcOutputFormatOptional =
  Parser Format -> Parser (Maybe Format)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (Parser Format -> Parser (Maybe Format))
-> Parser Format -> Parser (Maybe Format)
forall a b. (a -> b) -> a -> b
$
    ReadM Format -> Mod OptionFields Format -> Parser Format
forall a. ReadM a -> Mod OptionFields a -> Parser a
option
      ((String -> Maybe Format) -> ReadM Format
forall a. (String -> Maybe a) -> ReadM a
maybeReader String -> Maybe Format
plcFormatReader)
      ( String -> Mod OptionFields Format
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"of"
          Mod OptionFields Format
-> Mod OptionFields Format -> Mod OptionFields Format
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields Format
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"output-format"
          Mod OptionFields Format
-> Mod OptionFields Format -> Mod OptionFields Format
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields Format
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"FORMAT"
          Mod OptionFields Format
-> Mod OptionFields Format -> Mod OptionFields Format
forall a. Semigroup a => a -> a -> a
<> [String] -> Mod OptionFields Format
forall (f :: * -> *) a. HasCompleter f => [String] -> Mod f a
completeWith [String]
plcFormatNames
          Mod OptionFields Format
-> Mod OptionFields Format -> Mod OptionFields Format
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields Format
forall (f :: * -> *) a. String -> Mod f a
help (String -> String -> String -> String
formatOptionHelp String
"Output" String
plcFormatHelp (String -> [(String, Maybe String, Format)] -> String
extensionDeductionNote String
".plc" [(String, Maybe String, Format)]
plcFormatTable))
      )

plcInputWithFormat :: Parser (Input, Format)
plcInputWithFormat :: Parser (Input, Format)
plcInputWithFormat =
  (\Input
inp Maybe Format
mfmt -> (Input
inp, String -> [Format] -> Maybe Format -> Input -> Format
resolveInputFormat String
".plc" ([(String, Maybe String, Format)] -> [Format]
supportedFormats [(String, Maybe String, Format)]
plcFormatTable) Maybe Format
mfmt Input
inp))
    (Input -> Maybe Format -> (Input, Format))
-> Parser Input -> Parser (Maybe Format -> (Input, Format))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Input
input
    Parser (Maybe Format -> (Input, Format))
-> Parser (Maybe Format) -> Parser (Input, Format)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser (Maybe Format)
plcInputFormatOptional

plcFilesWithFormats :: Parser [(FilePath, Format)]
plcFilesWithFormats :: Parser [(String, Format)]
plcFilesWithFormats =
  ( \[String]
fs Maybe Format
mfmt -> [(String
f, String -> [Format] -> Maybe Format -> Input -> Format
resolveInputFormat String
".plc" ([(String, Maybe String, Format)] -> [Format]
supportedFormats [(String, Maybe String, Format)]
plcFormatTable) Maybe Format
mfmt (String -> Input
FileInput String
f)) | String
f <- [String]
fs]
  )
    ([String] -> Maybe Format -> [(String, Format)])
-> Parser [String] -> Parser (Maybe Format -> [(String, Format)])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser [String]
files
    Parser (Maybe Format -> [(String, Format)])
-> Parser (Maybe Format) -> Parser [(String, Format)]
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser (Maybe Format)
plcInputFormatOptional

plcOutputWithFormat :: Parser (Output, Format)
plcOutputWithFormat :: Parser (Output, Format)
plcOutputWithFormat =
  (\Output
outp Maybe Format
mfmt -> (Output
outp, String -> [Format] -> Maybe Format -> Output -> Format
resolveOutputFormat String
".plc" ([(String, Maybe String, Format)] -> [Format]
supportedFormats [(String, Maybe String, Format)]
plcFormatTable) Maybe Format
mfmt Output
outp))
    (Output -> Maybe Format -> (Output, Format))
-> Parser Output -> Parser (Maybe Format -> (Output, Format))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Output
output
    Parser (Maybe Format -> (Output, Format))
-> Parser (Maybe Format) -> Parser (Output, Format)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser (Maybe Format)
plcOutputFormatOptional

plcApplyOpts :: Parser ApplyOptions
plcApplyOpts :: Parser ApplyOptions
plcApplyOpts =
  (\[(String, Format)]
fps (Output
outp, Format
ofmt) PrintMode
mode -> [(String, Format)] -> Output -> Format -> PrintMode -> ApplyOptions
ApplyOptions [(String, Format)]
fps Output
outp Format
ofmt PrintMode
mode)
    ([(String, Format)]
 -> (Output, Format) -> PrintMode -> ApplyOptions)
-> Parser [(String, Format)]
-> Parser ((Output, Format) -> PrintMode -> ApplyOptions)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser [(String, Format)]
plcFilesWithFormats
    Parser ((Output, Format) -> PrintMode -> ApplyOptions)
-> Parser (Output, Format) -> Parser (PrintMode -> ApplyOptions)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser (Output, Format)
plcOutputWithFormat
    Parser (PrintMode -> ApplyOptions)
-> Parser PrintMode -> Parser ApplyOptions
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser PrintMode
printmode

plcConvertOpts :: Parser ConvertOptions
plcConvertOpts :: Parser ConvertOptions
plcConvertOpts =
  (\(Input
inp, Format
ifmt) (Output
outp, Format
ofmt) PrintMode
mode -> Input -> Format -> Output -> Format -> PrintMode -> ConvertOptions
ConvertOptions Input
inp Format
ifmt Output
outp Format
ofmt PrintMode
mode)
    ((Input, Format)
 -> (Output, Format) -> PrintMode -> ConvertOptions)
-> Parser (Input, Format)
-> Parser ((Output, Format) -> PrintMode -> ConvertOptions)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser (Input, Format)
plcInputWithFormat
    Parser ((Output, Format) -> PrintMode -> ConvertOptions)
-> Parser (Output, Format) -> Parser (PrintMode -> ConvertOptions)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser (Output, Format)
plcOutputWithFormat
    Parser (PrintMode -> ConvertOptions)
-> Parser PrintMode -> Parser ConvertOptions
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser PrintMode
printmode

plcOptimiseOpts :: Parser (OptimiseOptions name a)
plcOptimiseOpts :: forall name a. Parser (OptimiseOptions name a)
plcOptimiseOpts =
  ( \(Input
inp, Format
ifmt) (Output
outp, Format
ofmt) PrintMode
mode Maybe String
cert CertifierOutputMode
certOut OptimizeOpts name a
sopts OptimiseEvalOpts
eopts ->
      Input
-> Format
-> Output
-> Format
-> PrintMode
-> Maybe String
-> CertifierOutputMode
-> OptimizeOpts name a
-> OptimiseEvalOpts
-> OptimiseOptions name a
forall name a.
Input
-> Format
-> Output
-> Format
-> PrintMode
-> Maybe String
-> CertifierOutputMode
-> OptimizeOpts name a
-> OptimiseEvalOpts
-> OptimiseOptions name a
OptimiseOptions Input
inp Format
ifmt Output
outp Format
ofmt PrintMode
mode Maybe String
cert CertifierOutputMode
certOut OptimizeOpts name a
sopts OptimiseEvalOpts
eopts
  )
    ((Input, Format)
 -> (Output, Format)
 -> PrintMode
 -> Maybe String
 -> CertifierOutputMode
 -> OptimizeOpts name a
 -> OptimiseEvalOpts
 -> OptimiseOptions name a)
-> Parser (Input, Format)
-> Parser
     ((Output, Format)
      -> PrintMode
      -> Maybe String
      -> CertifierOutputMode
      -> OptimizeOpts name a
      -> OptimiseEvalOpts
      -> OptimiseOptions name a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser (Input, Format)
plcInputWithFormat
    Parser
  ((Output, Format)
   -> PrintMode
   -> Maybe String
   -> CertifierOutputMode
   -> OptimizeOpts name a
   -> OptimiseEvalOpts
   -> OptimiseOptions name a)
-> Parser (Output, Format)
-> Parser
     (PrintMode
      -> Maybe String
      -> CertifierOutputMode
      -> OptimizeOpts name a
      -> OptimiseEvalOpts
      -> OptimiseOptions name a)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser (Output, Format)
plcOutputWithFormat
    Parser
  (PrintMode
   -> Maybe String
   -> CertifierOutputMode
   -> OptimizeOpts name a
   -> OptimiseEvalOpts
   -> OptimiseOptions name a)
-> Parser PrintMode
-> Parser
     (Maybe String
      -> CertifierOutputMode
      -> OptimizeOpts name a
      -> OptimiseEvalOpts
      -> OptimiseOptions name a)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser PrintMode
printmode
    Parser
  (Maybe String
   -> CertifierOutputMode
   -> OptimizeOpts name a
   -> OptimiseEvalOpts
   -> OptimiseOptions name a)
-> Parser (Maybe String)
-> Parser
     (CertifierOutputMode
      -> OptimizeOpts name a
      -> OptimiseEvalOpts
      -> OptimiseOptions name a)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser (Maybe String)
certifier
    Parser
  (CertifierOutputMode
   -> OptimizeOpts name a
   -> OptimiseEvalOpts
   -> OptimiseOptions name a)
-> Parser CertifierOutputMode
-> Parser
     (OptimizeOpts name a -> OptimiseEvalOpts -> OptimiseOptions name a)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser CertifierOutputMode
certifierOutputMode
    Parser
  (OptimizeOpts name a -> OptimiseEvalOpts -> OptimiseOptions name a)
-> Parser (OptimizeOpts name a)
-> Parser (OptimiseEvalOpts -> OptimiseOptions name a)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser (OptimizeOpts name a)
forall name a. Parser (OptimizeOpts name a)
optimizeOpts
    Parser (OptimiseEvalOpts -> OptimiseOptions name a)
-> Parser OptimiseEvalOpts -> Parser (OptimiseOptions name a)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser OptimiseEvalOpts
optimiseEvalOpts

-- Specialised parsers for PIR, which only supports ASTs over the Textual and
-- Named types.

pirFormatTable :: [(String, Maybe String, PirFormat)]
pirFormatTable :: [(String, Maybe String, PirFormat)]
pirFormatTable =
  [ (String
"textual", Maybe String
forall a. Maybe a
Nothing, PirFormat
TextualPir)
  , (String
"flat-named", String -> Maybe String
forall a. a -> Maybe a
Just String
"names", PirFormat
FlatNamed)
  ]

pirFormatHelp :: String
pirFormatHelp :: String
pirFormatHelp =
  String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate
    String
" or "
    [String -> (String -> String) -> Maybe String -> String
forall b a. b -> (a -> b) -> Maybe a -> b
maybe String
name (\String
d -> String
name String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
" (" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
d String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
")") Maybe String
mdesc | (String
name, Maybe String
mdesc, PirFormat
_) <- [(String, Maybe String, PirFormat)]
pirFormatTable]

pirFormatReader :: String -> Maybe PirFormat
pirFormatReader :: String -> Maybe PirFormat
pirFormatReader String
s = [PirFormat] -> Maybe PirFormat
forall a. [a] -> Maybe a
listToMaybe [PirFormat
v | (String
name, Maybe String
_, PirFormat
v) <- [(String, Maybe String, PirFormat)]
pirFormatTable, String
name String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
s]

pirFormatNames :: [String]
pirFormatNames :: [String]
pirFormatNames = [String
name | (String
name, Maybe String
_, PirFormat
_) <- [(String, Maybe String, PirFormat)]
pirFormatTable]

-- File extensions recognised for PIR: its own textual extension, plus flat
-- encoding (PIR doesn't support de Bruijn names, so unlike UPLC/PLC there's
-- only one flat variant to recognise).
pirExtensionTable :: [(String, PirFormat)]
pirExtensionTable :: [(String, PirFormat)]
pirExtensionTable =
  [ (String
".pir", PirFormat
TextualPir)
  , (String
".flat", PirFormat
FlatNamed)
  ]

{-| Guess the PIR format from a file name's extension. Returns 'Nothing' for
an unrecognised extension, in which case callers fall back to 'TextualPir'. -}
pirFormatFromExtension :: FilePath -> Maybe PirFormat
pirFormatFromExtension :: String -> Maybe PirFormat
pirFormatFromExtension String
path = String -> [(String, PirFormat)] -> Maybe PirFormat
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup (String -> String
takeExtension String
path) [(String, PirFormat)]
pirExtensionTable

-- The parenthetical explanation embedded in the PIR @--if@/@--of@ "default:"
-- help text, shared between the input and output variants.
pirExtensionDeductionNote :: String
pirExtensionDeductionNote :: String
pirExtensionDeductionNote =
  String -> String
extensionDeductionSentence
    (String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
", " [String
ext String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
" -> " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> PirFormat -> String
forall a. Show a => a -> String
show PirFormat
fmt | (String
ext, PirFormat
fmt) <- [(String, PirFormat)]
pirExtensionTable])

{-| Work out which PIR format to use. An explicit @--if@/@--of@ always wins;
otherwise the format is deduced from the file's extension, falling back to
'TextualPir' for stdin/stdout or an unrecognised extension. -}
resolvePirInputFormat :: Maybe PirFormat -> Input -> PirFormat
resolvePirInputFormat :: Maybe PirFormat -> Input -> PirFormat
resolvePirInputFormat = (String -> Maybe PirFormat)
-> PirFormat -> Maybe PirFormat -> Input -> PirFormat
forall fmt.
(String -> Maybe fmt) -> fmt -> Maybe fmt -> Input -> fmt
deduceInputFormat String -> Maybe PirFormat
pirFormatFromExtension PirFormat
TextualPir

-- | The output-format counterpart of 'resolvePirInputFormat'.
resolvePirOutputFormat :: Maybe PirFormat -> Output -> PirFormat
resolvePirOutputFormat :: Maybe PirFormat -> Output -> PirFormat
resolvePirOutputFormat = (String -> Maybe PirFormat)
-> PirFormat -> Maybe PirFormat -> Output -> PirFormat
forall fmt.
(String -> Maybe fmt) -> fmt -> Maybe fmt -> Output -> fmt
deduceOutputFormat String -> Maybe PirFormat
pirFormatFromExtension PirFormat
TextualPir

{-| The @--if@ option for @pir@, without a default so the format can be deduced
from the file extension when it isn't given. -}
pPirInputFormatOptional :: Parser (Maybe PirFormat)
pPirInputFormatOptional :: Parser (Maybe PirFormat)
pPirInputFormatOptional =
  Parser PirFormat -> Parser (Maybe PirFormat)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (Parser PirFormat -> Parser (Maybe PirFormat))
-> Parser PirFormat -> Parser (Maybe PirFormat)
forall a b. (a -> b) -> a -> b
$
    ReadM PirFormat -> Mod OptionFields PirFormat -> Parser PirFormat
forall a. ReadM a -> Mod OptionFields a -> Parser a
option
      ((String -> Maybe PirFormat) -> ReadM PirFormat
forall a. (String -> Maybe a) -> ReadM a
maybeReader String -> Maybe PirFormat
pirFormatReader)
      ( String -> Mod OptionFields PirFormat
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"if"
          Mod OptionFields PirFormat
-> Mod OptionFields PirFormat -> Mod OptionFields PirFormat
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields PirFormat
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"input-format"
          Mod OptionFields PirFormat
-> Mod OptionFields PirFormat -> Mod OptionFields PirFormat
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields PirFormat
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"PIR-FORMAT"
          Mod OptionFields PirFormat
-> Mod OptionFields PirFormat -> Mod OptionFields PirFormat
forall a. Semigroup a => a -> a -> a
<> [String] -> Mod OptionFields PirFormat
forall (f :: * -> *) a. HasCompleter f => [String] -> Mod f a
completeWith [String]
pirFormatNames
          Mod OptionFields PirFormat
-> Mod OptionFields PirFormat -> Mod OptionFields PirFormat
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields PirFormat
forall (f :: * -> *) a. String -> Mod f a
help (String -> String -> String -> String
formatOptionHelp String
"Input" String
pirFormatHelp String
pirExtensionDeductionNote)
      )

{-| The @--of@ option for @pir@, without a default so the format can be deduced
from the file extension when it isn't given. -}
pPirOutputFormatOptional :: Parser (Maybe PirFormat)
pPirOutputFormatOptional :: Parser (Maybe PirFormat)
pPirOutputFormatOptional =
  Parser PirFormat -> Parser (Maybe PirFormat)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (Parser PirFormat -> Parser (Maybe PirFormat))
-> Parser PirFormat -> Parser (Maybe PirFormat)
forall a b. (a -> b) -> a -> b
$
    ReadM PirFormat -> Mod OptionFields PirFormat -> Parser PirFormat
forall a. ReadM a -> Mod OptionFields a -> Parser a
option
      ((String -> Maybe PirFormat) -> ReadM PirFormat
forall a. (String -> Maybe a) -> ReadM a
maybeReader String -> Maybe PirFormat
pirFormatReader)
      ( String -> Mod OptionFields PirFormat
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"of"
          Mod OptionFields PirFormat
-> Mod OptionFields PirFormat -> Mod OptionFields PirFormat
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields PirFormat
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"output-format"
          Mod OptionFields PirFormat
-> Mod OptionFields PirFormat -> Mod OptionFields PirFormat
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields PirFormat
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"PIR-FORMAT"
          Mod OptionFields PirFormat
-> Mod OptionFields PirFormat -> Mod OptionFields PirFormat
forall a. Semigroup a => a -> a -> a
<> [String] -> Mod OptionFields PirFormat
forall (f :: * -> *) a. HasCompleter f => [String] -> Mod f a
completeWith [String]
pirFormatNames
          Mod OptionFields PirFormat
-> Mod OptionFields PirFormat -> Mod OptionFields PirFormat
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields PirFormat
forall (f :: * -> *) a. String -> Mod f a
help (String -> String -> String -> String
formatOptionHelp String
"Output" String
pirFormatHelp String
pirExtensionDeductionNote)
      )

{-| An input stream together with its PIR format, deducing the format from the
file extension when @--if@ is not given. See 'resolvePirInputFormat'. -}
pPirInputWithFormat :: Parser (Input, PirFormat)
pPirInputWithFormat :: Parser (Input, PirFormat)
pPirInputWithFormat =
  (\Input
inp Maybe PirFormat
mfmt -> (Input
inp, Maybe PirFormat -> Input -> PirFormat
resolvePirInputFormat Maybe PirFormat
mfmt Input
inp))
    (Input -> Maybe PirFormat -> (Input, PirFormat))
-> Parser Input -> Parser (Maybe PirFormat -> (Input, PirFormat))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Input
input
    Parser (Maybe PirFormat -> (Input, PirFormat))
-> Parser (Maybe PirFormat) -> Parser (Input, PirFormat)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser (Maybe PirFormat)
pPirInputFormatOptional

{-| An output stream together with its PIR format, deducing the format from
the file extension when @--of@ is not given. See 'resolvePirOutputFormat'. -}
pPirOutputWithFormat :: Parser (Output, PirFormat)
pPirOutputWithFormat :: Parser (Output, PirFormat)
pPirOutputWithFormat =
  (\Output
outp Maybe PirFormat
mfmt -> (Output
outp, Maybe PirFormat -> Output -> PirFormat
resolvePirOutputFormat Maybe PirFormat
mfmt Output
outp))
    (Output -> Maybe PirFormat -> (Output, PirFormat))
-> Parser Output -> Parser (Maybe PirFormat -> (Output, PirFormat))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Output
output
    Parser (Maybe PirFormat -> (Output, PirFormat))
-> Parser (Maybe PirFormat) -> Parser (Output, PirFormat)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser (Maybe PirFormat)
pPirOutputFormatOptional

-- Which language: PLC or UPLC?

languageTable :: [(String, Language)]
languageTable :: [(String, Language)]
languageTable =
  [ (String
"plc", Language
PLC)
  , (String
"uplc", Language
UPLC)
  ]

languageReader :: String -> Maybe Language
languageReader :: String -> Maybe Language
languageReader = (String -> [(String, Language)] -> Maybe Language
forall a b. Eq a => a -> [(a, b)] -> Maybe b
`lookup` [(String, Language)]
languageTable)

pLanguage :: Parser Language
pLanguage :: Parser Language
pLanguage =
  ReadM Language -> Mod OptionFields Language -> Parser Language
forall a. ReadM a -> Mod OptionFields a -> Parser a
option
    ((String -> Maybe Language) -> ReadM Language
forall a. (String -> Maybe a) -> ReadM a
maybeReader String -> Maybe Language
languageReader)
    ( String -> Mod OptionFields Language
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"language"
        Mod OptionFields Language
-> Mod OptionFields Language -> Mod OptionFields Language
forall a. Semigroup a => a -> a -> a
<> Char -> Mod OptionFields Language
forall (f :: * -> *) a. HasName f => Char -> Mod f a
short Char
'l'
        Mod OptionFields Language
-> Mod OptionFields Language -> Mod OptionFields Language
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields Language
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"LANGUAGE"
        Mod OptionFields Language
-> Mod OptionFields Language -> Mod OptionFields Language
forall a. Semigroup a => a -> a -> a
<> Language -> Mod OptionFields Language
forall (f :: * -> *) a. HasValue f => a -> Mod f a
value Language
UPLC
        Mod OptionFields Language
-> Mod OptionFields Language -> Mod OptionFields Language
forall a. Semigroup a => a -> a -> a
<> (Language -> String) -> Mod OptionFields Language
forall a (f :: * -> *). (a -> String) -> Mod f a
showDefaultWith ([(String, Language)] -> Language -> String
forall a. Show a => [(String, a)] -> a -> String
showByTable [(String, Language)]
languageTable)
        Mod OptionFields Language
-> Mod OptionFields Language -> Mod OptionFields Language
forall a. Semigroup a => a -> a -> a
<> [String] -> Mod OptionFields Language
forall (f :: * -> *) a. HasCompleter f => [String] -> Mod f a
completeWith (((String, Language) -> String) -> [(String, Language)] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String, Language) -> String
forall a b. (a, b) -> a
fst [(String, Language)]
languageTable)
        Mod OptionFields Language
-> Mod OptionFields Language -> Mod OptionFields Language
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields Language
forall (f :: * -> *) a. String -> Mod f a
help (String
"Target language: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
" or " (((String, Language) -> String) -> [(String, Language)] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String, Language) -> String
forall a b. (a, b) -> a
fst [(String, Language)]
languageTable))
    )