-- | Convenient common interface for command line Futhark compilers.
-- Using this module ensures that all compilers take the same options.
-- A small amount of flexibility is provided for backend-specific
-- options.
module Futhark.Compiler.CLI
  ( compilerMain,
    CompilerOption,
    CompilerMode (..),
    module Futhark.Pipeline,
    module Futhark.Compiler,
  )
where

import Control.Monad
import Data.Maybe
import Futhark.Compiler
import Futhark.IR (Name, Prog, nameFromString)
import Futhark.IR.SOACS (SOACS)
import Futhark.Pipeline
import Futhark.Util.Options
import System.FilePath
import System.IO

-- | Run a parameterised Futhark compiler, where @cfg@ is a user-given
-- configuration type.  Call this from @main@.
compilerMain ::
  -- | Initial configuration.
  cfg ->
  -- | Options that affect the configuration.
  [CompilerOption cfg] ->
  -- | The short action name (e.g. "compile to C").
  String ->
  -- | The longer action description.
  String ->
  -- | The pipeline to use.
  Pipeline SOACS lore ->
  -- | The action to take on the result of the pipeline.
  ( FutharkConfig ->
    cfg ->
    CompilerMode ->
    FilePath ->
    Prog lore ->
    FutharkM ()
  ) ->
  -- | Program name
  String ->
  -- | Command line arguments.
  [String] ->
  IO ()
compilerMain :: forall cfg lore.
cfg
-> [CompilerOption cfg]
-> String
-> String
-> Pipeline SOACS lore
-> (FutharkConfig
    -> cfg -> CompilerMode -> String -> Prog lore -> FutharkM ())
-> String
-> [String]
-> IO ()
compilerMain cfg
cfg [CompilerOption cfg]
cfg_opts String
name String
desc Pipeline SOACS lore
pipeline FutharkConfig
-> cfg -> CompilerMode -> String -> Prog lore -> FutharkM ()
doIt String
prog [String]
args = do
  Handle -> TextEncoding -> IO ()
hSetEncoding Handle
stdout TextEncoding
utf8
  Handle -> TextEncoding -> IO ()
hSetEncoding Handle
stderr TextEncoding
utf8
  CompilerConfig cfg
-> [FunOptDescr (CompilerConfig cfg)]
-> String
-> ([String] -> CompilerConfig cfg -> Maybe (IO ()))
-> String
-> [String]
-> IO ()
forall cfg.
cfg
-> [FunOptDescr cfg]
-> String
-> ([String] -> cfg -> Maybe (IO ()))
-> String
-> [String]
-> IO ()
mainWithOptions
    (cfg -> CompilerConfig cfg
forall cfg. cfg -> CompilerConfig cfg
newCompilerConfig cfg
cfg)
    ([FunOptDescr (CompilerConfig cfg)]
forall cfg. [CoreCompilerOption cfg]
commandLineOptions [FunOptDescr (CompilerConfig cfg)]
-> [FunOptDescr (CompilerConfig cfg)]
-> [FunOptDescr (CompilerConfig cfg)]
forall a. [a] -> [a] -> [a]
++ (CompilerOption cfg -> FunOptDescr (CompilerConfig cfg))
-> [CompilerOption cfg] -> [FunOptDescr (CompilerConfig cfg)]
forall a b. (a -> b) -> [a] -> [b]
map CompilerOption cfg -> FunOptDescr (CompilerConfig cfg)
forall cfg. CompilerOption cfg -> CoreCompilerOption cfg
wrapOption [CompilerOption cfg]
cfg_opts)
    String
"options... <program.fut>"
    [String] -> CompilerConfig cfg -> Maybe (IO ())
inspectNonOptions
    String
prog
    [String]
args
  where
    inspectNonOptions :: [String] -> CompilerConfig cfg -> Maybe (IO ())
inspectNonOptions [String
file] CompilerConfig cfg
config = IO () -> Maybe (IO ())
forall a. a -> Maybe a
Just (IO () -> Maybe (IO ())) -> IO () -> Maybe (IO ())
forall a b. (a -> b) -> a -> b
$ CompilerConfig cfg -> String -> IO ()
compile CompilerConfig cfg
config String
file
    inspectNonOptions [String]
_ CompilerConfig cfg
_ = Maybe (IO ())
forall a. Maybe a
Nothing

    compile :: CompilerConfig cfg -> String -> IO ()
compile CompilerConfig cfg
config String
filepath =
      FutharkConfig
-> Pipeline SOACS lore -> Action lore -> String -> IO ()
forall lore.
FutharkConfig
-> Pipeline SOACS lore -> Action lore -> String -> IO ()
runCompilerOnProgram
        (CompilerConfig cfg -> FutharkConfig
forall cfg. CompilerConfig cfg -> FutharkConfig
futharkConfig CompilerConfig cfg
config)
        Pipeline SOACS lore
pipeline
        (CompilerConfig cfg -> String -> Action lore
action CompilerConfig cfg
config String
filepath)
        String
filepath

    action :: CompilerConfig cfg -> String -> Action lore
action CompilerConfig cfg
config String
filepath =
      Action :: forall lore.
String -> String -> (Prog lore -> FutharkM ()) -> Action lore
Action
        { actionName :: String
actionName = String
name,
          actionDescription :: String
actionDescription = String
desc,
          actionProcedure :: Prog lore -> FutharkM ()
actionProcedure =
            FutharkConfig
-> cfg -> CompilerMode -> String -> Prog lore -> FutharkM ()
doIt
              (CompilerConfig cfg -> FutharkConfig
forall cfg. CompilerConfig cfg -> FutharkConfig
futharkConfig CompilerConfig cfg
config)
              (CompilerConfig cfg -> cfg
forall cfg. CompilerConfig cfg -> cfg
compilerConfig CompilerConfig cfg
config)
              (CompilerConfig cfg -> CompilerMode
forall cfg. CompilerConfig cfg -> CompilerMode
compilerMode CompilerConfig cfg
config)
              (String -> CompilerConfig cfg -> String
forall cfg. String -> CompilerConfig cfg -> String
outputFilePath String
filepath CompilerConfig cfg
config)
        }

-- | An option that modifies the configuration of type @cfg@.
type CompilerOption cfg = OptDescr (Either (IO ()) (cfg -> cfg))

type CoreCompilerOption cfg =
  OptDescr
    ( Either
        (IO ())
        (CompilerConfig cfg -> CompilerConfig cfg)
    )

commandLineOptions :: [CoreCompilerOption cfg]
commandLineOptions :: forall cfg. [CoreCompilerOption cfg]
commandLineOptions =
  [ String
-> [String]
-> ArgDescr
     (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
-> String
-> CoreCompilerOption cfg
forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
Option
      String
"o"
      []
      ( (String
 -> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
-> String
-> ArgDescr
     (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
forall a. (String -> a) -> String -> ArgDescr a
ReqArg
          (\String
filename -> (CompilerConfig cfg -> CompilerConfig cfg)
-> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)
forall a b. b -> Either a b
Right ((CompilerConfig cfg -> CompilerConfig cfg)
 -> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
-> (CompilerConfig cfg -> CompilerConfig cfg)
-> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)
forall a b. (a -> b) -> a -> b
$ \CompilerConfig cfg
config -> CompilerConfig cfg
config {compilerOutput :: Maybe String
compilerOutput = String -> Maybe String
forall a. a -> Maybe a
Just String
filename})
          String
"FILE"
      )
      String
"Name of the compiled binary.",
    String
-> [String]
-> ArgDescr
     (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
-> String
-> CoreCompilerOption cfg
forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
Option
      String
"v"
      [String
"verbose"]
      ((Maybe String
 -> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
-> String
-> ArgDescr
     (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
forall a. (Maybe String -> a) -> String -> ArgDescr a
OptArg ((CompilerConfig cfg -> CompilerConfig cfg)
-> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)
forall a b. b -> Either a b
Right ((CompilerConfig cfg -> CompilerConfig cfg)
 -> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
-> (Maybe String -> CompilerConfig cfg -> CompilerConfig cfg)
-> Maybe String
-> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe String -> CompilerConfig cfg -> CompilerConfig cfg
forall cfg.
Maybe String -> CompilerConfig cfg -> CompilerConfig cfg
incVerbosity) String
"FILE")
      String
"Print verbose output on standard error; wrong program to FILE.",
    String
-> [String]
-> ArgDescr
     (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
-> String
-> CoreCompilerOption cfg
forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
Option
      []
      [String
"library"]
      (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)
-> ArgDescr
     (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
forall a. a -> ArgDescr a
NoArg (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)
 -> ArgDescr
      (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)))
-> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)
-> ArgDescr
     (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
forall a b. (a -> b) -> a -> b
$ (CompilerConfig cfg -> CompilerConfig cfg)
-> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)
forall a b. b -> Either a b
Right ((CompilerConfig cfg -> CompilerConfig cfg)
 -> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
-> (CompilerConfig cfg -> CompilerConfig cfg)
-> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)
forall a b. (a -> b) -> a -> b
$ \CompilerConfig cfg
config -> CompilerConfig cfg
config {compilerMode :: CompilerMode
compilerMode = CompilerMode
ToLibrary})
      String
"Generate a library instead of an executable.",
    String
-> [String]
-> ArgDescr
     (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
-> String
-> CoreCompilerOption cfg
forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
Option
      []
      [String
"executable"]
      (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)
-> ArgDescr
     (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
forall a. a -> ArgDescr a
NoArg (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)
 -> ArgDescr
      (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)))
-> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)
-> ArgDescr
     (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
forall a b. (a -> b) -> a -> b
$ (CompilerConfig cfg -> CompilerConfig cfg)
-> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)
forall a b. b -> Either a b
Right ((CompilerConfig cfg -> CompilerConfig cfg)
 -> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
-> (CompilerConfig cfg -> CompilerConfig cfg)
-> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)
forall a b. (a -> b) -> a -> b
$ \CompilerConfig cfg
config -> CompilerConfig cfg
config {compilerMode :: CompilerMode
compilerMode = CompilerMode
ToExecutable})
      String
"Generate an executable instead of a library (set by default).",
    String
-> [String]
-> ArgDescr
     (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
-> String
-> CoreCompilerOption cfg
forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
Option
      []
      [String
"server"]
      (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)
-> ArgDescr
     (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
forall a. a -> ArgDescr a
NoArg (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)
 -> ArgDescr
      (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)))
-> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)
-> ArgDescr
     (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
forall a b. (a -> b) -> a -> b
$ (CompilerConfig cfg -> CompilerConfig cfg)
-> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)
forall a b. b -> Either a b
Right ((CompilerConfig cfg -> CompilerConfig cfg)
 -> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
-> (CompilerConfig cfg -> CompilerConfig cfg)
-> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)
forall a b. (a -> b) -> a -> b
$ \CompilerConfig cfg
config -> CompilerConfig cfg
config {compilerMode :: CompilerMode
compilerMode = CompilerMode
ToServer})
      String
"Generate a server executable instead of a library.",
    String
-> [String]
-> ArgDescr
     (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
-> String
-> CoreCompilerOption cfg
forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
Option
      String
"w"
      []
      (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)
-> ArgDescr
     (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
forall a. a -> ArgDescr a
NoArg (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)
 -> ArgDescr
      (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)))
-> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)
-> ArgDescr
     (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
forall a b. (a -> b) -> a -> b
$ (CompilerConfig cfg -> CompilerConfig cfg)
-> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)
forall a b. b -> Either a b
Right ((CompilerConfig cfg -> CompilerConfig cfg)
 -> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
-> (CompilerConfig cfg -> CompilerConfig cfg)
-> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)
forall a b. (a -> b) -> a -> b
$ \CompilerConfig cfg
config -> CompilerConfig cfg
config {compilerWarn :: Bool
compilerWarn = Bool
False})
      String
"Disable all warnings.",
    String
-> [String]
-> ArgDescr
     (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
-> String
-> CoreCompilerOption cfg
forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
Option
      []
      [String
"Werror"]
      (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)
-> ArgDescr
     (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
forall a. a -> ArgDescr a
NoArg (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)
 -> ArgDescr
      (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)))
-> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)
-> ArgDescr
     (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
forall a b. (a -> b) -> a -> b
$ (CompilerConfig cfg -> CompilerConfig cfg)
-> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)
forall a b. b -> Either a b
Right ((CompilerConfig cfg -> CompilerConfig cfg)
 -> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
-> (CompilerConfig cfg -> CompilerConfig cfg)
-> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)
forall a b. (a -> b) -> a -> b
$ \CompilerConfig cfg
config -> CompilerConfig cfg
config {compilerWerror :: Bool
compilerWerror = Bool
True})
      String
"Treat warnings as errors.",
    String
-> [String]
-> ArgDescr
     (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
-> String
-> CoreCompilerOption cfg
forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
Option
      []
      [String
"safe"]
      (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)
-> ArgDescr
     (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
forall a. a -> ArgDescr a
NoArg (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)
 -> ArgDescr
      (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)))
-> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)
-> ArgDescr
     (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
forall a b. (a -> b) -> a -> b
$ (CompilerConfig cfg -> CompilerConfig cfg)
-> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)
forall a b. b -> Either a b
Right ((CompilerConfig cfg -> CompilerConfig cfg)
 -> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
-> (CompilerConfig cfg -> CompilerConfig cfg)
-> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)
forall a b. (a -> b) -> a -> b
$ \CompilerConfig cfg
config -> CompilerConfig cfg
config {compilerSafe :: Bool
compilerSafe = Bool
True})
      String
"Ignore 'unsafe' in code.",
    String
-> [String]
-> ArgDescr
     (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
-> String
-> CoreCompilerOption cfg
forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
Option
      []
      [String
"entry-points"]
      ( (String
 -> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
-> String
-> ArgDescr
     (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
forall a. (String -> a) -> String -> ArgDescr a
ReqArg
          ( \String
arg -> (CompilerConfig cfg -> CompilerConfig cfg)
-> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)
forall a b. b -> Either a b
Right ((CompilerConfig cfg -> CompilerConfig cfg)
 -> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
-> (CompilerConfig cfg -> CompilerConfig cfg)
-> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)
forall a b. (a -> b) -> a -> b
$ \CompilerConfig cfg
config ->
              CompilerConfig cfg
config
                { compilerEntryPoints :: [Name]
compilerEntryPoints =
                    String -> Name
nameFromString String
arg Name -> [Name] -> [Name]
forall a. a -> [a] -> [a]
: CompilerConfig cfg -> [Name]
forall cfg. CompilerConfig cfg -> [Name]
compilerEntryPoints CompilerConfig cfg
config
                }
          )
          String
"NAME"
      )
      String
"Treat this function as an additional entry point."
  ]

wrapOption :: CompilerOption cfg -> CoreCompilerOption cfg
wrapOption :: forall cfg. CompilerOption cfg -> CoreCompilerOption cfg
wrapOption = (Either (IO ()) (cfg -> cfg)
 -> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
-> OptDescr (Either (IO ()) (cfg -> cfg))
-> OptDescr
     (Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Either (IO ()) (cfg -> cfg)
-> Either (IO ()) (CompilerConfig cfg -> CompilerConfig cfg)
forall {m :: * -> *} {t} {cfg}.
Monad m =>
m (t -> cfg) -> m (CompilerConfig t -> CompilerConfig cfg)
wrap
  where
    wrap :: m (t -> cfg) -> m (CompilerConfig t -> CompilerConfig cfg)
wrap m (t -> cfg)
f = do
      t -> cfg
g <- m (t -> cfg)
f
      (CompilerConfig t -> CompilerConfig cfg)
-> m (CompilerConfig t -> CompilerConfig cfg)
forall (m :: * -> *) a. Monad m => a -> m a
return ((CompilerConfig t -> CompilerConfig cfg)
 -> m (CompilerConfig t -> CompilerConfig cfg))
-> (CompilerConfig t -> CompilerConfig cfg)
-> m (CompilerConfig t -> CompilerConfig cfg)
forall a b. (a -> b) -> a -> b
$ \CompilerConfig t
cfg -> CompilerConfig t
cfg {compilerConfig :: cfg
compilerConfig = t -> cfg
g (CompilerConfig t -> t
forall cfg. CompilerConfig cfg -> cfg
compilerConfig CompilerConfig t
cfg)}

incVerbosity :: Maybe FilePath -> CompilerConfig cfg -> CompilerConfig cfg
incVerbosity :: forall cfg.
Maybe String -> CompilerConfig cfg -> CompilerConfig cfg
incVerbosity Maybe String
file CompilerConfig cfg
cfg =
  CompilerConfig cfg
cfg {compilerVerbose :: (Verbosity, Maybe String)
compilerVerbose = (Verbosity
v, Maybe String
file Maybe String -> Maybe String -> Maybe String
forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
`mplus` (Verbosity, Maybe String) -> Maybe String
forall a b. (a, b) -> b
snd (CompilerConfig cfg -> (Verbosity, Maybe String)
forall cfg. CompilerConfig cfg -> (Verbosity, Maybe String)
compilerVerbose CompilerConfig cfg
cfg))}
  where
    v :: Verbosity
v = case (Verbosity, Maybe String) -> Verbosity
forall a b. (a, b) -> a
fst ((Verbosity, Maybe String) -> Verbosity)
-> (Verbosity, Maybe String) -> Verbosity
forall a b. (a -> b) -> a -> b
$ CompilerConfig cfg -> (Verbosity, Maybe String)
forall cfg. CompilerConfig cfg -> (Verbosity, Maybe String)
compilerVerbose CompilerConfig cfg
cfg of
      Verbosity
NotVerbose -> Verbosity
Verbose
      Verbosity
Verbose -> Verbosity
VeryVerbose
      Verbosity
VeryVerbose -> Verbosity
VeryVerbose

data CompilerConfig cfg = CompilerConfig
  { forall cfg. CompilerConfig cfg -> Maybe String
compilerOutput :: Maybe FilePath,
    forall cfg. CompilerConfig cfg -> (Verbosity, Maybe String)
compilerVerbose :: (Verbosity, Maybe FilePath),
    forall cfg. CompilerConfig cfg -> CompilerMode
compilerMode :: CompilerMode,
    forall cfg. CompilerConfig cfg -> Bool
compilerWerror :: Bool,
    forall cfg. CompilerConfig cfg -> Bool
compilerSafe :: Bool,
    forall cfg. CompilerConfig cfg -> Bool
compilerWarn :: Bool,
    forall cfg. CompilerConfig cfg -> cfg
compilerConfig :: cfg,
    forall cfg. CompilerConfig cfg -> [Name]
compilerEntryPoints :: [Name]
  }

-- | Are we compiling a library or an executable?
data CompilerMode
  = ToLibrary
  | ToExecutable
  | ToServer
  deriving (CompilerMode -> CompilerMode -> Bool
(CompilerMode -> CompilerMode -> Bool)
-> (CompilerMode -> CompilerMode -> Bool) -> Eq CompilerMode
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CompilerMode -> CompilerMode -> Bool
$c/= :: CompilerMode -> CompilerMode -> Bool
== :: CompilerMode -> CompilerMode -> Bool
$c== :: CompilerMode -> CompilerMode -> Bool
Eq, Eq CompilerMode
Eq CompilerMode
-> (CompilerMode -> CompilerMode -> Ordering)
-> (CompilerMode -> CompilerMode -> Bool)
-> (CompilerMode -> CompilerMode -> Bool)
-> (CompilerMode -> CompilerMode -> Bool)
-> (CompilerMode -> CompilerMode -> Bool)
-> (CompilerMode -> CompilerMode -> CompilerMode)
-> (CompilerMode -> CompilerMode -> CompilerMode)
-> Ord CompilerMode
CompilerMode -> CompilerMode -> Bool
CompilerMode -> CompilerMode -> Ordering
CompilerMode -> CompilerMode -> CompilerMode
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: CompilerMode -> CompilerMode -> CompilerMode
$cmin :: CompilerMode -> CompilerMode -> CompilerMode
max :: CompilerMode -> CompilerMode -> CompilerMode
$cmax :: CompilerMode -> CompilerMode -> CompilerMode
>= :: CompilerMode -> CompilerMode -> Bool
$c>= :: CompilerMode -> CompilerMode -> Bool
> :: CompilerMode -> CompilerMode -> Bool
$c> :: CompilerMode -> CompilerMode -> Bool
<= :: CompilerMode -> CompilerMode -> Bool
$c<= :: CompilerMode -> CompilerMode -> Bool
< :: CompilerMode -> CompilerMode -> Bool
$c< :: CompilerMode -> CompilerMode -> Bool
compare :: CompilerMode -> CompilerMode -> Ordering
$ccompare :: CompilerMode -> CompilerMode -> Ordering
Ord, Int -> CompilerMode -> ShowS
[CompilerMode] -> ShowS
CompilerMode -> String
(Int -> CompilerMode -> ShowS)
-> (CompilerMode -> String)
-> ([CompilerMode] -> ShowS)
-> Show CompilerMode
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [CompilerMode] -> ShowS
$cshowList :: [CompilerMode] -> ShowS
show :: CompilerMode -> String
$cshow :: CompilerMode -> String
showsPrec :: Int -> CompilerMode -> ShowS
$cshowsPrec :: Int -> CompilerMode -> ShowS
Show)

-- | The configuration of the compiler.
newCompilerConfig :: cfg -> CompilerConfig cfg
newCompilerConfig :: forall cfg. cfg -> CompilerConfig cfg
newCompilerConfig cfg
x =
  CompilerConfig :: forall cfg.
Maybe String
-> (Verbosity, Maybe String)
-> CompilerMode
-> Bool
-> Bool
-> Bool
-> cfg
-> [Name]
-> CompilerConfig cfg
CompilerConfig
    { compilerOutput :: Maybe String
compilerOutput = Maybe String
forall a. Maybe a
Nothing,
      compilerVerbose :: (Verbosity, Maybe String)
compilerVerbose = (Verbosity
NotVerbose, Maybe String
forall a. Maybe a
Nothing),
      compilerMode :: CompilerMode
compilerMode = CompilerMode
ToExecutable,
      compilerWerror :: Bool
compilerWerror = Bool
False,
      compilerSafe :: Bool
compilerSafe = Bool
False,
      compilerWarn :: Bool
compilerWarn = Bool
True,
      compilerConfig :: cfg
compilerConfig = cfg
x,
      compilerEntryPoints :: [Name]
compilerEntryPoints = [Name]
forall a. Monoid a => a
mempty
    }

outputFilePath :: FilePath -> CompilerConfig cfg -> FilePath
outputFilePath :: forall cfg. String -> CompilerConfig cfg -> String
outputFilePath String
srcfile =
  String -> Maybe String -> String
forall a. a -> Maybe a -> a
fromMaybe (String
srcfile String -> ShowS
`replaceExtension` String
"") (Maybe String -> String)
-> (CompilerConfig cfg -> Maybe String)
-> CompilerConfig cfg
-> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CompilerConfig cfg -> Maybe String
forall cfg. CompilerConfig cfg -> Maybe String
compilerOutput

futharkConfig :: CompilerConfig cfg -> FutharkConfig
futharkConfig :: forall cfg. CompilerConfig cfg -> FutharkConfig
futharkConfig CompilerConfig cfg
config =
  FutharkConfig
newFutharkConfig
    { futharkVerbose :: (Verbosity, Maybe String)
futharkVerbose = CompilerConfig cfg -> (Verbosity, Maybe String)
forall cfg. CompilerConfig cfg -> (Verbosity, Maybe String)
compilerVerbose CompilerConfig cfg
config,
      futharkWerror :: Bool
futharkWerror = CompilerConfig cfg -> Bool
forall cfg. CompilerConfig cfg -> Bool
compilerWerror CompilerConfig cfg
config,
      futharkSafe :: Bool
futharkSafe = CompilerConfig cfg -> Bool
forall cfg. CompilerConfig cfg -> Bool
compilerSafe CompilerConfig cfg
config,
      futharkWarn :: Bool
futharkWarn = CompilerConfig cfg -> Bool
forall cfg. CompilerConfig cfg -> Bool
compilerWarn CompilerConfig cfg
config,
      futharkEntryPoints :: [Name]
futharkEntryPoints = CompilerConfig cfg -> [Name]
forall cfg. CompilerConfig cfg -> [Name]
compilerEntryPoints CompilerConfig cfg
config
    }