diff options
author | Aspen Smith <root@gws.fyi> | 2024-07-05T03·46-0400 |
---|---|---|
committer | clbot <clbot@tvl.fyi> | 2024-07-05T16·40+0000 |
commit | fc63594631590547c9a31001806095f2e079a20e (patch) | |
tree | bed08e994d56fb224a62be6ab371f9cd1fec17e6 /tvix/cli/src/repl.rs | |
parent | ac3d717944412b17d7dcd18006c2f9f522b1b3f7 (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/repl.rs')
-rw-r--r-- | tvix/cli/src/repl.rs | 46 |
1 files changed, 39 insertions, 7 deletions
diff --git a/tvix/cli/src/repl.rs b/tvix/cli/src/repl.rs index 5a4830a027bc..758874016326 100644 --- a/tvix/cli/src/repl.rs +++ b/tvix/cli/src/repl.rs @@ -1,10 +1,13 @@ -use std::path::PathBuf; use std::rc::Rc; +use std::{collections::HashMap, path::PathBuf}; use rustyline::{error::ReadlineError, Editor}; +use smol_str::SmolStr; +use tvix_eval::Value; use tvix_glue::tvix_store_io::TvixStoreIO; -use crate::{interpret, AllowIncomplete, Args, IncompleteInput}; +use crate::evaluate; +use crate::{assignment::Assignment, interpret, AllowIncomplete, Args, IncompleteInput}; fn state_dir() -> Option<PathBuf> { let mut path = dirs::data_dir(); @@ -17,6 +20,7 @@ fn state_dir() -> Option<PathBuf> { #[derive(Debug, Clone, PartialEq, Eq)] pub enum ReplCommand<'a> { Expr(&'a str), + Assign(Assignment<'a>), Explain(&'a str), Print(&'a str), Quit, @@ -29,11 +33,12 @@ Welcome to the Tvix REPL! The following commands are supported: - <expr> Evaluate a Nix language expression and print the result, along with its inferred type - :d <expr> Evaluate a Nix language expression and print a detailed description of the result - :p <expr> Evaluate a Nix language expression and print the result recursively - :q Exit the REPL - :?, :h Display this help text + <expr> Evaluate a Nix language expression and print the result, along with its inferred type + <x> = <expr> Bind the result of an expression to a variable + :d <expr> Evaluate a Nix language expression and print a detailed description of the result + :p <expr> Evaluate a Nix language expression and print the result recursively + :q Exit the REPL + :?, :h Display this help text "; pub fn parse(input: &'a str) -> Self { @@ -52,6 +57,10 @@ The following commands are supported: } } + if let Some(assignment) = Assignment::parse(input) { + return Self::Assign(assignment); + } + Self::Expr(input) } } @@ -61,6 +70,8 @@ pub struct Repl { /// In-progress multiline input, when the input so far doesn't parse as a complete expression multiline_input: Option<String>, rl: Editor<()>, + /// Local variables defined at the top-level in the repl + env: HashMap<SmolStr, Value>, } impl Repl { @@ -69,6 +80,7 @@ impl Repl { Self { multiline_input: None, rl, + env: HashMap::new(), } } @@ -125,7 +137,25 @@ impl Repl { args, false, AllowIncomplete::Allow, + Some(&self.env), ), + ReplCommand::Assign(Assignment { ident, value }) => { + match evaluate( + Rc::clone(&io_handle), + &value.to_string(), /* FIXME: don't re-parse */ + None, + args, + AllowIncomplete::Allow, + Some(&self.env), + ) { + Ok(Some(value)) => { + self.env.insert(ident.into(), value); + Ok(true) + } + Ok(None) => Ok(true), + Err(incomplete) => Err(incomplete), + } + } ReplCommand::Explain(input) => interpret( Rc::clone(&io_handle), input, @@ -133,6 +163,7 @@ impl Repl { args, true, AllowIncomplete::Allow, + Some(&self.env), ), ReplCommand::Print(input) => interpret( Rc::clone(&io_handle), @@ -144,6 +175,7 @@ impl Repl { }, false, AllowIncomplete::Allow, + Some(&self.env), ), }; |