#[allow(unused)]
use std::{
collections::HashSet,
env, fs,
path::{Path, PathBuf},
process::Command,
time::Instant,
};
use crate::{
build::{build, BuildOutput, FailedBuildOutput},
build::{BuildConfig, EznoParsePostCheckVisitors},
check::check,
error_handling::emit_ezno_diagnostic,
utilities::print_to_cli,
};
use argh::FromArgs;
#[derive(FromArgs, Debug)]
struct TopLevel {
#[argh(subcommand)]
nested: CompilerSubCommand,
}
#[derive(FromArgs, Debug)]
#[argh(subcommand)]
enum CompilerSubCommand {
Info(Info),
ASTExplorer(crate::ast_explorer::ExplorerArguments),
Check(CheckArguments),
Experimental(ExperimentalArguments),
#[cfg(not(target_family = "wasm"))]
Repl(crate::repl::ReplArguments),
}
#[derive(FromArgs, Debug)]
#[argh(subcommand, name = "info")]
struct Info {}
#[derive(FromArgs, Debug)]
#[argh(subcommand, name = "experimental")]
pub(crate) struct ExperimentalArguments {
#[argh(subcommand)]
nested: ExperimentalSubcommand,
}
#[derive(FromArgs, Debug)]
#[argh(subcommand)]
pub(crate) enum ExperimentalSubcommand {
Build(BuildArguments),
}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "build")]
#[allow(clippy::struct_excessive_bools)]
pub(crate) struct BuildArguments {
#[argh(positional)]
pub input: PathBuf,
#[argh(positional)]
pub output: Option<PathBuf>,
#[argh(option, short = 'd')]
pub definition_file: Option<PathBuf>,
#[argh(switch, short = 'm')]
pub minify: bool,
#[argh(switch)]
pub no_comments: bool,
#[argh(switch)]
pub source_maps: bool,
#[argh(switch)]
pub non_standard_syntax: bool,
#[argh(switch)]
pub non_standard_library: bool,
#[argh(switch)]
pub optimise: bool,
#[cfg(not(target_family = "wasm"))]
#[argh(switch)]
pub timings: bool,
}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "check")]
pub(crate) struct CheckArguments {
#[argh(positional)]
pub input: PathBuf,
#[argh(option, short = 'd')]
pub definition_file: Option<PathBuf>,
#[argh(switch)]
pub watch: bool,
}
#[allow(unused)]
fn file_system_resolver(path: &Path) -> Option<String> {
if path.to_str() == Some("BLANK") {
return Some(String::new());
}
match fs::read_to_string(path) {
Ok(source) => Some(source),
Err(_) => None,
}
}
pub fn run_cli<T: crate::ReadFromFS, U: crate::WriteToFS, V: crate::CLIInputResolver>(
cli_arguments: &[&str],
read_file: &T,
write_file: U,
cli_input_resolver: V,
) {
let command = match FromArgs::from_args(&["ezno-cli"], cli_arguments) {
Ok(TopLevel { nested }) => nested,
Err(err) => {
print_to_cli(format_args!("{}", err.output));
return;
}
};
match command {
CompilerSubCommand::Info(_) => {
crate::utilities::print_info();
}
CompilerSubCommand::Check(check_arguments) => {
let CheckArguments { input, watch: _, definition_file } = check_arguments;
let (diagnostics, _others) = check(read_file, &input, definition_file.as_deref());
let fs = match _others {
Ok(data) => data.module_contents,
Err(data) => data,
};
if !diagnostics.has_error() {
print_to_cli(format_args!("No type errors found 🎉"))
}
for diagnostic in diagnostics.into_iter() {
emit_ezno_diagnostic(diagnostic, &fs).unwrap();
}
}
CompilerSubCommand::Experimental(ExperimentalArguments {
nested: ExperimentalSubcommand::Build(build_config),
}) => {
let output_path = build_config.output.unwrap_or("ezno_output.js".into());
let default_builders = EznoParsePostCheckVisitors {
expression_visitors_mut: vec![Box::new(
crate::transformers::optimisations::ExpressionOptimiser,
)],
statement_visitors_mut: vec![Box::new(
crate::transformers::optimisations::StatementOptimiser,
)],
variable_visitors_mut: Default::default(),
block_visitors_mut: Default::default(),
};
let output = build(
read_file,
&build_config.input,
build_config.definition_file.as_deref(),
&output_path,
&BuildConfig { strip_whitespace: build_config.minify },
Some(default_builders),
);
match output {
Ok(BuildOutput { diagnostics, fs, outputs }) => {
for output in outputs {
write_file(output.output_path.as_path(), output.content);
}
for diagnostic in diagnostics {
emit_ezno_diagnostic(diagnostic, &fs).unwrap();
}
print_to_cli(format_args!("Project built successfully 🎉"))
}
Err(FailedBuildOutput { fs, diagnostics }) => {
for diagnostic in diagnostics {
emit_ezno_diagnostic(diagnostic, &fs).unwrap();
}
}
}
}
CompilerSubCommand::ASTExplorer(mut repl) => repl.run(read_file, cli_input_resolver),
#[cfg(not(target_family = "wasm"))]
CompilerSubCommand::Repl(argument) => crate::repl::run_deno_repl(cli_input_resolver, argument),
}
}