mirror of
https://github.com/anoma/juvix.git
synced 2024-12-04 17:07:28 +03:00
2d36a65324
# Changes The main goal of this pr is to remove the `--target` flag for `juvix compile` and use subcommands instead. The targets that are relevant to normal users are found in `juvix compile --help`. Targets that are relevant only to developers are found in `juvix dev compile --help`. Below I list some of the changes in more detail. ## Compile targets for user-facing languages - `juvix compile native` - `juvix compile wasi`. I wasn't sure how to call this: `wasm`, `wasm32-wasi`, etc. In the end I thought `wasi` was short and accurate, but we can change it. - `juvix compile vampir` - `juvix compile anoma` - `juvix compile cairo` ## *New* compile targets for internal languages See `juvix dev compile --help`. 1. `dev compile core` has the same behaviour as `dev core from-concrete`. The `dev core from-concrete` is redundant at the moment. 2. `dev compile tree` compiles to Tree and prints the InfoTable to the output file wihout any additional checks. 3. `dev compile reg` compiles to Reg and prints the InfoTable to the output file wihout any additional checks. 4. `dev compile asm` compiles to Asm and prints the InfoTable to the output file wihout any additional checks. 5. 4. `dev compile casm` compiles to Asm and prints the Result to the output file wihout any additional checks. TODO: should the Result be printed or something else? At the moment the Result lacks a pretty instance. 6. ## Optional input file 1. The input file for commands that expect a .juvix file as input is now optional. If the argument is ommited, he main file given in the package.yaml will be used. This applies to the following commands: 1. `juvix compile [native|wasi|geb|vampir|anoma|cairo]` 8. `juvix dev compile [core|reg|tree|casm|asm]` 1. `juvix html` 3. `juvix markdown`. 4. `juvix dev internal [typecheck|pretty]`. 5. `juvix dev [parse|scope]` 7. `juvix compile [native|wasi|geb|vampir|anoma|cairo]` 9. note that `juvix format` has not changed its behaviour. ## Refactor some C-like compiler flags Both `juvix compile native` and `juvix compile wasi` support `--only-c` (`-C`), `--only-preprocess` (`-E`), `--only-assemble` (`-S`). I propose to deviate from the `gcc` style and instead use a flag with a single argument: - `--cstage [source|preprocess|assembly|exec(default)]`. I'm open to suggestions. For now, I've kept the legacy flags but marked them as deprecated in the help message. ## Remove code duplication I've tried to reduce code duplication. This is sometimes in tension with code readability so I've tried to find a good balance. I've tried to make it so we don't have to jump to many different files to understand what a single command is doing. I'm sure there is still room for improvement. ## Other refactors I've implemented other small refactors that I considered improved the quality of the code. ## TODO/Future work We should refactor commands (under `compile dev`) which still use `module Commands.Extra.Compile` and remove it.
245 lines
6.6 KiB
Haskell
245 lines
6.6 KiB
Haskell
module TopCommand.Options where
|
|
|
|
import Commands.Clean.Options
|
|
import Commands.Compile.Options
|
|
import Commands.Dependencies.Options qualified as Dependencies
|
|
import Commands.Dev.Options qualified as Dev
|
|
import Commands.Doctor.Options
|
|
import Commands.Eval.Options
|
|
import Commands.Format.Options
|
|
import Commands.Html.Options
|
|
import Commands.Init.Options
|
|
import Commands.Markdown.Options
|
|
import Commands.Repl.Options
|
|
import Commands.Typecheck.Options
|
|
import CommonOptions hiding (Doc)
|
|
import Data.Generics.Uniplate.Data
|
|
import GlobalOptions
|
|
import Options.Applicative.Help.Pretty
|
|
|
|
data TopCommand
|
|
= DisplayVersion
|
|
| DisplayNumericVersion
|
|
| DisplayHelp
|
|
| Typecheck TypecheckOptions
|
|
| Compile CompileCommand
|
|
| Clean CleanOptions
|
|
| Eval EvalOptions
|
|
| Html HtmlOptions
|
|
| Markdown MarkdownOptions
|
|
| Dev Dev.DevCommand
|
|
| Doctor DoctorOptions
|
|
| Init InitOptions
|
|
| JuvixRepl ReplOptions
|
|
| JuvixFormat FormatOptions
|
|
| Dependencies Dependencies.DependenciesCommand
|
|
deriving stock (Data)
|
|
|
|
topCommandInputPath :: TopCommand -> IO (Maybe (SomePath Abs))
|
|
topCommandInputPath = \case
|
|
JuvixFormat fopts -> case fopts ^. formatInput of
|
|
Just f -> getInputPathFromPrepathFileOrDir f
|
|
Nothing -> return Nothing
|
|
t -> do
|
|
d <- firstJustM getInputFileOrDir (universeBi t)
|
|
f <- firstJustM getInputFile (universeBi t)
|
|
return (f <|> d)
|
|
where
|
|
getInputFile :: AppPath File -> IO (Maybe (SomePath Abs))
|
|
getInputFile p
|
|
| p ^. pathIsInput = do
|
|
cwd <- getCurrentDir
|
|
Just . File <$> prepathToAbsFile cwd (p ^. pathPath)
|
|
| otherwise = return Nothing
|
|
|
|
getInputFileOrDir :: AppPath FileOrDir -> IO (Maybe (SomePath Abs))
|
|
getInputFileOrDir p
|
|
| p ^. pathIsInput = getInputPathFromPrepathFileOrDir (p ^. pathPath)
|
|
| otherwise = return Nothing
|
|
|
|
getInputPathFromPrepathFileOrDir :: Prepath FileOrDir -> IO (Maybe (SomePath Abs))
|
|
getInputPathFromPrepathFileOrDir p = do
|
|
cwd <- getCurrentDir
|
|
lr <- fromPreFileOrDir cwd p
|
|
return . Just $ case lr of
|
|
Left file -> File file
|
|
Right dir -> Dir dir
|
|
|
|
parseDisplayVersion :: Parser TopCommand
|
|
parseDisplayVersion =
|
|
flag'
|
|
DisplayVersion
|
|
( long "version"
|
|
<> short 'v'
|
|
<> help "Show version information"
|
|
)
|
|
|
|
parseDisplayNumericVersion :: Parser TopCommand
|
|
parseDisplayNumericVersion =
|
|
flag'
|
|
DisplayNumericVersion
|
|
( long "numeric-version"
|
|
<> help "Show only the version number"
|
|
)
|
|
|
|
parseDisplayHelp :: Parser TopCommand
|
|
parseDisplayHelp =
|
|
flag'
|
|
DisplayHelp
|
|
( long "help"
|
|
<> short 'h'
|
|
<> help "Show the help text"
|
|
)
|
|
|
|
parseUtility :: Parser TopCommand
|
|
parseUtility =
|
|
hsubparser
|
|
( mconcat
|
|
[ commandGroup "Utility commands:",
|
|
metavar "UTILITY_CMD",
|
|
commandInit,
|
|
commandRepl,
|
|
commandFormat,
|
|
commandClean,
|
|
commandDependencies,
|
|
commandDoctor,
|
|
commandDev
|
|
]
|
|
)
|
|
where
|
|
commandInit :: Mod CommandFields TopCommand
|
|
commandInit =
|
|
command
|
|
"init"
|
|
( info
|
|
(Init <$> parseInitOptions)
|
|
(progDesc "Interactively initialize a Juvix project in the current directory")
|
|
)
|
|
commandDoctor :: Mod CommandFields TopCommand
|
|
commandDoctor =
|
|
command
|
|
"doctor"
|
|
( info
|
|
(Doctor <$> parseDoctorOptions)
|
|
(progDesc "Perform checks on your Juvix development environment")
|
|
)
|
|
commandRepl :: Mod CommandFields TopCommand
|
|
commandRepl =
|
|
command
|
|
"repl"
|
|
( info
|
|
(JuvixRepl <$> parseRepl)
|
|
(progDesc "Run the Juvix REPL")
|
|
)
|
|
|
|
commandFormat :: Mod CommandFields TopCommand
|
|
commandFormat =
|
|
command "format" $
|
|
info
|
|
(JuvixFormat <$> parseFormat)
|
|
( headerDoc
|
|
( Just
|
|
( vsep
|
|
[ "juvix format is used to format Juvix source files.",
|
|
"",
|
|
"Given a file, it prints the reformatted source to standard output.",
|
|
"Given a project directory it prints a list of unformatted files in the project.",
|
|
"Given no argument it prints a list of unformatted files in the project which contains the current directory."
|
|
]
|
|
)
|
|
)
|
|
<> progDesc "Format a Juvix file or Juvix project"
|
|
)
|
|
|
|
commandClean :: Mod CommandFields TopCommand
|
|
commandClean =
|
|
command
|
|
"clean"
|
|
(info (Clean <$> parseCleanOptions) (progDesc "Delete build artifacts"))
|
|
|
|
commandDependencies :: Mod CommandFields TopCommand
|
|
commandDependencies =
|
|
command
|
|
"dependencies"
|
|
(info (Dependencies <$> Dependencies.parseDependenciesCommand) (progDesc "Subcommands related to dependencies"))
|
|
|
|
commandCheck :: Mod CommandFields TopCommand
|
|
commandCheck =
|
|
command "typecheck" $
|
|
info
|
|
(Typecheck <$> parseTypecheck)
|
|
(progDesc "Typecheck a Juvix file")
|
|
|
|
commandCompile :: Mod CommandFields TopCommand
|
|
commandCompile =
|
|
command "compile" $
|
|
info
|
|
(Compile <$> parseCompileCommand)
|
|
(progDesc "Compile a Juvix file")
|
|
|
|
commandEval :: Mod CommandFields TopCommand
|
|
commandEval =
|
|
command "eval" $
|
|
info
|
|
(Eval <$> parseEvalOptions)
|
|
(progDesc "Evaluate a Juvix file")
|
|
|
|
commandHtml :: Mod CommandFields TopCommand
|
|
commandHtml =
|
|
command "html" $
|
|
info
|
|
(Html <$> parseHtml)
|
|
(progDesc "Generate HTML for a Juvix file")
|
|
|
|
commandMarkdown :: Mod CommandFields TopCommand
|
|
commandMarkdown =
|
|
command "markdown" $
|
|
info
|
|
(Markdown <$> parseJuvixMarkdown)
|
|
(progDesc "Translate Juvix code blocks in a Markdown file to Markdown")
|
|
|
|
commandDev :: Mod CommandFields TopCommand
|
|
commandDev =
|
|
command "dev" $
|
|
info
|
|
(Dev <$> Dev.parseDevCommand)
|
|
(progDesc "Commands for the developers")
|
|
|
|
parseCompilerCommand :: Parser TopCommand
|
|
parseCompilerCommand =
|
|
hsubparser
|
|
( mconcat
|
|
[ commandGroup "Compiler commands:",
|
|
metavar "COMPILER_CMD",
|
|
commandCheck,
|
|
commandCompile,
|
|
commandEval,
|
|
commandHtml,
|
|
commandMarkdown
|
|
]
|
|
)
|
|
|
|
parseTopCommand :: Parser TopCommand
|
|
parseTopCommand =
|
|
parseDisplayVersion
|
|
<|> parseDisplayNumericVersion
|
|
<|> parseDisplayHelp
|
|
<|> parseCompilerCommand
|
|
<|> parseUtility
|
|
|
|
descr :: ParserInfo (GlobalOptions, TopCommand)
|
|
descr =
|
|
info
|
|
( do
|
|
cli <- parseTopCommand
|
|
opts <- parseGlobalFlags
|
|
return (opts, cli)
|
|
)
|
|
( fullDesc
|
|
<> progDesc "The Juvix compiler."
|
|
<> footerDoc (Just foot)
|
|
)
|
|
where
|
|
foot :: Doc
|
|
foot = annotate bold "maintainers: " <> "The Juvix Team"
|