diff options
Diffstat (limited to 'tvix/eval/src')
-rw-r--r-- | tvix/eval/src/eval.rs | 25 | ||||
-rw-r--r-- | tvix/eval/src/lib.rs | 2 | ||||
-rw-r--r-- | tvix/eval/src/main.rs | 33 | ||||
-rw-r--r-- | tvix/eval/src/tests/mod.rs | 6 |
4 files changed, 45 insertions, 21 deletions
diff --git a/tvix/eval/src/eval.rs b/tvix/eval/src/eval.rs index 6510ef0afb2b..21591802a443 100644 --- a/tvix/eval/src/eval.rs +++ b/tvix/eval/src/eval.rs @@ -7,7 +7,24 @@ use crate::{ value::Value, }; -pub fn interpret(code: &str, location: Option<PathBuf>) -> EvalResult<Value> { +/// Runtime options for the Tvix interpreter +#[derive(Debug, Clone, Copy, Default)] +#[cfg_attr(feature = "repl", derive(clap::Parser))] +pub struct Options { + /// Dump the raw AST to stdout before interpreting + #[cfg_attr(feature = "repl", clap(long, env = "TVIX_DISPLAY_AST"))] + display_ast: bool, + + /// Dump the bytecode to stdout before evaluating + #[cfg_attr(feature = "repl", clap(long, env = "TVIX_DUMP_BYTECODE"))] + dump_bytecode: bool, + + /// Trace the runtime of the VM + #[cfg_attr(feature = "repl", clap(long, env = "TVIX_TRACE_RUNTIME"))] + trace_runtime: bool, +} + +pub fn interpret(code: &str, location: Option<PathBuf>, options: Options) -> EvalResult<Value> { let mut codemap = codemap::CodeMap::new(); let file = codemap.add_file( location @@ -37,11 +54,11 @@ pub fn interpret(code: &str, location: Option<PathBuf>) -> EvalResult<Value> { .expr() .expect("expression should exist if no errors occured"); - if std::env::var("TVIX_DISPLAY_AST").is_ok() { + if options.display_ast { println!("{:?}", root_expr); } - let result = if std::env::var("TVIX_DUMP_BYTECODE").is_ok() { + let result = if options.dump_bytecode { crate::compiler::compile( root_expr, location, @@ -76,7 +93,7 @@ pub fn interpret(code: &str, location: Option<PathBuf>) -> EvalResult<Value> { return Err(err.clone()); } - if std::env::var("TVIX_TRACE_RUNTIME").is_ok() { + if options.trace_runtime { crate::vm::run_lambda(&mut TracingObserver::new(std::io::stderr()), result.lambda) } else { crate::vm::run_lambda(&mut NoOpObserver::default(), result.lambda) diff --git a/tvix/eval/src/lib.rs b/tvix/eval/src/lib.rs index 1c3fea3d5b9f..d7255af14e68 100644 --- a/tvix/eval/src/lib.rs +++ b/tvix/eval/src/lib.rs @@ -21,6 +21,6 @@ mod tests; pub use crate::builtins::global_builtins; pub use crate::compiler::compile; pub use crate::errors::EvalResult; -pub use crate::eval::interpret; +pub use crate::eval::{interpret, Options}; pub use crate::value::Value; pub use crate::vm::run_lambda; diff --git a/tvix/eval/src/main.rs b/tvix/eval/src/main.rs index 177d4f2ec8e6..351554c2d538 100644 --- a/tvix/eval/src/main.rs +++ b/tvix/eval/src/main.rs @@ -1,30 +1,35 @@ use std::{ - env, fs, + fs, path::{Path, PathBuf}, - process, }; +use clap::Parser; use rustyline::{error::ReadlineError, Editor}; +#[derive(Parser)] +struct Args { + /// Path to a script to evaluate + script: Option<PathBuf>, + + #[clap(flatten)] + eval_options: tvix_eval::Options, +} + fn main() { - let mut args = env::args(); - if args.len() > 2 { - println!("Usage: tvix-eval [script]"); - process::exit(1); - } + let args = Args::parse(); - if let Some(file) = args.nth(1) { - run_file(&file); + if let Some(file) = &args.script { + run_file(file, args.eval_options) } else { - run_prompt(); + run_prompt(args.eval_options) } } -fn run_file(file: &str) { +fn run_file(file: &Path, eval_options: tvix_eval::Options) { let contents = fs::read_to_string(file).expect("failed to read the input file"); let path = Path::new(file).to_owned(); - match tvix_eval::interpret(&contents, Some(path)) { + match tvix_eval::interpret(&contents, Some(path), eval_options) { Ok(result) => println!("=> {} :: {}", result, result.type_of()), Err(err) => eprintln!("{}", err), } @@ -38,7 +43,7 @@ fn state_dir() -> Option<PathBuf> { path } -fn run_prompt() { +fn run_prompt(eval_options: tvix_eval::Options) { let mut rl = Editor::<()>::new().expect("should be able to launch rustyline"); let history_path = match state_dir() { @@ -63,7 +68,7 @@ fn run_prompt() { } rl.add_history_entry(&line); - match tvix_eval::interpret(&line, None) { + match tvix_eval::interpret(&line, None, eval_options) { Ok(result) => { println!("=> {} :: {}", result, result.type_of()); } diff --git a/tvix/eval/src/tests/mod.rs b/tvix/eval/src/tests/mod.rs index ec9ee0d1c9ea..49ca35973e56 100644 --- a/tvix/eval/src/tests/mod.rs +++ b/tvix/eval/src/tests/mod.rs @@ -12,7 +12,8 @@ fn eval_okay_test(code_path: &str) { let code = std::fs::read_to_string(code_path).expect("should be able to read test code"); let exp = std::fs::read_to_string(exp_path).expect("should be able to read test expectation"); - let result = interpret(&code, None).expect("evaluation of eval-okay test should succeed"); + let result = interpret(&code, None, Default::default()) + .expect("evaluation of eval-okay test should succeed"); let result_str = format!("{}", result); assert_eq!( @@ -28,7 +29,8 @@ fn eval_okay_test(code_path: &str) { fn identity(code_path: &str) { let code = std::fs::read_to_string(code_path).expect("should be able to read test code"); - let result = interpret(&code, None).expect("evaluation of identity test should succeed"); + let result = interpret(&code, None, Default::default()) + .expect("evaluation of identity test should succeed"); let result_str = format!("{}", result); assert_eq!( |