refactor(tvix/eval): make OpFindFile use internal UnresolvedPath

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>
This commit is contained in:
sterni 2022-10-15 16:21:14 +02:00 committed by clbot
parent a8f7383fcb
commit 0624d78af0
3 changed files with 22 additions and 12 deletions

View file

@ -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 {

View file

@ -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]"),
}
}
}

View file

@ -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)
}