{- -----------------------------------------------------------------------------
Copyright 2020-2021 Kevin P. Barry

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
----------------------------------------------------------------------------- -}

-- Author: Kevin P. Barry [ta0kira@gmail.com]

module Cli.ParseCompileOptions (
  optionHelpText,
  parseCompileOptions,
  validateCompileOptions,
) where

import Control.Monad (when)
import Lens.Micro
import Text.Regex.TDFA
import qualified Data.Set as Set

import Base.CompilerError
import Cli.CompileOptions
import Module.ProcessMetadata (isPrivateSource,isPublicSource,isTestSource)
import Types.TypeCategory (FunctionName(..))
import Types.TypeInstance (CategoryName(..))


optionHelpText :: [String]
optionHelpText :: [String]
optionHelpText = [
    String
"",
    String
"Compilation Modes:",
    String
"",
    String
"  zeolite [options...] --fast [category(.function)] [.0rx source]",
    String
"    Create a binary without needing a config.",
    String
"",
    String
"  zeolite [options...] -r [modules...]",
    String
"    Recompile using each module's .zeolite-module config.",
    String
"",
    String
"  zeolite [options...] -R [modules...]",
    String
"    Recursively recompile using each module's .zeolite-module config.",
    String
"",
    String
"  zeolite [options...] -t (--log-traces [filename]) [modules...] (tests...)",
    String
"    Only execute tests, without other compilation.",
    String
"",
    String
"Configuration Modes:",
    String
"",
    String
"  zeolite [options...] -c [module]",
    String
"    Create a new .zeolite-module config for a libary module.",
    String
"",
    String
"  zeolite [options...] -m [category(.function)] (-o [binary]) [module]",
    String
"    Create a new .zeolite-module config for a binary module.",
    String
"",
    String
"Special Modes:",
    String
"",
    String
"  zeolite [options...] --templates [modules...]",
    String
"    Only create C++ templates for undefined categories in .0rp sources.",
    String
"",
    String
"  zeolite (-p [path]) --clean [modules...]",
    String
"    Remove all cached data for the modules.",
    String
"",
    String
"  zeolite (-p [path]) --missed-lines [filename] [modules...]",
    String
"    List all lines missed in a log file taken from --log-traces.",
    String
"",
    String
"  zeolite (-p [path]) --show-deps [modules...]",
    String
"    Show category dependencies for the modules.",
    String
"",
    String
"  zeolite (-p [path]) --show-traces [modules...]",
    String
"    Show the possible code traces for the modules.",
    String
"",
    String
"Compiler Info:",
    String
"",
    String
"  zeolite --get-path",
    String
"    Show the data path and immediately exit.",
    String
"",
    String
"  zeolite --version",
    String
"    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
"  -j [# parallel]: Parallel execution of compilation subprocesses.",
    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
"  test: Name of a .0rt file to limit test execution to.",
    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
"",
    String
"  # Display the contexts of all code lines missed by tests for mylibrary.",
    String
"  zeolite -t --log-traces traces.csv mylibrary",
    String
"  zeolite --missed-lines traces.csv mylibrary",
    String
""
  ]

defaultMainFunc :: String
defaultMainFunc :: String
defaultMainFunc = String
"run"

optionsWithArgs :: Set.Set Char
optionsWithArgs :: Set Char
optionsWithArgs = String -> Set Char
forall a. Ord a => [a] -> Set a
Set.fromList String
"iIjmop"

splitOptionClusters :: [String] -> [String]
splitOptionClusters :: [String] -> [String]
splitOptionClusters (o :: String
o@(Char
'-':Char
c:String
rest):[String]
os)
  | Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'-' Bool -> Bool -> Bool
|| String -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
rest          = String
o String -> [String] -> [String]
forall a. a -> [a] -> [a]
: [String] -> [String]
splitOptionClusters [String]
os
  | Char
c Char -> Set Char -> Bool
forall a. Ord a => a -> Set a -> Bool
`Set.member` Set Char
optionsWithArgs = (Char
'-'Char -> String -> String
forall a. a -> [a] -> [a]
:Char
cChar -> String -> String
forall a. a -> [a] -> [a]
:[]) String -> [String] -> [String]
forall a. a -> [a] -> [a]
: String
rest String -> [String] -> [String]
forall a. a -> [a] -> [a]
: [String] -> [String]
splitOptionClusters [String]
os
  | Bool
otherwise                      = (Char
'-'Char -> String -> String
forall a. a -> [a] -> [a]
:Char
cChar -> String -> String
forall a. a -> [a] -> [a]
:[]) String -> [String] -> [String]
forall a. a -> [a] -> [a]
: [String] -> [String]
splitOptionClusters ((Char
'-'Char -> String -> String
forall a. a -> [a] -> [a]
:String
rest)String -> [String] -> [String]
forall a. a -> [a] -> [a]
:[String]
os)
splitOptionClusters (String
o:[String]
os) = String
o String -> [String] -> [String]
forall a. a -> [a] -> [a]
: [String] -> [String]
splitOptionClusters [String]
os
splitOptionClusters [] = []

parseCompileOptions :: CollectErrorsM m => [String] -> m CompileOptions
parseCompileOptions :: forall (m :: * -> *).
CollectErrorsM m =>
[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]) ([String] -> [(Int, String)])
-> ([String] -> [String]) -> [String] -> [(Int, String)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> [String]
splitOptionClusters where
  parseAll :: CompileOptions -> [(a, String)] -> m CompileOptions
parseAll CompileOptions
co [] = CompileOptions -> m CompileOptions
forall a. a -> m a
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 a. 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 a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
    | String -> Bool
forall a. [a] -> 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 a. a -> m a
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 a. a -> m a
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
opts ((a
_,String
"-h"):[(a, String)]
os) =
    ([(a, String)], CompileOptions)
-> m ([(a, String)], CompileOptions)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ([(a, String)]
os,CompileOptions
opts CompileOptions
-> (CompileOptions -> CompileOptions) -> CompileOptions
forall a b. a -> (a -> b) -> b
& (HelpMode -> Identity HelpMode)
-> CompileOptions -> Identity CompileOptions
Lens' CompileOptions HelpMode
coHelp ((HelpMode -> Identity HelpMode)
 -> CompileOptions -> Identity CompileOptions)
-> HelpMode -> CompileOptions -> CompileOptions
forall s t a b. ASetter s t a b -> b -> s -> t
.~ HelpMode
HelpNeeded)

  parseSingle CompileOptions
opts ((a
_,String
"-f"):[(a, String)]
os) =
    ([(a, String)], CompileOptions)
-> m ([(a, String)], CompileOptions)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ([(a, String)]
os,CompileOptions
opts CompileOptions
-> (CompileOptions -> CompileOptions) -> CompileOptions
forall a b. a -> (a -> b) -> b
& (ForceMode -> Identity ForceMode)
-> CompileOptions -> Identity CompileOptions
Lens' CompileOptions ForceMode
coForce ((ForceMode -> Identity ForceMode)
 -> CompileOptions -> Identity CompileOptions)
-> ForceMode -> CompileOptions -> CompileOptions
forall s t a b. ASetter s t a b -> b -> s -> t
.~ ForceMode
ForceAll)

  parseSingle CompileOptions
opts ((a
n,String
"-c"):[(a, String)]
os)
    | (CompileOptions
opts CompileOptions
-> Getting CompileMode CompileOptions CompileMode -> CompileMode
forall s a. s -> Getting a s a -> a
^. Getting CompileMode CompileOptions CompileMode
Lens' CompileOptions CompileMode
coMode) 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 a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ([(a, String)]
os,CompileOptions
opts CompileOptions
-> (CompileOptions -> CompileOptions) -> CompileOptions
forall a b. a -> (a -> b) -> b
& (HelpMode -> Identity HelpMode)
-> CompileOptions -> Identity CompileOptions
Lens' CompileOptions HelpMode
coHelp ((HelpMode -> Identity HelpMode)
 -> CompileOptions -> Identity CompileOptions)
-> (HelpMode -> HelpMode) -> CompileOptions -> CompileOptions
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ HelpMode -> HelpMode
maybeDisableHelp CompileOptions
-> (CompileOptions -> CompileOptions) -> CompileOptions
forall a b. a -> (a -> b) -> b
& (CompileMode -> Identity CompileMode)
-> CompileOptions -> Identity CompileOptions
Lens' CompileOptions CompileMode
coMode ((CompileMode -> Identity CompileMode)
 -> CompileOptions -> Identity CompileOptions)
-> CompileMode -> CompileOptions -> CompileOptions
forall s t a b. ASetter s t a b -> b -> s -> t
.~ ([String] -> CompileMode
CompileIncremental []))

  parseSingle CompileOptions
opts ((a
n,String
"-r"):[(a, String)]
os)
    | (CompileOptions
opts CompileOptions
-> Getting CompileMode CompileOptions CompileMode -> CompileMode
forall s a. s -> Getting a s a -> a
^. Getting CompileMode CompileOptions CompileMode
Lens' CompileOptions CompileMode
coMode) 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 a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ([(a, String)]
os,CompileOptions
opts CompileOptions
-> (CompileOptions -> CompileOptions) -> CompileOptions
forall a b. a -> (a -> b) -> b
& (HelpMode -> Identity HelpMode)
-> CompileOptions -> Identity CompileOptions
Lens' CompileOptions HelpMode
coHelp ((HelpMode -> Identity HelpMode)
 -> CompileOptions -> Identity CompileOptions)
-> (HelpMode -> HelpMode) -> CompileOptions -> CompileOptions
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ HelpMode -> HelpMode
maybeDisableHelp CompileOptions
-> (CompileOptions -> CompileOptions) -> CompileOptions
forall a b. a -> (a -> b) -> b
& (CompileMode -> Identity CompileMode)
-> CompileOptions -> Identity CompileOptions
Lens' CompileOptions CompileMode
coMode ((CompileMode -> Identity CompileMode)
 -> CompileOptions -> Identity CompileOptions)
-> CompileMode -> CompileOptions -> CompileOptions
forall s t a b. ASetter s t a b -> b -> s -> t
.~ CompileMode
CompileRecompile)

  parseSingle CompileOptions
opts ((a
n,String
"-R"):[(a, String)]
os)
    | (CompileOptions
opts CompileOptions
-> Getting CompileMode CompileOptions CompileMode -> CompileMode
forall s a. s -> Getting a s a -> a
^. Getting CompileMode CompileOptions CompileMode
Lens' CompileOptions CompileMode
coMode) 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 a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ([(a, String)]
os,CompileOptions
opts CompileOptions
-> (CompileOptions -> CompileOptions) -> CompileOptions
forall a b. a -> (a -> b) -> b
& (HelpMode -> Identity HelpMode)
-> CompileOptions -> Identity CompileOptions
Lens' CompileOptions HelpMode
coHelp ((HelpMode -> Identity HelpMode)
 -> CompileOptions -> Identity CompileOptions)
-> (HelpMode -> HelpMode) -> CompileOptions -> CompileOptions
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ HelpMode -> HelpMode
maybeDisableHelp CompileOptions
-> (CompileOptions -> CompileOptions) -> CompileOptions
forall a b. a -> (a -> b) -> b
& (CompileMode -> Identity CompileMode)
-> CompileOptions -> Identity CompileOptions
Lens' CompileOptions CompileMode
coMode ((CompileMode -> Identity CompileMode)
 -> CompileOptions -> Identity CompileOptions)
-> CompileMode -> CompileOptions -> CompileOptions
forall s t a b. ASetter s t a b -> b -> s -> t
.~ CompileMode
CompileRecompileRecursive)

  parseSingle CompileOptions
opts ((a
n,String
"-t"):[(a, String)]
os)
    | (CompileOptions
opts CompileOptions
-> Getting CompileMode CompileOptions CompileMode -> CompileMode
forall s a. s -> Getting a s a -> a
^. Getting CompileMode CompileOptions CompileMode
Lens' CompileOptions CompileMode
coMode) 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 a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ([(a, String)]
os,CompileOptions
opts CompileOptions
-> (CompileOptions -> CompileOptions) -> CompileOptions
forall a b. a -> (a -> b) -> b
& (HelpMode -> Identity HelpMode)
-> CompileOptions -> Identity CompileOptions
Lens' CompileOptions HelpMode
coHelp ((HelpMode -> Identity HelpMode)
 -> CompileOptions -> Identity CompileOptions)
-> (HelpMode -> HelpMode) -> CompileOptions -> CompileOptions
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ HelpMode -> HelpMode
maybeDisableHelp CompileOptions
-> (CompileOptions -> CompileOptions) -> CompileOptions
forall a b. a -> (a -> b) -> b
& (CompileMode -> Identity CompileMode)
-> CompileOptions -> Identity CompileOptions
Lens' CompileOptions CompileMode
coMode ((CompileMode -> Identity CompileMode)
 -> CompileOptions -> Identity CompileOptions)
-> CompileMode -> CompileOptions -> CompileOptions
forall s t a b. ASetter s t a b -> b -> s -> t
.~ ([String] -> Maybe String -> CompileMode
ExecuteTests [] Maybe String
forall a. Maybe a
Nothing))

  parseSingle CompileOptions
opts ((a
n,String
"--templates"):[(a, String)]
os)
    | (CompileOptions
opts CompileOptions
-> Getting CompileMode CompileOptions CompileMode -> CompileMode
forall s a. s -> Getting a s a -> a
^. Getting CompileMode CompileOptions CompileMode
Lens' CompileOptions CompileMode
coMode) 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
"--templates" String
"Compiler mode already set."
    | Bool
otherwise = ([(a, String)], CompileOptions)
-> m ([(a, String)], CompileOptions)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ([(a, String)]
os,CompileOptions
opts CompileOptions
-> (CompileOptions -> CompileOptions) -> CompileOptions
forall a b. a -> (a -> b) -> b
& (HelpMode -> Identity HelpMode)
-> CompileOptions -> Identity CompileOptions
Lens' CompileOptions HelpMode
coHelp ((HelpMode -> Identity HelpMode)
 -> CompileOptions -> Identity CompileOptions)
-> (HelpMode -> HelpMode) -> CompileOptions -> CompileOptions
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ HelpMode -> HelpMode
maybeDisableHelp CompileOptions
-> (CompileOptions -> CompileOptions) -> CompileOptions
forall a b. a -> (a -> b) -> b
& (CompileMode -> Identity CompileMode)
-> CompileOptions -> Identity CompileOptions
Lens' CompileOptions CompileMode
coMode ((CompileMode -> Identity CompileMode)
 -> CompileOptions -> Identity CompileOptions)
-> CompileMode -> CompileOptions -> CompileOptions
forall s t a b. ASetter s t a b -> b -> s -> t
.~ CompileMode
CreateTemplates)

  parseSingle CompileOptions
opts ((a
n,String
"-m"):[(a, String)]
os)
    | (CompileOptions
opts CompileOptions
-> Getting CompileMode CompileOptions CompileMode -> CompileMode
forall s a. s -> Getting a s a -> a
^. Getting CompileMode CompileOptions CompileMode
Lens' CompileOptions CompileMode
coMode) 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 a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ([(a, String)]
os2,CompileOptions
opts CompileOptions
-> (CompileOptions -> CompileOptions) -> CompileOptions
forall a b. a -> (a -> b) -> b
& (HelpMode -> Identity HelpMode)
-> CompileOptions -> Identity CompileOptions
Lens' CompileOptions HelpMode
coHelp ((HelpMode -> Identity HelpMode)
 -> CompileOptions -> Identity CompileOptions)
-> (HelpMode -> HelpMode) -> CompileOptions -> CompileOptions
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ HelpMode -> HelpMode
maybeDisableHelp CompileOptions
-> (CompileOptions -> CompileOptions) -> CompileOptions
forall a b. a -> (a -> b) -> b
& (CompileMode -> Identity CompileMode)
-> CompileOptions -> Identity CompileOptions
Lens' CompileOptions CompileMode
coMode ((CompileMode -> Identity CompileMode)
 -> CompileOptions -> Identity CompileOptions)
-> CompileMode -> CompileOptions -> CompileOptions
forall s t a b. ASetter s t a b -> b -> s -> t
.~ CompileMode
m2) where
          check :: (a, String) -> m (a, String)
check (a
t,String
"")     = (a, String) -> m (a, String)
forall a. a -> m a
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 a. a -> m a
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
opts ((a
n,String
"--fast"):[(a, String)]
os)
    | (CompileOptions
opts CompileOptions
-> Getting CompileMode CompileOptions CompileMode -> CompileMode
forall s a. s -> Getting a s a -> a
^. Getting CompileMode CompileOptions CompileMode
Lens' CompileOptions CompileMode
coMode) 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 -> Bool
isPrivateSource 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 a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ([(a, String)]
os2,CompileOptions
opts CompileOptions
-> (CompileOptions -> CompileOptions) -> CompileOptions
forall a b. a -> (a -> b) -> b
& (HelpMode -> Identity HelpMode)
-> CompileOptions -> Identity CompileOptions
Lens' CompileOptions HelpMode
coHelp ((HelpMode -> Identity HelpMode)
 -> CompileOptions -> Identity CompileOptions)
-> (HelpMode -> HelpMode) -> CompileOptions -> CompileOptions
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ HelpMode -> HelpMode
maybeDisableHelp CompileOptions
-> (CompileOptions -> CompileOptions) -> CompileOptions
forall a b. a -> (a -> b) -> b
& (CompileMode -> Identity CompileMode)
-> CompileOptions -> Identity CompileOptions
Lens' CompileOptions CompileMode
coMode ((CompileMode -> Identity CompileMode)
 -> CompileOptions -> Identity CompileOptions)
-> CompileMode -> CompileOptions -> CompileOptions
forall s t a b. ASetter s t a b -> b -> s -> t
.~ CompileMode
m2) where
          check :: (a, String) -> m (a, String)
check (a
t,String
"")     = (a, String) -> m (a, String)
forall a. a -> m a
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 a. a -> m a
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
opts ((a
n,String
"--log-traces"):[(a, String)]
os) = CompileMode -> [(a, String)] -> m ([(a, String)], CompileOptions)
forall {m :: * -> *} {a}.
ErrorContextM m =>
CompileMode -> [(a, String)] -> m ([(a, String)], CompileOptions)
update (CompileOptions
opts CompileOptions
-> Getting CompileMode CompileOptions CompileMode -> CompileMode
forall s a. s -> Getting a s a -> a
^. Getting CompileMode CompileOptions CompileMode
Lens' CompileOptions CompileMode
coMode) [(a, String)]
os where
    update :: CompileMode -> [(a, String)] -> m ([(a, String)], CompileOptions)
update (ExecuteTests [String]
tp Maybe String
cl) ((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 a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ([(a, String)]
os2,CompileOptions
opts CompileOptions
-> (CompileOptions -> CompileOptions) -> CompileOptions
forall a b. a -> (a -> b) -> b
& (HelpMode -> Identity HelpMode)
-> CompileOptions -> Identity CompileOptions
Lens' CompileOptions HelpMode
coHelp ((HelpMode -> Identity HelpMode)
 -> CompileOptions -> Identity CompileOptions)
-> (HelpMode -> HelpMode) -> CompileOptions -> CompileOptions
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ HelpMode -> HelpMode
maybeDisableHelp CompileOptions
-> (CompileOptions -> CompileOptions) -> CompileOptions
forall a b. a -> (a -> b) -> b
& (CompileMode -> Identity CompileMode)
-> CompileOptions -> Identity CompileOptions
Lens' CompileOptions CompileMode
coMode ((CompileMode -> Identity CompileMode)
 -> CompileOptions -> Identity CompileOptions)
-> CompileMode -> CompileOptions -> CompileOptions
forall s t a b. ASetter s t a b -> b -> s -> t
.~ ([String] -> Maybe String -> CompileMode
ExecuteTests [String]
tp (String -> Maybe String
forall a. a -> Maybe a
Just String
cl2)))
    update CompileMode
_ [] = 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."
    update CompileMode
_ [(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
opts ((a
n,String
"-o"):[(a, String)]
os) = CompileMode -> [(a, String)] -> m ([(a, String)], CompileOptions)
forall {m :: * -> *} {a}.
(ErrorContextM m, Show a) =>
CompileMode -> [(a, String)] -> m ([(a, String)], CompileOptions)
update (CompileOptions
opts CompileOptions
-> Getting CompileMode CompileOptions CompileMode -> CompileMode
forall s a. s -> Getting a s a -> a
^. Getting CompileMode CompileOptions CompileMode
Lens' CompileOptions CompileMode
coMode) [(a, String)]
os where
    update :: CompileMode -> [(a, String)] -> m ([(a, String)], CompileOptions)
update (CompileBinary CategoryName
t FunctionName
fn LinkerMode
lm String
o [String]
lf) ((a
n2,String
o2):[(a, String)]
os2)
      | Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ String -> Bool
forall a. [a] -> 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 = 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 a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ([(a, String)]
os2,CompileOptions
opts CompileOptions
-> (CompileOptions -> CompileOptions) -> CompileOptions
forall a b. a -> (a -> b) -> b
& (HelpMode -> Identity HelpMode)
-> CompileOptions -> Identity CompileOptions
Lens' CompileOptions HelpMode
coHelp ((HelpMode -> Identity HelpMode)
 -> CompileOptions -> Identity CompileOptions)
-> (HelpMode -> HelpMode) -> CompileOptions -> CompileOptions
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ HelpMode -> HelpMode
maybeDisableHelp CompileOptions
-> (CompileOptions -> CompileOptions) -> CompileOptions
forall a b. a -> (a -> b) -> b
& (CompileMode -> Identity CompileMode)
-> CompileOptions -> Identity CompileOptions
Lens' CompileOptions CompileMode
coMode ((CompileMode -> Identity CompileMode)
 -> CompileOptions -> Identity CompileOptions)
-> CompileMode -> CompileOptions -> CompileOptions
forall s t a b. ASetter s t a b -> b -> s -> t
.~ (CategoryName
-> FunctionName -> LinkerMode -> String -> [String] -> CompileMode
CompileBinary CategoryName
t FunctionName
fn LinkerMode
lm String
o2 [String]
lf))
    update CompileMode
_ [] = 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."
    update CompileMode
_ [(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
opts ((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 -> Bool
isPublicSource  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 -> Bool
isPrivateSource 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 -> Bool
isTestSource    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 a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ([(a, String)]
os2,CompileOptions
opts CompileOptions
-> (CompileOptions -> CompileOptions) -> CompileOptions
forall a b. a -> (a -> b) -> b
& (HelpMode -> Identity HelpMode)
-> CompileOptions -> Identity CompileOptions
Lens' CompileOptions HelpMode
coHelp ((HelpMode -> Identity HelpMode)
 -> CompileOptions -> Identity CompileOptions)
-> (HelpMode -> HelpMode) -> CompileOptions -> CompileOptions
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ HelpMode -> HelpMode
maybeDisableHelp CompileOptions
-> (CompileOptions -> CompileOptions) -> CompileOptions
forall a b. a -> (a -> b) -> b
& ([String] -> Identity [String])
-> CompileOptions -> Identity CompileOptions
Lens' CompileOptions [String]
coPublicDeps (([String] -> Identity [String])
 -> CompileOptions -> Identity CompileOptions)
-> [String] -> CompileOptions -> CompileOptions
forall a s t. Monoid a => ASetter s t a a -> a -> s -> t
<>~ [String
d])
    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
opts ((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 -> Bool
isPublicSource  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 -> Bool
isPrivateSource 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 -> Bool
isTestSource    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 a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ([(a, String)]
os2,CompileOptions
opts CompileOptions
-> (CompileOptions -> CompileOptions) -> CompileOptions
forall a b. a -> (a -> b) -> b
& (HelpMode -> Identity HelpMode)
-> CompileOptions -> Identity CompileOptions
Lens' CompileOptions HelpMode
coHelp ((HelpMode -> Identity HelpMode)
 -> CompileOptions -> Identity CompileOptions)
-> (HelpMode -> HelpMode) -> CompileOptions -> CompileOptions
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ HelpMode -> HelpMode
maybeDisableHelp CompileOptions
-> (CompileOptions -> CompileOptions) -> CompileOptions
forall a b. a -> (a -> b) -> b
& ([String] -> Identity [String])
-> CompileOptions -> Identity CompileOptions
Lens' CompileOptions [String]
coPrivateDeps (([String] -> Identity [String])
 -> CompileOptions -> Identity CompileOptions)
-> [String] -> CompileOptions -> CompileOptions
forall a s t. Monoid a => ASetter s t a a -> a -> s -> t
<>~ [String
d])
    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
opts ((a
n,String
"-p"):[(a, String)]
os)
    | Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ String -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null (CompileOptions
opts CompileOptions -> Getting String CompileOptions String -> String
forall s a. s -> Getting a s a -> a
^. Getting String CompileOptions String
Lens' CompileOptions String
coSourcePrefix) = 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 a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ([(a, String)]
os2,CompileOptions
opts CompileOptions
-> (CompileOptions -> CompileOptions) -> CompileOptions
forall a b. a -> (a -> b) -> b
& (HelpMode -> Identity HelpMode)
-> CompileOptions -> Identity CompileOptions
Lens' CompileOptions HelpMode
coHelp ((HelpMode -> Identity HelpMode)
 -> CompileOptions -> Identity CompileOptions)
-> (HelpMode -> HelpMode) -> CompileOptions -> CompileOptions
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ HelpMode -> HelpMode
maybeDisableHelp CompileOptions
-> (CompileOptions -> CompileOptions) -> CompileOptions
forall a b. a -> (a -> b) -> b
& (String -> Identity String)
-> CompileOptions -> Identity CompileOptions
Lens' CompileOptions String
coSourcePrefix ((String -> Identity String)
 -> CompileOptions -> Identity CompileOptions)
-> String -> CompileOptions -> CompileOptions
forall s t a b. ASetter s t a b -> b -> s -> t
.~ String
p2)
      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
opts ((a
n,String
"-j"):[(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
k):[(a, String)]
os2) = do
      case ReadS Int
forall a. Read a => ReadS a
reads String
k of
           [(Int
pn,[])] -> if Int
pn Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0
                           then ([(a, String)], CompileOptions)
-> m ([(a, String)], CompileOptions)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ([(a, String)]
os2,CompileOptions
opts CompileOptions
-> (CompileOptions -> CompileOptions) -> CompileOptions
forall a b. a -> (a -> b) -> b
& (HelpMode -> Identity HelpMode)
-> CompileOptions -> Identity CompileOptions
Lens' CompileOptions HelpMode
coHelp ((HelpMode -> Identity HelpMode)
 -> CompileOptions -> Identity CompileOptions)
-> (HelpMode -> HelpMode) -> CompileOptions -> CompileOptions
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ HelpMode -> HelpMode
maybeDisableHelp CompileOptions
-> (CompileOptions -> CompileOptions) -> CompileOptions
forall a b. a -> (a -> b) -> b
& (Int -> Identity Int) -> CompileOptions -> Identity CompileOptions
Lens' CompileOptions Int
coParallel ((Int -> Identity Int)
 -> CompileOptions -> Identity CompileOptions)
-> Int -> CompileOptions -> CompileOptions
forall s t a b. ASetter s t a b -> b -> s -> t
.~ Int
pn)
                           else a -> String -> String -> m ([(a, String)], CompileOptions)
forall {m :: * -> *} {a} {a}.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n2 String
k String
"Must be > 0."
           [(Int, String)]
_ -> a -> String -> String -> m ([(a, String)], CompileOptions)
forall {m :: * -> *} {a} {a}.
(ErrorContextM m, Show a) =>
a -> String -> String -> m a
argError a
n2 String
k String
"Not a valid integer."
    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
"-j" String
"Requires an integer > 0."

  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
opts ((a
n,String
d):[(a, String)]
os)
      | String -> Bool
isPublicSource  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 -> Bool
isPrivateSource 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 -> Bool
isTestSource    String
d = do
        case CompileOptions
opts CompileOptions
-> Getting CompileMode CompileOptions CompileMode -> CompileMode
forall s a. s -> Getting a s a -> a
^. Getting CompileMode CompileOptions CompileMode
Lens' CompileOptions CompileMode
coMode of
             ExecuteTests [String]
tp Maybe String
cl -> 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 a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ([(a, String)]
os,CompileOptions
opts CompileOptions
-> (CompileOptions -> CompileOptions) -> CompileOptions
forall a b. a -> (a -> b) -> b
& (HelpMode -> Identity HelpMode)
-> CompileOptions -> Identity CompileOptions
Lens' CompileOptions HelpMode
coHelp ((HelpMode -> Identity HelpMode)
 -> CompileOptions -> Identity CompileOptions)
-> (HelpMode -> HelpMode) -> CompileOptions -> CompileOptions
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ HelpMode -> HelpMode
maybeDisableHelp CompileOptions
-> (CompileOptions -> CompileOptions) -> CompileOptions
forall a b. a -> (a -> b) -> b
& (CompileMode -> Identity CompileMode)
-> CompileOptions -> Identity CompileOptions
Lens' CompileOptions CompileMode
coMode ((CompileMode -> Identity CompileMode)
 -> CompileOptions -> Identity CompileOptions)
-> CompileMode -> CompileOptions -> CompileOptions
forall s t a b. ASetter s t a b -> b -> s -> t
.~ ([String] -> Maybe String -> CompileMode
ExecuteTests ([String]
tp [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [String
d]) Maybe String
cl))
             CompileMode
_ -> 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
"Test mode (-t) must be enabled before listing any .0rt test files."
      | 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 a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ([(a, String)]
os,CompileOptions
opts CompileOptions
-> (CompileOptions -> CompileOptions) -> CompileOptions
forall a b. a -> (a -> b) -> b
& (HelpMode -> Identity HelpMode)
-> CompileOptions -> Identity CompileOptions
Lens' CompileOptions HelpMode
coHelp ((HelpMode -> Identity HelpMode)
 -> CompileOptions -> Identity CompileOptions)
-> (HelpMode -> HelpMode) -> CompileOptions -> CompileOptions
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ HelpMode -> HelpMode
maybeDisableHelp CompileOptions
-> (CompileOptions -> CompileOptions) -> CompileOptions
forall a b. a -> (a -> b) -> b
& ([String] -> Identity [String])
-> CompileOptions -> Identity CompileOptions
Lens' CompileOptions [String]
coPaths (([String] -> Identity [String])
 -> CompileOptions -> Identity CompileOptions)
-> [String] -> CompileOptions -> CompileOptions
forall a s t. Monoid a => ASetter s t a a -> a -> s -> t
<>~ [String
d])

validateCompileOptions :: CollectErrorsM m => CompileOptions -> m CompileOptions
validateCompileOptions :: forall (m :: * -> *).
CollectErrorsM m =>
CompileOptions -> m CompileOptions
validateCompileOptions CompileOptions
opts
  | (CompileOptions
opts CompileOptions
-> Getting HelpMode CompileOptions HelpMode -> HelpMode
forall s a. s -> Getting a s a -> a
^. Getting HelpMode CompileOptions HelpMode
Lens' CompileOptions HelpMode
coHelp) HelpMode -> HelpMode -> Bool
forall a. Eq a => a -> a -> Bool
/= HelpMode
HelpNotNeeded = CompileOptions -> m CompileOptions
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return CompileOptions
opts

  | CompileMode -> Bool
isCompileUnspecified (CompileOptions
opts CompileOptions
-> Getting CompileMode CompileOptions CompileMode -> CompileMode
forall s a. s -> Getting a s a -> a
^. Getting CompileMode CompileOptions CompileMode
Lens' CompileOptions CompileMode
coMode) =
    String -> m CompileOptions
forall a. String -> m a
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 a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null ([String] -> Bool) -> [String] -> Bool
forall a b. (a -> b) -> a -> b
$ (CompileOptions
opts CompileOptions
-> Getting [String] CompileOptions [String] -> [String]
forall s a. s -> Getting a s a -> a
^. Getting [String] CompileOptions [String]
Lens' CompileOptions [String]
coPublicDeps) [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ (CompileOptions
opts CompileOptions
-> Getting [String] CompileOptions [String] -> [String]
forall s a. s -> Getting a s a -> a
^. Getting [String] CompileOptions [String]
Lens' CompileOptions [String]
coPrivateDeps)) Bool -> Bool -> Bool
&& (CompileMode -> Bool
isExecuteTests (CompileOptions
opts CompileOptions
-> Getting CompileMode CompileOptions CompileMode -> CompileMode
forall s a. s -> Getting a s a -> a
^. Getting CompileMode CompileOptions CompileMode
Lens' CompileOptions CompileMode
coMode)) =
    String -> m CompileOptions
forall a. String -> m a
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 a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null ([String] -> Bool) -> [String] -> Bool
forall a b. (a -> b) -> a -> b
$ (CompileOptions
opts CompileOptions
-> Getting [String] CompileOptions [String] -> [String]
forall s a. s -> Getting a s a -> a
^. Getting [String] CompileOptions [String]
Lens' CompileOptions [String]
coPublicDeps) [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ (CompileOptions
opts CompileOptions
-> Getting [String] CompileOptions [String] -> [String]
forall s a. s -> Getting a s a -> a
^. Getting [String] CompileOptions [String]
Lens' CompileOptions [String]
coPrivateDeps)) Bool -> Bool -> Bool
&& (CompileMode -> Bool
isCompileRecompile (CompileOptions
opts CompileOptions
-> Getting CompileMode CompileOptions CompileMode -> CompileMode
forall s a. s -> Getting a s a -> a
^. Getting CompileMode CompileOptions CompileMode
Lens' CompileOptions CompileMode
coMode)) =
    String -> m CompileOptions
forall a. String -> m a
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 a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (CompileOptions
opts CompileOptions
-> Getting [String] CompileOptions [String] -> [String]
forall s a. s -> Getting a s a -> a
^. Getting [String] CompileOptions [String]
Lens' CompileOptions [String]
coPaths) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
0) Bool -> Bool -> Bool
&& (CompileMode -> Bool
isCompileFast (CompileOptions
opts CompileOptions
-> Getting CompileMode CompileOptions CompileMode -> CompileMode
forall s a. s -> Getting a s a -> a
^. Getting CompileMode CompileOptions CompileMode
Lens' CompileOptions CompileMode
coMode)) =
    String -> m CompileOptions
forall a. String -> m a
forall (m :: * -> *) a. ErrorContextM m => String -> m a
compilerErrorM String
"Input path is not allowed with fast mode (--fast)."
  | [String] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null (CompileOptions
opts CompileOptions
-> Getting [String] CompileOptions [String] -> [String]
forall s a. s -> Getting a s a -> a
^. Getting [String] CompileOptions [String]
Lens' CompileOptions [String]
coPaths) Bool -> Bool -> Bool
&& (Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ CompileMode -> Bool
isCompileFast (CompileOptions
opts CompileOptions
-> Getting CompileMode CompileOptions CompileMode -> CompileMode
forall s a. s -> Getting a s a -> a
^. Getting CompileMode CompileOptions CompileMode
Lens' CompileOptions CompileMode
coMode)) =
    String -> m CompileOptions
forall a. String -> m a
forall (m :: * -> *) a. ErrorContextM m => String -> m a
compilerErrorM String
"Please specify at least one input path."
  | ([String] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (CompileOptions
opts CompileOptions
-> Getting [String] CompileOptions [String] -> [String]
forall s a. s -> Getting a s a -> a
^. Getting [String] CompileOptions [String]
Lens' CompileOptions [String]
coPaths) 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 (CompileOptions
opts CompileOptions
-> Getting CompileMode CompileOptions CompileMode -> CompileMode
forall s a. s -> Getting a s a -> a
^. Getting CompileMode CompileOptions CompileMode
Lens' CompileOptions CompileMode
coMode)) Bool -> Bool -> Bool
&& (Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ CompileMode -> Bool
isExecuteTests (CompileOptions
opts CompileOptions
-> Getting CompileMode CompileOptions CompileMode -> CompileMode
forall s a. s -> Getting a s a -> a
^. Getting CompileMode CompileOptions CompileMode
Lens' CompileOptions CompileMode
coMode)) =
    String -> m CompileOptions
forall a. String -> m a
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 = do
    Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when ((CompileOptions
opts CompileOptions -> Getting Int CompileOptions Int -> Int
forall s a. s -> Getting a s a -> a
^. Getting Int CompileOptions Int
Lens' CompileOptions Int
coParallel) Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0 Bool -> Bool -> Bool
&& Bool -> Bool
not (CompileMode -> Bool
isCompileRecompile (CompileOptions
opts CompileOptions
-> Getting CompileMode CompileOptions CompileMode -> CompileMode
forall s a. s -> Getting a s a -> a
^. Getting CompileMode CompileOptions CompileMode
Lens' CompileOptions CompileMode
coMode)) Bool -> Bool -> Bool
&& Bool -> Bool
not (CompileMode -> Bool
isCompileFast (CompileOptions
opts CompileOptions
-> Getting CompileMode CompileOptions CompileMode -> CompileMode
forall s a. s -> Getting a s a -> a
^. Getting CompileMode CompileOptions CompileMode
Lens' CompileOptions CompileMode
coMode))) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$
      String -> m ()
forall (m :: * -> *). ErrorContextM m => String -> m ()
compilerWarningM String
"Parallel processing (-j) has no effect outside of recompile mode (-r/-R) and fast mode (--fast)."
    CompileOptions -> m CompileOptions
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return CompileOptions
opts