2022-09-18 21:59:59 +02:00
|
|
|
use clap::Parser;
|
2024-08-07 23:21:26 +02:00
|
|
|
use mimalloc::MiMalloc;
|
2024-01-16 05:31:20 +01:00
|
|
|
use std::rc::Rc;
|
|
|
|
use std::{fs, path::PathBuf};
|
2024-07-06 15:00:46 +02:00
|
|
|
use tvix_cli::args::Args;
|
|
|
|
use tvix_cli::repl::Repl;
|
|
|
|
use tvix_cli::{init_io_handle, interpret, AllowIncomplete};
|
|
|
|
use tvix_eval::observer::DisassemblingObserver;
|
2024-08-11 17:15:47 +02:00
|
|
|
use tvix_eval::EvalMode;
|
2023-11-03 12:34:37 +01:00
|
|
|
use tvix_glue::tvix_store_io::TvixStoreIO;
|
2022-08-04 15:43:51 +02:00
|
|
|
|
2024-02-13 19:23:39 +01:00
|
|
|
#[global_allocator]
|
2024-08-07 23:21:26 +02:00
|
|
|
static GLOBAL: MiMalloc = MiMalloc;
|
2024-02-13 19:23:39 +01:00
|
|
|
|
2023-01-05 10:56:19 +01:00
|
|
|
/// Interpret the given code snippet, but only run the Tvix compiler
|
|
|
|
/// on it and return errors and warnings.
|
|
|
|
fn lint(code: &str, path: Option<PathBuf>, args: &Args) -> bool {
|
2024-08-11 17:15:47 +02:00
|
|
|
let mut eval_builder = tvix_eval::Evaluation::builder_impure();
|
|
|
|
|
|
|
|
if args.strict {
|
|
|
|
eval_builder = eval_builder.mode(EvalMode::Strict);
|
|
|
|
}
|
2023-03-17 22:15:03 +01:00
|
|
|
|
2024-07-06 02:29:41 +02:00
|
|
|
let source_map = eval_builder.source_map().clone();
|
2023-01-05 10:56:19 +01:00
|
|
|
|
|
|
|
let mut compiler_observer = DisassemblingObserver::new(source_map.clone(), std::io::stderr());
|
|
|
|
|
|
|
|
if args.dump_bytecode {
|
2024-07-06 02:29:41 +02:00
|
|
|
eval_builder.set_compiler_observer(Some(&mut compiler_observer));
|
2023-01-05 10:56:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if args.trace_runtime {
|
|
|
|
eprintln!("warning: --trace-runtime has no effect with --compile-only!");
|
|
|
|
}
|
|
|
|
|
2024-07-06 02:29:41 +02:00
|
|
|
let eval = eval_builder.build();
|
2023-12-30 21:36:48 +01:00
|
|
|
let result = eval.compile_only(code, path);
|
2023-01-05 10:56:19 +01:00
|
|
|
|
|
|
|
if args.display_ast {
|
|
|
|
if let Some(ref expr) = result.expr {
|
|
|
|
eprintln!("AST: {}", tvix_eval::pretty_print_expr(expr));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for error in &result.errors {
|
2024-02-20 09:38:33 +01:00
|
|
|
error.fancy_format_stderr();
|
2023-01-05 10:56:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
for warning in &result.warnings {
|
|
|
|
warning.fancy_format_stderr(&source_map);
|
|
|
|
}
|
|
|
|
|
|
|
|
// inform the caller about any errors
|
|
|
|
result.errors.is_empty()
|
|
|
|
}
|
|
|
|
|
2022-08-04 15:29:38 +02:00
|
|
|
fn main() {
|
2022-09-18 21:59:59 +02:00
|
|
|
let args = Args::parse();
|
2022-08-04 15:43:51 +02:00
|
|
|
|
2024-11-01 15:57:42 +01:00
|
|
|
tvix_tracing::TracingBuilder::default()
|
2024-06-19 11:30:31 +02:00
|
|
|
.enable_progressbar()
|
2024-06-10 17:49:45 +02:00
|
|
|
.build()
|
|
|
|
.expect("unable to set up tracing subscriber");
|
2024-04-19 21:42:17 +02:00
|
|
|
let tokio_runtime = tokio::runtime::Runtime::new().expect("failed to setup tokio runtime");
|
|
|
|
|
|
|
|
let io_handle = init_io_handle(&tokio_runtime, &args);
|
|
|
|
|
2022-12-09 11:29:08 +01:00
|
|
|
if let Some(file) = &args.script {
|
2024-04-19 21:42:17 +02:00
|
|
|
run_file(io_handle, file.clone(), &args)
|
2022-12-09 11:29:08 +01:00
|
|
|
} else if let Some(expr) = &args.expr {
|
2024-05-27 20:15:38 +02:00
|
|
|
if !interpret(
|
|
|
|
io_handle,
|
|
|
|
expr,
|
|
|
|
None,
|
|
|
|
&args,
|
|
|
|
false,
|
|
|
|
AllowIncomplete::RequireComplete,
|
2024-07-05 05:46:20 +02:00
|
|
|
None, // TODO(aspen): Pass in --arg/--argstr here
|
2024-07-07 15:21:52 +02:00
|
|
|
None,
|
|
|
|
None,
|
2024-05-27 20:15:38 +02:00
|
|
|
)
|
|
|
|
.unwrap()
|
2024-07-06 15:00:46 +02:00
|
|
|
.finalize()
|
2024-05-27 20:15:38 +02:00
|
|
|
{
|
2022-12-08 22:19:22 +01:00
|
|
|
std::process::exit(1);
|
2022-10-11 01:41:42 +02:00
|
|
|
}
|
2022-08-04 15:43:51 +02:00
|
|
|
} else {
|
2024-07-06 15:00:46 +02:00
|
|
|
let mut repl = Repl::new(io_handle, &args);
|
|
|
|
repl.run()
|
2022-08-04 15:43:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-19 21:42:17 +02:00
|
|
|
fn run_file(io_handle: Rc<TvixStoreIO>, mut path: PathBuf, args: &Args) {
|
2022-10-08 20:22:26 +02:00
|
|
|
if path.is_dir() {
|
|
|
|
path.push("default.nix");
|
|
|
|
}
|
|
|
|
let contents = fs::read_to_string(&path).expect("failed to read the input file");
|
2022-12-08 22:19:22 +01:00
|
|
|
|
2023-01-05 10:56:19 +01:00
|
|
|
let success = if args.compile_only {
|
|
|
|
lint(&contents, Some(path), args)
|
|
|
|
} else {
|
2024-05-27 20:15:38 +02:00
|
|
|
interpret(
|
|
|
|
io_handle,
|
|
|
|
&contents,
|
|
|
|
Some(path),
|
|
|
|
args,
|
|
|
|
false,
|
|
|
|
AllowIncomplete::RequireComplete,
|
2024-07-05 05:46:20 +02:00
|
|
|
None,
|
2024-07-07 15:21:52 +02:00
|
|
|
None,
|
|
|
|
None,
|
2024-05-27 20:15:38 +02:00
|
|
|
)
|
|
|
|
.unwrap()
|
2024-07-06 15:00:46 +02:00
|
|
|
.finalize()
|
2023-01-05 10:56:19 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
if !success {
|
2022-12-08 22:19:22 +01:00
|
|
|
std::process::exit(1);
|
2022-08-11 23:27:02 +02:00
|
|
|
}
|
|
|
|
}
|