diff options
-rw-r--r-- | tvix/eval/src/tests/tvix_tests/eval-okay-add-paths.exp | 1 | ||||
-rw-r--r-- | tvix/eval/src/tests/tvix_tests/eval-okay-add-paths.nix | 9 | ||||
-rw-r--r-- | tvix/eval/src/value/mod.rs | 6 | ||||
-rw-r--r-- | tvix/eval/src/vm.rs | 19 | ||||
-rw-r--r-- | tvix/eval/tests/nix_oracle.rs | 11 |
5 files changed, 40 insertions, 6 deletions
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-add-paths.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-add-paths.exp new file mode 100644 index 000000000000..94ba9a881ae6 --- /dev/null +++ b/tvix/eval/src/tests/tvix_tests/eval-okay-add-paths.exp @@ -0,0 +1 @@ +[ /bin /binbar /binbar /binbar /binbar /bin/bar /bin/bin ] diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-add-paths.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-add-paths.nix new file mode 100644 index 000000000000..462f670882a0 --- /dev/null +++ b/tvix/eval/src/tests/tvix_tests/eval-okay-add-paths.nix @@ -0,0 +1,9 @@ +[ + (/bin + "/") + (/bin + "bar") + (let name = "bar"; in /bin + name) + (let name = "bar"; in /bin + "${name}") + (let name = "bar"; in /bin + "/" + "${name}") + (let name = "bar"; in /bin + "/${name}") + (/bin + /bin) +] diff --git a/tvix/eval/src/value/mod.rs b/tvix/eval/src/value/mod.rs index 0e9d013fdf61..31ac0c07d4c2 100644 --- a/tvix/eval/src/value/mod.rs +++ b/tvix/eval/src/value/mod.rs @@ -383,6 +383,12 @@ impl From<String> for Value { } } +impl From<PathBuf> for Value { + fn from(path: PathBuf) -> Self { + Self::Path(path) + } +} + fn type_error(expected: &'static str, actual: &Value) -> ErrorKind { ErrorKind::TypeError { expected, diff --git a/tvix/eval/src/vm.rs b/tvix/eval/src/vm.rs index 01299ccc17da..cf766fb33523 100644 --- a/tvix/eval/src/vm.rs +++ b/tvix/eval/src/vm.rs @@ -1,7 +1,9 @@ //! This module implements the virtual (or abstract) machine that runs //! Tvix bytecode. -use std::{cell::RefMut, rc::Rc}; +use std::{cell::RefMut, path::PathBuf, rc::Rc}; + +use path_clean::PathClean; use crate::{ chunk::Chunk, @@ -347,10 +349,17 @@ impl<'o> VM<'o> { let b = self.pop(); let a = self.pop(); - let result = if let (Value::String(s1), Value::String(s2)) = (&a, &b) { - Value::String(s1.concat(s2)) - } else { - fallible!(self, arithmetic_op!(&a, &b, +)) + let result = match (&a, &b) { + (Value::String(s1), Value::String(s2)) => Value::String(s1.concat(s2)), + (Value::Path(p), v) => { + let mut path = p.to_string_lossy().into_owned(); + path.push_str( + &v.coerce_to_string(CoercionKind::Weak, self) + .map_err(|ek| self.error(ek))?, + ); + PathBuf::from(path).clean().into() + } + _ => fallible!(self, arithmetic_op!(&a, &b, +)), }; self.push(result) diff --git a/tvix/eval/tests/nix_oracle.rs b/tvix/eval/tests/nix_oracle.rs index 61f2be674e27..34ed50351053 100644 --- a/tvix/eval/tests/nix_oracle.rs +++ b/tvix/eval/tests/nix_oracle.rs @@ -15,7 +15,7 @@ fn nix_eval(expr: &str) -> String { let store_dir = TempDir::new("store-dir").unwrap(); let output = Command::new(nix_binary_path()) - .args(["--eval", "-E"]) + .args(["--eval", "--strict", "-E"]) .arg(format!("({expr})")) .env( "NIX_REMOTE", @@ -66,4 +66,13 @@ compare_eval_tests! { literal_int("1"); add_ints("1 + 1"); add_lists("[1 2] ++ [3 4]"); + add_paths(r#"[ + (./. + "/") + (./foo + "bar") + (let name = "bar"; in ./foo + name) + (let name = "bar"; in ./foo + "${name}") + (let name = "bar"; in ./foo + "/" + "${name}") + (let name = "bar"; in ./foo + "/${name}") + (./. + ./.) + ]"#); } |