module Cli.ParseCompileOptions (
optionHelpText,
parseCompileOptions,
validateCompileOptions,
) where
import Control.Monad (when)
import Data.List (isSuffixOf)
import Text.Regex.TDFA
import Base.CompilerError
import Cli.CompileOptions
import Types.TypeCategory (FunctionName(..))
import Types.TypeInstance (CategoryName(..))
optionHelpText :: [String]
optionHelpText :: [String]
optionHelpText = [
String
"",
String
"zeolite [options...] --fast [category(.function)] [.0rx source]",
String
"zeolite [options...] -r [modules...]",
String
"zeolite [options...] -R [modules...]",
String
"zeolite [options...] -t [modules...] (--log-traces [filename])",
String
"",
String
"zeolite [options...] -c [module]",
String
"zeolite [options...] -m [category(.function)] (-o [binary]) [module]",
String
"",
String
"zeolite [options...] --templates [modules...]",
String
"zeolite --get-path",
String
"zeolite --show-deps [modules...]",
String
"zeolite --version",
String
"",
String
"Compilation Modes:",
String
" --fast: Create a binary without needing a config.",
String
" -r: Recompile using each module's .zeolite-module config.",
String
" -R: Recursively recompile using each module's .zeolite-module config.",
String
" -t: Only execute tests, without other compilation.",
String
"",
String
"Configuration Modes:",
String
" -c: Create a new .zeolite-module config for a libary module.",
String
" -m: Create a new .zeolite-module config for a binary module.",
String
"",
String
"Special Modes:",
String
" --templates: Only create C++ templates for undefined categories in .0rp sources.",
String
" --get-path: Show the data path and immediately exit.",
String
" --show-deps: Show category dependencies for the modules.",
String
" --version: Show the compiler version and immediately exit.",
String
"",
String
"Options:",
String
" -f: Force an operation that zeolite would otherwise reject.",
String
" -i [module]: A single source module to include as a public dependency.",
String
" -I [module]: A single source module to include as a private dependency.",
String
" -o [binary]: The name of the binary file to create with -m.",
String
" -p [path]: Set a path prefix for finding modules or files.",
String
" --log-traces [filename]: Log call traces to a file when running tests.",
String
"",
String
"Argument Types:",
String
" category: The name of a concrete category with no params.",
String
" function: The name of a @type function (defaults to \"run\") with no args or params.",
String
" module: Path to a directory containing an existing or to-be-created Zeolite module.",
String
"",
String
"Examples:",
String
"",
String
" # Create a config for a binary in myprogram that calls MyProgram.run() that uses lib/util.",
String
" zeolite -I lib/util -m MyProgram.run myprogram",
String
"",
String
" # Compile a binary that calls MyProgram.run() from myprogram.0rx without a config.",
String
" zeolite -I lib/util --fast MyProgram.run myprogram.0rx",
String
"",
String
" # Create a config for a library in mylibrary that uses lib/util.",
String
" zeolite -I lib/util -c mylibrary",
String
"",
String
" # Recompile myprogram, recursively recompiling its dependencies first.",
String
" zeolite -R myprogram",
String
"",
String
" # Execute the tests from .0rt files in mylibrary.",
String
" zeolite -t mylibrary",
String
""
]
defaultMainFunc :: String
defaultMainFunc :: String
defaultMainFunc = String
"run"
parseCompileOptions :: CollectErrorsM m => [String] -> m CompileOptions
parseCompileOptions :: [String] -> m CompileOptions
parseCompileOptions = CompileOptions -> [(Int, String)] -> m CompileOptions
forall (m :: * -> *) a.
(ErrorContextM m, Show a) =>
CompileOptions -> [(a, String)] -> m CompileOptions
parseAll CompileOptions
emptyCompileOptions ([(Int, String)] -> m CompileOptions)
-> ([String] -> [(Int, String)]) -> [String] -> m CompileOptions
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Int] -> [String] -> [(Int, String)]
forall a b. [a] -> [b] -> [(a, b)]
zip ([Int
1..] :: [Int]) where
parseAll :: CompileOptions -> [(a, String)] -> m CompileOptions
parseAll CompileOptions
co [] = CompileOptions -> m CompileOptions
forall (m :: * -> *) a. Monad m => a -> m a
return CompileOptions
co
parseAll CompileOptions
co [(a, String)]
os = do
([(a, String)]
os',CompileOptions
co') <- CompileOptions
-> [(a, String)] -> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a.
(ErrorContextM m, Show a) =>
CompileOptions
-> [(a, String)] -> m ([(a, String)], CompileOptions)
parseSingle CompileOptions
co [(a, String)]
os
CompileOptions -> [(a, String)] -> m CompileOptions
parseAll CompileOptions
co' [(a, String)]
os'
argError :: a -> String -> String -> m a
argError a
n String
o String
m = String -> m a
forall (m :: * -> *) a. ErrorContextM m => String -> m a
compilerErrorM (String -> m a) -> String -> m a
forall a b. (a -> b) -> a -> b
$ String
"Argument " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
n String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" (\"" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
o String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\"): " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
m
checkPathName :: a -> String -> String -> m ()
checkPathName a
n String
f String
o
| String
f String -> String -> Bool
forall source source1 target.
(RegexMaker Regex CompOption ExecOption source,
RegexContext Regex source1 target) =>
source1 -> source -> target
=~ String
"^(/[^/]+|[^-/][^/]*)(/[^/]+)*$" = () -> m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
| String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
o = a -> String -> String -> m ()
forall (m :: * -> *) a a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n String
f String
"Invalid file path."
| Bool
otherwise = a -> String -> String -> m ()
forall (m :: * -> *) a a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n String
f (String -> m ()) -> String -> m ()
forall a b. (a -> b) -> a -> b
$ String
"Invalid file path for " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
o String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"."
checkCategoryName :: a -> String -> String -> m ()
checkCategoryName a
n String
c String
o
| String
c String -> String -> Bool
forall source source1 target.
(RegexMaker Regex CompOption ExecOption source,
RegexContext Regex source1 target) =>
source1 -> source -> target
=~ String
"^[A-Z][A-Za-z0-9]+$" = () -> m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
| Bool
otherwise = a -> String -> String -> m ()
forall (m :: * -> *) a a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n String
c (String -> m ()) -> String -> m ()
forall a b. (a -> b) -> a -> b
$ String
"Invalid category name for " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
o String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"."
checkFunctionName :: a -> String -> String -> m ()
checkFunctionName a
n String
d String
o
| String
d String -> String -> Bool
forall source source1 target.
(RegexMaker Regex CompOption ExecOption source,
RegexContext Regex source1 target) =>
source1 -> source -> target
=~ String
"^[a-z][A-Za-z0-9]+$" = () -> m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
| Bool
otherwise = a -> String -> String -> m ()
forall (m :: * -> *) a a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n String
d (String -> m ()) -> String -> m ()
forall a b. (a -> b) -> a -> b
$ String
"Invalid function name for " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
o String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"."
parseSingle :: CompileOptions
-> [(a, String)] -> m ([(a, String)], CompileOptions)
parseSingle CompileOptions
_ [] = m ([(a, String)], CompileOptions)
forall a. HasCallStack => a
undefined
parseSingle (CompileOptions HelpMode
_ [String]
is [String]
is2 [String]
ds [ExtraSource]
es [String]
ep String
p CompileMode
m ForceMode
f) ((a
_,String
"-h"):[(a, String)]
os) =
([(a, String)], CompileOptions)
-> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a. Monad m => a -> m a
return ([(a, String)]
os,HelpMode
-> [String]
-> [String]
-> [String]
-> [ExtraSource]
-> [String]
-> String
-> CompileMode
-> ForceMode
-> CompileOptions
CompileOptions HelpMode
HelpNeeded [String]
is [String]
is2 [String]
ds [ExtraSource]
es [String]
ep String
p CompileMode
m ForceMode
f)
parseSingle (CompileOptions HelpMode
h [String]
is [String]
is2 [String]
ds [ExtraSource]
es [String]
ep String
p CompileMode
m ForceMode
_) ((a
_,String
"-f"):[(a, String)]
os) =
([(a, String)], CompileOptions)
-> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a. Monad m => a -> m a
return ([(a, String)]
os,HelpMode
-> [String]
-> [String]
-> [String]
-> [ExtraSource]
-> [String]
-> String
-> CompileMode
-> ForceMode
-> CompileOptions
CompileOptions (HelpMode -> HelpMode
maybeDisableHelp HelpMode
h) [String]
is [String]
is2 [String]
ds [ExtraSource]
es [String]
ep String
p CompileMode
m ForceMode
ForceAll)
parseSingle (CompileOptions HelpMode
h [String]
is [String]
is2 [String]
ds [ExtraSource]
es [String]
ep String
p CompileMode
m ForceMode
f) ((a
n,String
"-c"):[(a, String)]
os)
| CompileMode
m CompileMode -> CompileMode -> Bool
forall a. Eq a => a -> a -> Bool
/= CompileMode
CompileUnspecified = a -> String -> String -> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n String
"-c" String
"Compiler mode already set."
| Bool
otherwise = ([(a, String)], CompileOptions)
-> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a. Monad m => a -> m a
return ([(a, String)]
os,HelpMode
-> [String]
-> [String]
-> [String]
-> [ExtraSource]
-> [String]
-> String
-> CompileMode
-> ForceMode
-> CompileOptions
CompileOptions (HelpMode -> HelpMode
maybeDisableHelp HelpMode
h) [String]
is [String]
is2 [String]
ds [ExtraSource]
es [String]
ep String
p ([String] -> CompileMode
CompileIncremental []) ForceMode
f)
parseSingle (CompileOptions HelpMode
h [String]
is [String]
is2 [String]
ds [ExtraSource]
es [String]
ep String
p CompileMode
m ForceMode
f) ((a
n,String
"-r"):[(a, String)]
os)
| CompileMode
m CompileMode -> CompileMode -> Bool
forall a. Eq a => a -> a -> Bool
/= CompileMode
CompileUnspecified = a -> String -> String -> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n String
"-r" String
"Compiler mode already set."
| Bool
otherwise = ([(a, String)], CompileOptions)
-> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a. Monad m => a -> m a
return ([(a, String)]
os,HelpMode
-> [String]
-> [String]
-> [String]
-> [ExtraSource]
-> [String]
-> String
-> CompileMode
-> ForceMode
-> CompileOptions
CompileOptions (HelpMode -> HelpMode
maybeDisableHelp HelpMode
h) [String]
is [String]
is2 [String]
ds [ExtraSource]
es [String]
ep String
p CompileMode
CompileRecompile ForceMode
f)
parseSingle (CompileOptions HelpMode
h [String]
is [String]
is2 [String]
ds [ExtraSource]
es [String]
ep String
p CompileMode
m ForceMode
f) ((a
n,String
"-R"):[(a, String)]
os)
| CompileMode
m CompileMode -> CompileMode -> Bool
forall a. Eq a => a -> a -> Bool
/= CompileMode
CompileUnspecified = a -> String -> String -> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n String
"-r" String
"Compiler mode already set."
| Bool
otherwise = ([(a, String)], CompileOptions)
-> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a. Monad m => a -> m a
return ([(a, String)]
os,HelpMode
-> [String]
-> [String]
-> [String]
-> [ExtraSource]
-> [String]
-> String
-> CompileMode
-> ForceMode
-> CompileOptions
CompileOptions (HelpMode -> HelpMode
maybeDisableHelp HelpMode
h) [String]
is [String]
is2 [String]
ds [ExtraSource]
es [String]
ep String
p CompileMode
CompileRecompileRecursive ForceMode
f)
parseSingle (CompileOptions HelpMode
h [String]
is [String]
is2 [String]
ds [ExtraSource]
es [String]
ep String
p CompileMode
m ForceMode
f) ((a
n,String
"-t"):[(a, String)]
os)
| CompileMode
m CompileMode -> CompileMode -> Bool
forall a. Eq a => a -> a -> Bool
/= CompileMode
CompileUnspecified = a -> String -> String -> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n String
"-t" String
"Compiler mode already set."
| Bool
otherwise = ([(a, String)], CompileOptions)
-> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a. Monad m => a -> m a
return ([(a, String)]
os,HelpMode
-> [String]
-> [String]
-> [String]
-> [ExtraSource]
-> [String]
-> String
-> CompileMode
-> ForceMode
-> CompileOptions
CompileOptions (HelpMode -> HelpMode
maybeDisableHelp HelpMode
h) [String]
is [String]
is2 [String]
ds [ExtraSource]
es [String]
ep String
p ([String] -> Maybe String -> CompileMode
ExecuteTests [] Maybe String
forall a. Maybe a
Nothing) ForceMode
f)
parseSingle (CompileOptions HelpMode
h [String]
is [String]
is2 [String]
ds [ExtraSource]
es [String]
ep String
p CompileMode
m ForceMode
f) ((a
n,String
"--templates"):[(a, String)]
os)
| CompileMode
m CompileMode -> CompileMode -> Bool
forall a. Eq a => a -> a -> Bool
/= CompileMode
CompileUnspecified = a -> String -> String -> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n String
"-t" String
"Compiler mode already set."
| Bool
otherwise = ([(a, String)], CompileOptions)
-> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a. Monad m => a -> m a
return ([(a, String)]
os,HelpMode
-> [String]
-> [String]
-> [String]
-> [ExtraSource]
-> [String]
-> String
-> CompileMode
-> ForceMode
-> CompileOptions
CompileOptions (HelpMode -> HelpMode
maybeDisableHelp HelpMode
h) [String]
is [String]
is2 [String]
ds [ExtraSource]
es [String]
ep String
p CompileMode
CreateTemplates ForceMode
f)
parseSingle (CompileOptions HelpMode
h [String]
is [String]
is2 [String]
ds [ExtraSource]
es [String]
ep String
p CompileMode
m ForceMode
f) ((a
n,String
"-m"):[(a, String)]
os)
| CompileMode
m CompileMode -> CompileMode -> Bool
forall a. Eq a => a -> a -> Bool
/= CompileMode
CompileUnspecified = a -> String -> String -> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n String
"-m" String
"Compiler mode already set."
| Bool
otherwise = [(a, String)] -> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a.
(ErrorContextM m, Show a) =>
[(a, String)] -> m ([(a, String)], CompileOptions)
update [(a, String)]
os where
update :: [(a, String)] -> m ([(a, String)], CompileOptions)
update ((a
n2,String
c):[(a, String)]
os2) = do
(String
t,String
fn) <- (String, String) -> m (String, String)
forall (m :: * -> *) a.
ErrorContextM m =>
(a, String) -> m (a, String)
check ((String, String) -> m (String, String))
-> (String, String) -> m (String, String)
forall a b. (a -> b) -> a -> b
$ (Char -> Bool) -> String -> (String, String)
forall a. (a -> Bool) -> [a] -> ([a], [a])
break (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'.') String
c
a -> String -> String -> m ()
forall (m :: * -> *) a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m ()
checkCategoryName a
n2 String
t String
"-m"
a -> String -> String -> m ()
forall (m :: * -> *) a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m ()
checkFunctionName a
n2 String
fn String
"-m"
let m2 :: CompileMode
m2 = CategoryName
-> FunctionName -> LinkerMode -> String -> [String] -> CompileMode
CompileBinary (String -> CategoryName
CategoryName String
t) (String -> FunctionName
FunctionName String
fn) LinkerMode
LinkDynamic String
"" []
([(a, String)], CompileOptions)
-> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a. Monad m => a -> m a
return ([(a, String)]
os2,HelpMode
-> [String]
-> [String]
-> [String]
-> [ExtraSource]
-> [String]
-> String
-> CompileMode
-> ForceMode
-> CompileOptions
CompileOptions (HelpMode -> HelpMode
maybeDisableHelp HelpMode
h) [String]
is [String]
is2 [String]
ds [ExtraSource]
es [String]
ep String
p CompileMode
m2 ForceMode
f) where
check :: (a, String) -> m (a, String)
check (a
t,String
"") = (a, String) -> m (a, String)
forall (m :: * -> *) a. Monad m => a -> m a
return (a
t,String
defaultMainFunc)
check (a
t,Char
'.':String
fn) = (a, String) -> m (a, String)
forall (m :: * -> *) a. Monad m => a -> m a
return (a
t,String
fn)
check (a, String)
_ = a -> String -> String -> m (a, String)
forall (m :: * -> *) a a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n2 String
c (String -> m (a, String)) -> String -> m (a, String)
forall a b. (a -> b) -> a -> b
$ String
"Invalid entry point."
update [(a, String)]
_ = a -> String -> String -> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n String
"-m" String
"Requires a category name."
parseSingle (CompileOptions HelpMode
h [String]
is [String]
is2 [String]
ds [ExtraSource]
es [String]
ep String
p CompileMode
m ForceMode
f) ((a
n,String
"--fast"):[(a, String)]
os)
| CompileMode
m CompileMode -> CompileMode -> Bool
forall a. Eq a => a -> a -> Bool
/= CompileMode
CompileUnspecified = a -> String -> String -> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n String
"--fast" String
"Compiler mode already set."
| Bool
otherwise = [(a, String)] -> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a.
(ErrorContextM m, Show a) =>
[(a, String)] -> m ([(a, String)], CompileOptions)
update [(a, String)]
os where
update :: [(a, String)] -> m ([(a, String)], CompileOptions)
update ((a
n2,String
c):(a
n3,String
f2):[(a, String)]
os2) = do
(String
t,String
fn) <- (String, String) -> m (String, String)
forall (m :: * -> *) a.
ErrorContextM m =>
(a, String) -> m (a, String)
check ((String, String) -> m (String, String))
-> (String, String) -> m (String, String)
forall a b. (a -> b) -> a -> b
$ (Char -> Bool) -> String -> (String, String)
forall a. (a -> Bool) -> [a] -> ([a], [a])
break (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'.') String
c
a -> String -> String -> m ()
forall (m :: * -> *) a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m ()
checkCategoryName a
n2 String
t String
"--fast"
a -> String -> String -> m ()
forall (m :: * -> *) a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m ()
checkFunctionName a
n2 String
fn String
"--fast"
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
isSuffixOf String
".0rx" String
f2) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ a -> String -> String -> m ()
forall (m :: * -> *) a a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n3 String
f2 (String -> m ()) -> String -> m ()
forall a b. (a -> b) -> a -> b
$ String
"Must specify a .0rx source file."
let m2 :: CompileMode
m2 = CategoryName -> FunctionName -> String -> CompileMode
CompileFast (String -> CategoryName
CategoryName String
t) (String -> FunctionName
FunctionName String
fn) String
f2
([(a, String)], CompileOptions)
-> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a. Monad m => a -> m a
return ([(a, String)]
os2,HelpMode
-> [String]
-> [String]
-> [String]
-> [ExtraSource]
-> [String]
-> String
-> CompileMode
-> ForceMode
-> CompileOptions
CompileOptions (HelpMode -> HelpMode
maybeDisableHelp HelpMode
h) [String]
is [String]
is2 [String]
ds [ExtraSource]
es [String]
ep String
p CompileMode
m2 ForceMode
f) where
check :: (a, String) -> m (a, String)
check (a
t,String
"") = (a, String) -> m (a, String)
forall (m :: * -> *) a. Monad m => a -> m a
return (a
t,String
defaultMainFunc)
check (a
t,Char
'.':String
fn) = (a, String) -> m (a, String)
forall (m :: * -> *) a. Monad m => a -> m a
return (a
t,String
fn)
check (a, String)
_ = a -> String -> String -> m (a, String)
forall (m :: * -> *) a a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n2 String
c (String -> m (a, String)) -> String -> m (a, String)
forall a b. (a -> b) -> a -> b
$ String
"Invalid entry point."
update [(a, String)]
_ = a -> String -> String -> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n String
"--fast" String
"Requires a category name and a .0rx file."
parseSingle (CompileOptions HelpMode
h [String]
is [String]
is2 [String]
ds [ExtraSource]
es [String]
ep String
p (ExecuteTests [String]
tp Maybe String
cl) ForceMode
f) ((a
n,String
"--log-traces"):[(a, String)]
os) = [(a, String)] -> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a.
ErrorContextM m =>
[(a, String)] -> m ([(a, String)], CompileOptions)
update [(a, String)]
os where
update :: [(a, String)] -> m ([(a, String)], CompileOptions)
update ((a
_,String
cl2):[(a, String)]
os2)
| Maybe String
cl Maybe String -> Maybe String -> Bool
forall a. Eq a => a -> a -> Bool
/= Maybe String
forall a. Maybe a
Nothing = a -> String -> String -> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n String
"--log-traces" String
"Trace-log filename already set."
| Bool
otherwise = ([(a, String)], CompileOptions)
-> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a. Monad m => a -> m a
return ([(a, String)]
os2,HelpMode
-> [String]
-> [String]
-> [String]
-> [ExtraSource]
-> [String]
-> String
-> CompileMode
-> ForceMode
-> CompileOptions
CompileOptions (HelpMode -> HelpMode
maybeDisableHelp HelpMode
h) [String]
is [String]
is2 [String]
ds [ExtraSource]
es [String]
ep String
p ([String] -> Maybe String -> CompileMode
ExecuteTests [String]
tp (String -> Maybe String
forall a. a -> Maybe a
Just String
cl2)) ForceMode
f)
update [(a, String)]
_ = a -> String -> String -> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n String
"--log-traces" String
"Requires an output filename."
parseSingle CompileOptions
_ ((a
n,String
"--log-traces"):[(a, String)]
_) = a -> String -> String -> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n String
"--log-traces" String
"Set mode to test (-t) first."
parseSingle (CompileOptions HelpMode
h [String]
is [String]
is2 [String]
ds [ExtraSource]
es [String]
ep String
p (CompileBinary CategoryName
t FunctionName
fn LinkerMode
lm String
o [String]
lf) ForceMode
f) ((a
n,String
"-o"):[(a, String)]
os)
| Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
o = a -> String -> String -> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n String
"-o" String
"Output name already set."
| Bool
otherwise = [(a, String)] -> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a.
(ErrorContextM m, Show a) =>
[(a, String)] -> m ([(a, String)], CompileOptions)
update [(a, String)]
os where
update :: [(a, String)] -> m ([(a, String)], CompileOptions)
update ((a
n2,String
o2):[(a, String)]
os2) = do
a -> String -> String -> m ()
forall (m :: * -> *) a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m ()
checkPathName a
n2 String
o2 String
"-o"
([(a, String)], CompileOptions)
-> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a. Monad m => a -> m a
return ([(a, String)]
os2,HelpMode
-> [String]
-> [String]
-> [String]
-> [ExtraSource]
-> [String]
-> String
-> CompileMode
-> ForceMode
-> CompileOptions
CompileOptions (HelpMode -> HelpMode
maybeDisableHelp HelpMode
h) [String]
is [String]
is2 [String]
ds [ExtraSource]
es [String]
ep String
p (CategoryName
-> FunctionName -> LinkerMode -> String -> [String] -> CompileMode
CompileBinary CategoryName
t FunctionName
fn LinkerMode
lm String
o2 [String]
lf) ForceMode
f)
update [(a, String)]
_ = a -> String -> String -> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n String
"-o" String
"Requires an output name."
parseSingle CompileOptions
_ ((a
n,String
"-o"):[(a, String)]
_) = a -> String -> String -> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n String
"-o" String
"Set mode to binary (-m) first."
parseSingle (CompileOptions HelpMode
h [String]
is [String]
is2 [String]
ds [ExtraSource]
es [String]
ep String
p CompileMode
m ForceMode
f) ((a
n,String
"-i"):[(a, String)]
os) = [(a, String)] -> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a.
(ErrorContextM m, Show a) =>
[(a, String)] -> m ([(a, String)], CompileOptions)
update [(a, String)]
os where
update :: [(a, String)] -> m ([(a, String)], CompileOptions)
update ((a
n2,String
d):[(a, String)]
os2)
| String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
isSuffixOf String
".0rp" String
d = a -> String -> String -> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n2 String
d String
"Cannot directly include .0rp source files."
| String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
isSuffixOf String
".0rx" String
d = a -> String -> String -> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n2 String
d String
"Cannot directly include .0rx source files."
| String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
isSuffixOf String
".0rt" String
d = a -> String -> String -> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n2 String
d String
"Cannot directly include .0rt test files."
| Bool
otherwise = do
a -> String -> String -> m ()
forall (m :: * -> *) a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m ()
checkPathName a
n2 String
d String
"-i"
([(a, String)], CompileOptions)
-> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a. Monad m => a -> m a
return ([(a, String)]
os2,HelpMode
-> [String]
-> [String]
-> [String]
-> [ExtraSource]
-> [String]
-> String
-> CompileMode
-> ForceMode
-> CompileOptions
CompileOptions (HelpMode -> HelpMode
maybeDisableHelp HelpMode
h) ([String]
is [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [String
d]) [String]
is2 [String]
ds [ExtraSource]
es [String]
ep String
p CompileMode
m ForceMode
f)
update [(a, String)]
_ = a -> String -> String -> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n String
"-i" String
"Requires a source path."
parseSingle (CompileOptions HelpMode
h [String]
is [String]
is2 [String]
ds [ExtraSource]
es [String]
ep String
p CompileMode
m ForceMode
f) ((a
n,String
"-I"):[(a, String)]
os) = [(a, String)] -> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a.
(ErrorContextM m, Show a) =>
[(a, String)] -> m ([(a, String)], CompileOptions)
update [(a, String)]
os where
update :: [(a, String)] -> m ([(a, String)], CompileOptions)
update ((a
n2,String
d):[(a, String)]
os2)
| String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
isSuffixOf String
".0rp" String
d = a -> String -> String -> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n2 String
d String
"Cannot directly include .0rp source files."
| String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
isSuffixOf String
".0rx" String
d = a -> String -> String -> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n2 String
d String
"Cannot directly include .0rx source files."
| String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
isSuffixOf String
".0rt" String
d = a -> String -> String -> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n2 String
d String
"Cannot directly include .0rt test files."
| Bool
otherwise = do
a -> String -> String -> m ()
forall (m :: * -> *) a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m ()
checkPathName a
n2 String
d String
"-i"
([(a, String)], CompileOptions)
-> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a. Monad m => a -> m a
return ([(a, String)]
os2,HelpMode
-> [String]
-> [String]
-> [String]
-> [ExtraSource]
-> [String]
-> String
-> CompileMode
-> ForceMode
-> CompileOptions
CompileOptions (HelpMode -> HelpMode
maybeDisableHelp HelpMode
h) [String]
is ([String]
is2 [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [String
d]) [String]
ds [ExtraSource]
es [String]
ep String
p CompileMode
m ForceMode
f)
update [(a, String)]
_ = a -> String -> String -> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n String
"-I" String
"Requires a source path."
parseSingle (CompileOptions HelpMode
h [String]
is [String]
is2 [String]
ds [ExtraSource]
es [String]
ep String
p CompileMode
m ForceMode
f) ((a
n,String
"-p"):[(a, String)]
os)
| Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
p = a -> String -> String -> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n String
"-p" String
"Path prefix already set."
| Bool
otherwise = [(a, String)] -> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a.
(ErrorContextM m, Show a) =>
[(a, String)] -> m ([(a, String)], CompileOptions)
update [(a, String)]
os where
update :: [(a, String)] -> m ([(a, String)], CompileOptions)
update ((a
n2,String
p2):[(a, String)]
os2) = do
a -> String -> String -> m ()
forall (m :: * -> *) a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m ()
checkPathName a
n2 String
p2 String
"-p"
([(a, String)], CompileOptions)
-> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a. Monad m => a -> m a
return ([(a, String)]
os2,HelpMode
-> [String]
-> [String]
-> [String]
-> [ExtraSource]
-> [String]
-> String
-> CompileMode
-> ForceMode
-> CompileOptions
CompileOptions (HelpMode -> HelpMode
maybeDisableHelp HelpMode
h) [String]
is [String]
is2 [String]
ds [ExtraSource]
es [String]
ep String
p2 CompileMode
m ForceMode
f)
update [(a, String)]
_ = a -> String -> String -> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n String
"-p" String
"Requires a path prefix."
parseSingle CompileOptions
_ ((a
n,o :: String
o@(Char
'-':String
_)):[(a, String)]
_) = a -> String -> String -> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n String
o String
"Unknown option."
parseSingle (CompileOptions HelpMode
h [String]
is [String]
is2 [String]
ds [ExtraSource]
es [String]
ep String
p CompileMode
m ForceMode
f) ((a
n,String
d):[(a, String)]
os)
| String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
isSuffixOf String
".0rp" String
d = a -> String -> String -> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n String
d String
"Cannot directly include .0rp source files."
| String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
isSuffixOf String
".0rx" String
d = a -> String -> String -> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n String
d String
"Cannot directly include .0rx source files."
| String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
isSuffixOf String
".0rt" String
d = do
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ CompileMode -> Bool
isExecuteTests CompileMode
m) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$
a -> String -> String -> m ()
forall (m :: * -> *) a a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n String
d String
"Test mode (-t) must be enabled before listing any .0rt test files."
a -> String -> String -> m ()
forall (m :: * -> *) a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m ()
checkPathName a
n String
d String
""
let (ExecuteTests [String]
tp Maybe String
cl) = CompileMode
m
([(a, String)], CompileOptions)
-> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a. Monad m => a -> m a
return ([(a, String)]
os,HelpMode
-> [String]
-> [String]
-> [String]
-> [ExtraSource]
-> [String]
-> String
-> CompileMode
-> ForceMode
-> CompileOptions
CompileOptions (HelpMode -> HelpMode
maybeDisableHelp HelpMode
h) [String]
is [String]
is2 [String]
ds [ExtraSource]
es [String]
ep String
p ([String] -> Maybe String -> CompileMode
ExecuteTests ([String]
tp [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [String
d]) Maybe String
cl) ForceMode
f)
| Bool
otherwise = do
a -> String -> String -> m ()
forall (m :: * -> *) a.
(ErrorContextM m, Show a) =>
a -> String -> String -> m ()
checkPathName a
n String
d String
""
([(a, String)], CompileOptions)
-> m ([(a, String)], CompileOptions)
forall (m :: * -> *) a. Monad m => a -> m a
return ([(a, String)]
os,HelpMode
-> [String]
-> [String]
-> [String]
-> [ExtraSource]
-> [String]
-> String
-> CompileMode
-> ForceMode
-> CompileOptions
CompileOptions (HelpMode -> HelpMode
maybeDisableHelp HelpMode
h) [String]
is [String]
is2 ([String]
ds [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [String
d]) [ExtraSource]
es [String]
ep String
p CompileMode
m ForceMode
f)
validateCompileOptions :: CollectErrorsM m => CompileOptions -> m CompileOptions
validateCompileOptions :: CompileOptions -> m CompileOptions
validateCompileOptions co :: CompileOptions
co@(CompileOptions HelpMode
h [String]
is [String]
is2 [String]
ds [ExtraSource]
_ [String]
_ String
_ CompileMode
m ForceMode
_)
| HelpMode
h HelpMode -> HelpMode -> Bool
forall a. Eq a => a -> a -> Bool
/= HelpMode
HelpNotNeeded = CompileOptions -> m CompileOptions
forall (m :: * -> *) a. Monad m => a -> m a
return CompileOptions
co
| CompileMode -> Bool
isCompileUnspecified CompileMode
m =
String -> m CompileOptions
forall (m :: * -> *) a. ErrorContextM m => String -> m a
compilerErrorM String
"Compiler mode must be specified explicitly."
| (Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ [String] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null ([String] -> Bool) -> [String] -> Bool
forall a b. (a -> b) -> a -> b
$ [String]
is [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [String]
is2) Bool -> Bool -> Bool
&& (CompileMode -> Bool
isExecuteTests CompileMode
m) =
String -> m CompileOptions
forall (m :: * -> *) a. ErrorContextM m => String -> m a
compilerErrorM String
"Include paths (-i/-I) are not allowed in test mode (-t)."
| (Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ [String] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null ([String] -> Bool) -> [String] -> Bool
forall a b. (a -> b) -> a -> b
$ [String]
is [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [String]
is2) Bool -> Bool -> Bool
&& (CompileMode -> Bool
isCompileRecompile CompileMode
m) =
String -> m CompileOptions
forall (m :: * -> *) a. ErrorContextM m => String -> m a
compilerErrorM String
"Include paths (-i/-I) are not allowed in recompile mode (-r/-R)."
| ([String] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [String]
ds Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
0) Bool -> Bool -> Bool
&& (CompileMode -> Bool
isCompileFast CompileMode
m) =
String -> m CompileOptions
forall (m :: * -> *) a. ErrorContextM m => String -> m a
compilerErrorM String
"Input path is not allowed with fast mode (--fast)."
| [String] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [String]
ds Bool -> Bool -> Bool
&& (Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ CompileMode -> Bool
isCompileFast CompileMode
m) =
String -> m CompileOptions
forall (m :: * -> *) a. ErrorContextM m => String -> m a
compilerErrorM String
"Please specify at least one input path."
| ([String] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [String]
ds Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
1) Bool -> Bool -> Bool
&& (Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ CompileMode -> Bool
isCompileRecompile CompileMode
m) Bool -> Bool -> Bool
&& (Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ CompileMode -> Bool
isExecuteTests CompileMode
m) =
String -> m CompileOptions
forall (m :: * -> *) a. ErrorContextM m => String -> m a
compilerErrorM String
"Multiple input paths are only allowed with recompile mode (-r/-R) and test mode (-t)."
| Bool
otherwise = CompileOptions -> m CompileOptions
forall (m :: * -> *) a. Monad m => a -> m a
return CompileOptions
co