diff options
-rw-r--r-- | tvix/eval/src/compiler/mod.rs | 20 | ||||
-rw-r--r-- | tvix/eval/src/opcode.rs | 3 | ||||
-rw-r--r-- | tvix/eval/src/vm.rs | 20 |
3 files changed, 31 insertions, 12 deletions
diff --git a/tvix/eval/src/compiler/mod.rs b/tvix/eval/src/compiler/mod.rs index 11537e76b5c9..95de69487071 100644 --- a/tvix/eval/src/compiler/mod.rs +++ b/tvix/eval/src/compiler/mod.rs @@ -268,19 +268,15 @@ impl Compiler<'_> { let path = if raw_path.starts_with('/') { Path::new(&raw_path).to_owned() } else if raw_path.starts_with('~') { - let mut buf = match dirs::home_dir() { - Some(buf) => buf, - None => { - self.emit_error( - node, - ErrorKind::PathResolution("failed to determine home directory".into()), - ); - return; - } - }; + return self.thunk(slot, node, move |c, _| { + // We assume that paths that home paths start with ~/ or fail to parse + // TODO: this should be checked using a parse-fail test. + debug_assert!(raw_path.len() > 2 && raw_path.starts_with("~/")); - buf.push(&raw_path); - buf + let home_relative_path = &raw_path[2..(raw_path.len())]; + c.emit_constant(Value::UnresolvedPath(home_relative_path.into()), node); + c.push_op(OpCode::OpResolveHomePath, node); + }); } else if raw_path.starts_with('.') { let mut buf = self.root_dir.clone(); buf.push(&raw_path); diff --git a/tvix/eval/src/opcode.rs b/tvix/eval/src/opcode.rs index fdc916ca7f79..70ef1a3b5324 100644 --- a/tvix/eval/src/opcode.rs +++ b/tvix/eval/src/opcode.rs @@ -117,6 +117,9 @@ pub enum OpCode { /// [`NixSearchPath`]: crate::nix_search_path::NixSearchPath OpFindFile, + /// Attempt to resolve a path literal relative to the home dir + OpResolveHomePath, + // Type assertion operators OpAssertBool, diff --git a/tvix/eval/src/vm.rs b/tvix/eval/src/vm.rs index 05adec5f6ea6..7fcdb9ea739b 100644 --- a/tvix/eval/src/vm.rs +++ b/tvix/eval/src/vm.rs @@ -536,6 +536,26 @@ impl<'o> VM<'o> { _ => panic!("tvix compiler bug: OpFindFile called on non-UnresolvedPath"), }, + OpCode::OpResolveHomePath => match self.pop() { + Value::UnresolvedPath(path) => { + match dirs::home_dir() { + None => { + return Err(self.error(ErrorKind::PathResolution( + "failed to determine home directory".into(), + ))); + } + Some(mut buf) => { + buf.push(path); + self.push(buf.into()); + } + }; + } + + _ => { + panic!("tvix compiler bug: OpResolveHomePath called on non-UnresolvedPath") + } + }, + OpCode::OpJump(JumpOffset(offset)) => { debug_assert!(offset != 0); self.frame_mut().ip += offset; |