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...] -m [category(.function)] -o [binary] [path]",
String
"zeolite [options...] --fast [category(.function)] [.0rx source]",
String
"zeolite [options...] -c [path]",
String
"zeolite [options...] -r [paths...]",
String
"zeolite [options...] -R [paths...]",
String
"zeolite [options...] -t [paths...]",
String
"",
String
"zeolite [options...] --templates [paths...]",
String
"zeolite --get-path",
String
"zeolite --show-deps [paths...]",
String
"zeolite --version",
String
"",
String
"Normal Modes:",
String
" -c: Only compile the individual files. (default)",
String
" -m [category(.function)]: Create a binary that executes the function.",
String
" --fast [category(.function)] [.0rx source]: Create a binary without needing a module.",
String
" -r: Recompile using the previous compilation options.",
String
" -R: Recursively recompile using the previous compilation options.",
String
" -t: Only execute tests, without other compilation.",
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 compilation instead of recompiling with -r/-R.",
String
" -i [path]: A single source path to include as a *public* dependency.",
String
" -I [path]: A single source path 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 the specified source files.",
String
"",
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
"[path(s...)]: Path(s) containing source or dependency files.",
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] -> CompileMode
ExecuteTests []) 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 -> String -> [String] -> CompileMode
CompileBinary (String -> CategoryName
CategoryName String
t) (String -> FunctionName
FunctionName String
fn) 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 (CompileBinary CategoryName
t FunctionName
fn 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 -> String -> [String] -> CompileMode
CompileBinary CategoryName
t FunctionName
fn 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) = 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] -> CompileMode
ExecuteTests ([String] -> CompileMode) -> [String] -> CompileMode
forall a b. (a -> b) -> a -> b
$ [String]
tp [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [String
d]) 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
| (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