about summary refs log tree commit diff
path: root/tvix/eval
diff options
context:
space:
mode:
authorsterni <sternenseemann@systemli.org>2022-10-15T14·21+0200
committerclbot <clbot@tvl.fyi>2022-10-16T19·11+0000
commit0624d78af0839cd8b290eb9cb6e5737f01162b96 (patch)
tree65b3044307223c33b6cdb02a82f8b565889a531a /tvix/eval
parenta8f7383fcb151f76c9cda1235abf0577b1ce6720 (diff)
refactor(tvix/eval): make OpFindFile use internal UnresolvedPath r/5146
To assert that OpFindFile is only emitted for specially compiled SPATH
expressions, as well as make sure it doesn't accidentally operate on
“ordinary values”, introduce an UnresolvedPath internal value. If
OpFindFile sees a non-UnresolvedPath value, it'll crash.

Note that this change is not done purely for OpFindFile: We may want to
compile SPATH expressions as function calls to __findFile (like C++ Nix
does) in the future, so the UnresolvedPath value would definitely need
to be an ordinary string again then. Rather, this change is done in
preparation for resolving home dir relative paths at runtime (since they
depend on the environment) for which we'll need a similar mechanism to
OpFindFile.

Change-Id: I6acf287f35197cd9e13377079f972b9d36e5b22e
Reviewed-on: https://cl.tvl.fyi/c/depot/+/7023
Autosubmit: sterni <sternenseemann@systemli.org>
Reviewed-by: Adam Joseph <adam@westernsemico.com>
Tested-by: BuildkiteCI
Reviewed-by: tazjin <tazjin@tvl.su>
Diffstat (limited to 'tvix/eval')
-rw-r--r--tvix/eval/src/compiler/mod.rs2
-rw-r--r--tvix/eval/src/value/mod.rs8
-rw-r--r--tvix/eval/src/vm.rs24
3 files changed, 22 insertions, 12 deletions
diff --git a/tvix/eval/src/compiler/mod.rs b/tvix/eval/src/compiler/mod.rs
index e3076246de33..11537e76b5c9 100644
--- a/tvix/eval/src/compiler/mod.rs
+++ b/tvix/eval/src/compiler/mod.rs
@@ -296,7 +296,7 @@ impl Compiler<'_> {
             let path = &raw_path[1..(raw_path.len() - 1)];
             // Make a thunk to resolve the path (without using `findFile`, at least for now?)
             return self.thunk(slot, node, move |c, _| {
-                c.emit_constant(path.into(), node);
+                c.emit_constant(Value::UnresolvedPath(path.into()), node);
                 c.push_op(OpCode::OpFindFile, node);
             });
         } else {
diff --git a/tvix/eval/src/value/mod.rs b/tvix/eval/src/value/mod.rs
index 9231e91bbe8b..93e194e37940 100644
--- a/tvix/eval/src/value/mod.rs
+++ b/tvix/eval/src/value/mod.rs
@@ -46,6 +46,7 @@ pub enum Value {
     AttrNotFound,
     Blueprint(Rc<Lambda>),
     DeferredUpvalue(StackIdx),
+    UnresolvedPath(PathBuf),
 }
 
 // Helper macros to generate the to_*/as_* macros while accounting for
@@ -240,7 +241,8 @@ impl Value {
 
             (Value::AttrNotFound, _)
             | (Value::Blueprint(_), _)
-            | (Value::DeferredUpvalue(_), _) => {
+            | (Value::DeferredUpvalue(_), _)
+            | (Value::UnresolvedPath(_), _) => {
                 panic!("tvix bug: .coerce_to_string() called on internal value")
             }
         }
@@ -262,7 +264,8 @@ impl Value {
             Value::Thunk(_)
             | Value::AttrNotFound
             | Value::Blueprint(_)
-            | Value::DeferredUpvalue(_) => "internal",
+            | Value::DeferredUpvalue(_)
+            | Value::UnresolvedPath(_) => "internal",
         }
     }
 
@@ -362,6 +365,7 @@ impl Display for Value {
             Value::AttrNotFound => f.write_str("internal[not found]"),
             Value::Blueprint(_) => f.write_str("internal[blueprint]"),
             Value::DeferredUpvalue(_) => f.write_str("internal[deferred_upvalue]"),
+            Value::UnresolvedPath(_) => f.write_str("internal[unresolved_path]"),
         }
     }
 }
diff --git a/tvix/eval/src/vm.rs b/tvix/eval/src/vm.rs
index 252635de56d0..05adec5f6ea6 100644
--- a/tvix/eval/src/vm.rs
+++ b/tvix/eval/src/vm.rs
@@ -524,14 +524,17 @@ impl<'o> VM<'o> {
                 self.push(Value::String(string));
             }
 
-            OpCode::OpFindFile => {
-                let path = self.pop().to_str().map_err(|e| self.error(e))?;
-                let resolved = self
-                    .nix_search_path
-                    .resolve(path)
-                    .map_err(|e| self.error(e))?;
-                self.push(resolved.into());
-            }
+            OpCode::OpFindFile => match self.pop() {
+                Value::UnresolvedPath(path) => {
+                    let resolved = self
+                        .nix_search_path
+                        .resolve(path)
+                        .map_err(|e| self.error(e))?;
+                    self.push(resolved.into());
+                }
+
+                _ => panic!("tvix compiler bug: OpFindFile called on non-UnresolvedPath"),
+            },
 
             OpCode::OpJump(JumpOffset(offset)) => {
                 debug_assert!(offset != 0);
@@ -836,7 +839,10 @@ impl<'o> VM<'o> {
 
             // If any of these internal values are encountered here a
             // critical error has happened (likely a compiler bug).
-            Value::AttrNotFound | Value::Blueprint(_) | Value::DeferredUpvalue(_) => {
+            Value::AttrNotFound
+            | Value::Blueprint(_)
+            | Value::DeferredUpvalue(_)
+            | Value::UnresolvedPath(_) => {
                 panic!("tvix bug: internal value left on stack: {:?}", value)
             }