mirror of
https://github.com/carp-lang/Carp.git
synced 2024-09-11 05:25:28 +03:00
Switch option parsing to optparse-applicative, remove tcc dependency.
This commit is contained in:
parent
ccb31c589a
commit
dba9ef53c3
@ -79,6 +79,7 @@ executable carp
|
||||
, filepath
|
||||
, haskeline
|
||||
, process
|
||||
, optparse-applicative
|
||||
default-language: Haskell2010
|
||||
|
||||
executable carp-header-parse
|
||||
@ -89,8 +90,8 @@ executable carp-header-parse
|
||||
, CarpHask
|
||||
, containers
|
||||
, directory
|
||||
, cmdargs
|
||||
, parsec
|
||||
, optparse-applicative
|
||||
default-language: Haskell2010
|
||||
|
||||
test-suite CarpHask-test
|
||||
|
150
app/Main.hs
150
app/Main.hs
@ -3,6 +3,7 @@ module Main where
|
||||
import qualified System.Environment as SystemEnvironment
|
||||
import System.Console.Haskeline (runInputT)
|
||||
import GHC.IO.Encoding
|
||||
import Data.Maybe
|
||||
|
||||
import ColorText
|
||||
import Obj
|
||||
@ -13,12 +14,20 @@ import Eval
|
||||
import Util
|
||||
import Path
|
||||
|
||||
import Options.Applicative
|
||||
|
||||
defaultProject :: Project
|
||||
defaultProject =
|
||||
Project { projectTitle = "Untitled"
|
||||
, projectIncludes = []
|
||||
, projectCFlags = [""]
|
||||
, projectLibFlags = [""]
|
||||
, projectCFlags = case platform of
|
||||
Windows -> ["-D_CRT_SECURE_NO_WARNINGS"]
|
||||
_ -> [ "-fPIC"
|
||||
, "-g"
|
||||
]
|
||||
, projectLibFlags = case platform of
|
||||
Windows -> []
|
||||
_ -> [ "-lm" ]
|
||||
, projectFiles = []
|
||||
, projectAlreadyLoaded = []
|
||||
, projectEchoC = False
|
||||
@ -38,8 +47,8 @@ defaultProject =
|
||||
, projectCarpSearchPaths = []
|
||||
, projectPrintTypedAST = False
|
||||
, projectCompiler = case platform of
|
||||
Windows -> "clang-cl.exe -D _CRT_SECURE_NO_WARNINGS"
|
||||
_ -> "clang -fPIC -lm -g"
|
||||
Windows -> "clang-cl.exe"
|
||||
_ -> "clang"
|
||||
, projectCore = True
|
||||
, projectEchoCompilationCommand = False
|
||||
, projectCanExecute = False
|
||||
@ -47,30 +56,38 @@ defaultProject =
|
||||
, projectGenerateOnly = False
|
||||
, projectForceReload = False
|
||||
}
|
||||
where win = platform == Windows
|
||||
|
||||
|
||||
-- | Starting point of the application.
|
||||
main :: IO ()
|
||||
main = do setLocaleEncoding utf8
|
||||
args <- SystemEnvironment.getArgs
|
||||
sysEnv <- SystemEnvironment.getEnvironment
|
||||
let (argFilesToLoad, execMode, otherOptions) = parseArgs args
|
||||
logMemory = LogMemory `elem` otherOptions
|
||||
noCore = NoCore `elem` otherOptions
|
||||
noProfile = NoProfile `elem` otherOptions
|
||||
optimize = Optimize `elem` otherOptions
|
||||
generateOnly = GenerateOnly `elem` otherOptions
|
||||
compileFast = CompileFast `elem` otherOptions
|
||||
flagsSettings p = p { projectCFlags = ["-D LOG_MEMORY" | logMemory] ++
|
||||
fullOpts <- execParser $ Options.Applicative.info (parseFull <**> helper) fullDesc
|
||||
let execMode = optExecMode fullOpts
|
||||
compOptions = optComp fullOpts
|
||||
otherOptions = optOthers fullOpts
|
||||
argFilesToLoad = optFiles fullOpts
|
||||
logMemory = otherLogMemory otherOptions
|
||||
core = otherCore otherOptions
|
||||
profile = otherProfile otherOptions
|
||||
optimize = otherOptimize otherOptions
|
||||
generateOnly = otherGenerateOnly otherOptions
|
||||
compiler = compCompiler compOptions
|
||||
cflags = compCompFlags compOptions
|
||||
ldflags = compLinkFlags compOptions
|
||||
prompt = otherPrompt otherOptions
|
||||
applySettings p = p { projectCFlags = ["-D LOG_MEMORY" | logMemory] ++
|
||||
["-O3 -D NDEBUG" | optimize] ++
|
||||
projectCFlags p
|
||||
, projectCore = not noCore
|
||||
fromMaybe (projectCFlags p) cflags
|
||||
, projectLibFlags = fromMaybe (projectLibFlags p) ldflags
|
||||
, projectCore = core
|
||||
, projectGenerateOnly = generateOnly
|
||||
, projectCarpDir = case lookup "CARP_DIR" sysEnv of
|
||||
Just carpDir -> carpDir
|
||||
Nothing -> projectCarpDir p
|
||||
, projectCompiler = if compileFast then "tcc -lm" else projectCompiler p
|
||||
, projectCarpDir = fromMaybe (projectCarpDir p) $ lookup "CARP_DIR" sysEnv
|
||||
, projectCompiler = fromMaybe (projectCompiler p) compiler
|
||||
, projectPrompt = prompt
|
||||
}
|
||||
applySettings = flagsSettings . setCustomPromptFromOptions otherOptions
|
||||
project = applySettings defaultProject
|
||||
noArray = False
|
||||
startingContext = Context
|
||||
@ -82,11 +99,11 @@ main = do setLocaleEncoding utf8
|
||||
""
|
||||
execMode
|
||||
[]
|
||||
coreModulesToLoad = if noCore then [] else coreModules (projectCarpDir project)
|
||||
coreModulesToLoad = if core then coreModules (projectCarpDir project) else []
|
||||
context <- loadFilesOnce startingContext coreModulesToLoad
|
||||
carpProfile <- configPath "profile.carp"
|
||||
hasProfile <- doesFileExist carpProfile
|
||||
context' <- if (not noProfile) && hasProfile
|
||||
context' <- if profile && hasProfile
|
||||
then loadFiles context [carpProfile]
|
||||
else return context
|
||||
finalContext <- loadFiles context' argFilesToLoad
|
||||
@ -109,44 +126,57 @@ main = do setLocaleEncoding utf8
|
||||
Check -> return ()
|
||||
|
||||
-- | Options for how to run the compiler.
|
||||
data OtherOptions = NoCore
|
||||
| NoProfile
|
||||
| LogMemory
|
||||
| Optimize
|
||||
| GenerateOnly
|
||||
| CompileFast
|
||||
| SetPrompt String
|
||||
deriving (Show, Eq)
|
||||
data FullOptions = FullOptions
|
||||
{ optExecMode :: ExecutionMode
|
||||
, optComp :: CompOptions
|
||||
, optOthers :: OtherOptions
|
||||
, optFiles :: [FilePath]
|
||||
} deriving Show
|
||||
|
||||
-- | Parse the arguments sent to the compiler from the terminal.
|
||||
-- | TODO: Switch to 'cmdargs' library for parsing these!
|
||||
parseArgs :: [String] -> ([FilePath], ExecutionMode, [OtherOptions])
|
||||
parseArgs args = parseArgsInternal [] Repl [] args
|
||||
where parseArgsInternal filesToLoad execMode otherOptions [] =
|
||||
(filesToLoad, execMode, otherOptions)
|
||||
parseArgsInternal filesToLoad execMode otherOptions (arg:restArgs) =
|
||||
case arg of
|
||||
"-b" -> parseArgsInternal filesToLoad Build otherOptions restArgs
|
||||
"-x" -> parseArgsInternal filesToLoad BuildAndRun otherOptions restArgs
|
||||
"-i" -> parseArgsInternal filesToLoad (Install (head restArgs)) otherOptions (tail restArgs)
|
||||
"--check" -> parseArgsInternal filesToLoad Check otherOptions restArgs
|
||||
"--no-core" -> parseArgsInternal filesToLoad execMode (NoCore : otherOptions) restArgs
|
||||
"--no-profile" -> parseArgsInternal filesToLoad execMode (NoProfile : otherOptions) restArgs
|
||||
"--log-memory" -> parseArgsInternal filesToLoad execMode (LogMemory : otherOptions) restArgs
|
||||
"--optimize" -> parseArgsInternal filesToLoad execMode (Optimize : otherOptions) restArgs
|
||||
"--generate-only" -> parseArgsInternal filesToLoad execMode (GenerateOnly : otherOptions) restArgs
|
||||
"--compile-fast" -> parseArgsInternal filesToLoad execMode (CompileFast : otherOptions) restArgs
|
||||
"--prompt" -> case restArgs of
|
||||
newPrompt : restRestArgs ->
|
||||
parseArgsInternal filesToLoad execMode (SetPrompt newPrompt : otherOptions) restRestArgs
|
||||
_ ->
|
||||
error "No prompt given after --prompt"
|
||||
file -> parseArgsInternal (filesToLoad ++ [file]) execMode otherOptions restArgs
|
||||
parseFull :: Parser FullOptions
|
||||
parseFull = FullOptions
|
||||
<$> parseExecMode
|
||||
<*> parseComp
|
||||
<*> parseOther
|
||||
<*> parseFiles
|
||||
|
||||
setCustomPromptFromOptions :: [OtherOptions] -> Project -> Project
|
||||
setCustomPromptFromOptions (o:os) project =
|
||||
case o of
|
||||
SetPrompt newPrompt -> setCustomPromptFromOptions os (project { projectPrompt = newPrompt })
|
||||
_ -> setCustomPromptFromOptions os project
|
||||
setCustomPromptFromOptions _ project =
|
||||
project
|
||||
data CompOptions = CompOptions
|
||||
{ compCompiler :: Maybe String
|
||||
, compCompFlags :: Maybe [String]
|
||||
, compLinkFlags :: Maybe [String]
|
||||
} deriving Show
|
||||
|
||||
parseComp :: Parser CompOptions
|
||||
parseComp = CompOptions
|
||||
<$> optional (strOption (long "cc" <> help "Set C compiler to use"))
|
||||
<*> optional (some (strOption (long "cflag" <> metavar "FLAG" <> help "Add flag to the compiler invocation")))
|
||||
<*> optional (some (strOption (long "ldflag" <> metavar "FLAG" <> help "Add flag to the linker invocation")))
|
||||
|
||||
data OtherOptions = OtherOptions
|
||||
{ otherCore :: Bool
|
||||
, otherProfile :: Bool
|
||||
, otherLogMemory :: Bool
|
||||
, otherOptimize :: Bool
|
||||
, otherGenerateOnly :: Bool
|
||||
, otherPrompt :: String
|
||||
} deriving Show
|
||||
|
||||
parseOther :: Parser OtherOptions
|
||||
parseOther = OtherOptions
|
||||
<$> flag True False (long "core")
|
||||
<*> switch (long "profile" <> help "Profiling information")
|
||||
<*> switch (long "log-memory" <> help "Log memory allocations")
|
||||
<*> switch (long "optimize" <> help "Optimized build")
|
||||
<*> switch (long "generate-only" <> help "Stop after generating the C code")
|
||||
<*> strOption (long "prompt" <> value "鲤 " <> help "Set REPL prompt")
|
||||
|
||||
parseExecMode :: Parser ExecutionMode
|
||||
parseExecMode =
|
||||
flag' Check (long "check" <> help "Check project")
|
||||
<|> flag' Build (short 'b' <> help "Build project")
|
||||
<|> flag' BuildAndRun (short 'x' <> help "Build an run project")
|
||||
<|> Install <$> strOption (short 'i' <> help "Install built product")
|
||||
<|> pure Repl
|
||||
|
||||
parseFiles :: Parser [FilePath]
|
||||
parseFiles = some (argument str (metavar "FILES...")) <|> pure []
|
||||
|
3
carp.sh
3
carp.sh
@ -1,3 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
if [ -z "$CARP" ]
|
||||
then
|
||||
if [ -z "$NIX_CC" ]
|
||||
@ -7,4 +8,4 @@ then
|
||||
CARP="cabal -v0 run carp"
|
||||
fi
|
||||
fi
|
||||
$CARP $BUILD_OPTS $"--" $CARP_OPTS $*
|
||||
$CARP $BUILD_OPTS -- $CARP_OPTS "$@"
|
||||
|
@ -11,9 +11,10 @@ let
|
||||
optionals = nixpkgs.stdenv.lib.optionals;
|
||||
linuxOnly = optionals nixpkgs.stdenv.isLinux;
|
||||
|
||||
f = { mkDerivation, ansi-terminal, base, blaze-html, blaze-markup
|
||||
, cmark, cmdargs, containers, directory, edit-distance, filepath
|
||||
, haskeline, HUnit, mtl, parsec, process, split, stdenv, text
|
||||
f = { mkDerivation, stdenv
|
||||
, ansi-terminal, base, blaze-html, blaze-markup
|
||||
, cmark, containers, directory, edit-distance, filepath
|
||||
, haskeline, HUnit, mtl, optparse-applicative, parsec, process, split, text
|
||||
, darwin, glfw3, SDL2, SDL2_image, SDL2_gfx, SDL2_mixer, SDL2_ttf
|
||||
, ghc-prof-flamegraph
|
||||
, clang , makeWrapper
|
||||
@ -39,7 +40,7 @@ let
|
||||
[ glfw3 SDL2 SDL2_image SDL2_gfx SDL2_mixer SDL2_ttf ]
|
||||
++ linuxOnly [ libXext libXcursor libXinerama libXi libXrandr libXScrnSaver libXxf86vm libpthreadstubs libXdmcp libGL];
|
||||
executableHaskellDepends = [
|
||||
base cmdargs containers directory haskeline parsec process
|
||||
base containers directory haskeline optparse-applicative parsec process
|
||||
clang
|
||||
];
|
||||
executableFrameworkDepends = with darwin.apple_sdk.frameworks; optionals stdenv.isDarwin [
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
module Main where
|
||||
|
||||
import System.Console.CmdArgs
|
||||
import Options.Applicative hiding ((<|>))
|
||||
import Text.Parsec ((<|>))
|
||||
import qualified Text.Parsec as Parsec
|
||||
import Data.Char (toLower, isUpper)
|
||||
@ -12,16 +12,18 @@ import Types
|
||||
import Obj
|
||||
import Path
|
||||
|
||||
data Args = Args { sourcePath :: String
|
||||
, prefixToRemove :: String
|
||||
data Args = Args { prefixToRemove :: String
|
||||
, kebabCase :: Bool
|
||||
} deriving (Show, Data, Typeable)
|
||||
, sourcePath :: String
|
||||
} deriving Show
|
||||
|
||||
main = do parsedArgs <- cmdArgs (Args { sourcePath = def &= argPos 0
|
||||
, prefixToRemove = def
|
||||
, kebabCase = False
|
||||
}
|
||||
&= summary "Carp Header Parse 0.0.1")
|
||||
parseArgs :: Parser Args
|
||||
parseArgs = Args
|
||||
<$> strOption (long "prefixtoremove" <> short 'p' <> metavar "ITEM" <> value "")
|
||||
<*> switch (long "kebabcase" <> short 'f')
|
||||
<*> argument str (metavar "FILE")
|
||||
|
||||
main = do parsedArgs <- execParser $ Options.Applicative.info (parseArgs <**> helper) fullDesc
|
||||
let path = sourcePath parsedArgs
|
||||
if path /= ""
|
||||
then do source <- slurp path
|
||||
|
Loading…
Reference in New Issue
Block a user