about summary refs log tree commit diff
path: root/tvix/cli/src/main.rs
diff options
context:
space:
mode:
authorAspen Smith <root@gws.fyi>2024-07-05T03·46-0400
committerclbot <clbot@tvl.fyi>2024-07-05T16·40+0000
commitfc63594631590547c9a31001806095f2e079a20e (patch)
treebed08e994d56fb224a62be6ab371f9cd1fec17e6 /tvix/cli/src/main.rs
parentac3d717944412b17d7dcd18006c2f9f522b1b3f7 (diff)
feat(tvix/repl): Allow binding variables at the top-level r/8346
Allow binding variables at the REPL's toplevel in the same way the Nix
REPL does, using the syntax <ident> = <expr>. This fully, strictly
evaluates the value and sets it in the repl's "env", which gets passed
in at the toplevel when evaluating expressions.

The laziness behavior differs from Nix's, but I think this is good:

    ❯ nix repl
    Welcome to Nix version 2.3.18. Type :? for help.

    nix-repl> x = builtins.trace "x" 1

    nix-repl> x
    trace: x
    1

    nix-repl> x
    1

vs tvix:

    tvix-repl> x = builtins.trace "x" 1
    trace: "x" :: string
    tvix-repl> x
    => 1 :: int
    tvix-repl> x
    => 1 :: int

Bug: https://b.tvl.fyi/issues/371
Change-Id: Ieb2d626b7195fa87be638c9a4dae2eee45eb9ab1
Reviewed-on: https://cl.tvl.fyi/c/depot/+/11954
Reviewed-by: flokli <flokli@flokli.de>
Tested-by: BuildkiteCI
Autosubmit: aspen <root@gws.fyi>
Diffstat (limited to 'tvix/cli/src/main.rs')
-rw-r--r--tvix/cli/src/main.rs41
1 files changed, 32 insertions, 9 deletions
diff --git a/tvix/cli/src/main.rs b/tvix/cli/src/main.rs
index 686513b77cc4..c4c70d2a1777 100644
--- a/tvix/cli/src/main.rs
+++ b/tvix/cli/src/main.rs
@@ -1,7 +1,10 @@
+mod assignment;
 mod repl;
 
 use clap::Parser;
 use repl::Repl;
+use smol_str::SmolStr;
+use std::collections::HashMap;
 use std::rc::Rc;
 use std::{fs, path::PathBuf};
 use tracing::{instrument, Level, Span};
@@ -150,18 +153,15 @@ impl AllowIncomplete {
 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
 struct IncompleteInput;
 
-/// Interprets the given code snippet, printing out warnings, errors
-/// and the result itself. The return value indicates whether
-/// evaluation succeeded.
-#[instrument(skip_all, fields(indicatif.pb_show=1))]
-fn interpret(
+/// Interprets the given code snippet, printing out warnings and errors and returning the result
+fn evaluate(
     tvix_store_io: Rc<TvixStoreIO>,
     code: &str,
     path: Option<PathBuf>,
     args: &Args,
-    explain: bool,
     allow_incomplete: AllowIncomplete,
-) -> Result<bool, IncompleteInput> {
+    env: Option<&HashMap<SmolStr, Value>>,
+) -> Result<Option<Value>, IncompleteInput> {
     let span = Span::current();
     span.pb_start();
     span.pb_set_style(&tvix_tracing::PB_SPINNER_STYLE);
@@ -173,6 +173,9 @@ fn interpret(
     );
     eval.strict = args.strict;
     eval.builtins.extend(impure_builtins());
+    if let Some(env) = env {
+        eval.env = Some(env);
+    }
     add_derivation_builtins(&mut eval, Rc::clone(&tvix_store_io));
     add_fetcher_builtins(&mut eval, Rc::clone(&tvix_store_io));
     add_import_builtins(&mut eval, tvix_store_io);
@@ -226,7 +229,25 @@ fn interpret(
         }
     }
 
-    if let Some(value) = result.value.as_ref() {
+    Ok(result.value)
+}
+
+/// Interprets the given code snippet, printing out warnings, errors
+/// and the result itself. The return value indicates whether
+/// evaluation succeeded.
+#[instrument(skip_all, fields(indicatif.pb_show=1))]
+fn interpret(
+    tvix_store_io: Rc<TvixStoreIO>,
+    code: &str,
+    path: Option<PathBuf>,
+    args: &Args,
+    explain: bool,
+    allow_incomplete: AllowIncomplete,
+    env: Option<&HashMap<SmolStr, Value>>,
+) -> Result<bool, IncompleteInput> {
+    let result = evaluate(tvix_store_io, code, path, args, allow_incomplete, env)?;
+
+    if let Some(value) = result.as_ref() {
         if explain {
             println!("=> {}", value.explain());
         } else {
@@ -235,7 +256,7 @@ fn interpret(
     }
 
     // inform the caller about any errors
-    Ok(result.errors.is_empty())
+    Ok(result.is_some())
 }
 
 /// Interpret the given code snippet, but only run the Tvix compiler
@@ -298,6 +319,7 @@ fn main() {
             &args,
             false,
             AllowIncomplete::RequireComplete,
+            None, // TODO(aspen): Pass in --arg/--argstr here
         )
         .unwrap()
         {
@@ -325,6 +347,7 @@ fn run_file(io_handle: Rc<TvixStoreIO>, mut path: PathBuf, args: &Args) {
             args,
             false,
             AllowIncomplete::RequireComplete,
+            None,
         )
         .unwrap()
     };