diff options
Diffstat (limited to 'tvix/eval/src')
-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 |
4 files changed, 30 insertions, 5 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) |