about summary refs log tree commit diff
path: root/tvix/eval/src
diff options
context:
space:
mode:
Diffstat (limited to 'tvix/eval/src')
-rw-r--r--tvix/eval/src/eval.rs25
-rw-r--r--tvix/eval/src/lib.rs2
-rw-r--r--tvix/eval/src/main.rs33
-rw-r--r--tvix/eval/src/tests/mod.rs6
4 files changed, 45 insertions, 21 deletions
diff --git a/tvix/eval/src/eval.rs b/tvix/eval/src/eval.rs
index 6510ef0afb..21591802a4 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 1c3fea3d5b..d7255af14e 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 177d4f2ec8..351554c2d5 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 ec9ee0d1c9..49ca35973e 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!(