fix(tvix/eval): force value passed to builtins.toString

This introduces a macro to do the forcing, but this solution isn't
very nice and also does not work in all cases yet.

Change-Id: Icd18862ec47edb82c0efc3af5835a6cb6126f629
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6456
Reviewed-by: sterni <sternenseemann@systemli.org>
Tested-by: BuildkiteCI
This commit is contained in:
Vincent Ambo 2022-09-04 22:34:25 +03:00 committed by tazjin
parent 0aeca64777
commit 6deaa0d6ce
2 changed files with 26 additions and 4 deletions

View file

@ -15,6 +15,27 @@ use crate::{
use crate::arithmetic_op; use crate::arithmetic_op;
/// Helper macro to ensure that a value has been forced. The structure
/// of this is a little cumbersome as there are different reference
/// types depending on whether the value is inside a thunk or not.
macro_rules! force {
( $vm:ident, $src:expr, $value:ident, $body:block ) => {
if let Value::Thunk(thunk) = $src {
thunk.force($vm)?;
let guard = thunk.value();
let $value: &Value = &guard;
$body
} else {
let $value: &Value = $src;
$body
}
};
( $vm:ident, $value:ident, $body:block ) => {
force!($vm, &$value, $value, $body)
};
}
fn pure_builtins() -> Vec<Builtin> { fn pure_builtins() -> Vec<Builtin> {
vec![ vec![
Builtin::new("add", 2, |mut args, _| { Builtin::new("add", 2, |mut args, _| {
@ -96,9 +117,10 @@ fn pure_builtins() -> Vec<Builtin> {
args.pop().unwrap().to_str()?.as_str().to_owned(), args.pop().unwrap().to_str()?.as_str().to_owned(),
)); ));
}), }),
Builtin::new("toString", 1, |args, _| { Builtin::new("toString", 1, |args, vm| {
// TODO: toString is actually not the same as Display force!(vm, &args[0], value, {
Ok(Value::String(format!("{}", args[0]).into())) Ok(Value::String(format!("{}", value).into()))
})
}), }),
Builtin::new("typeOf", 1, |args, _| { Builtin::new("typeOf", 1, |args, _| {
Ok(Value::String(args[0].type_of().into())) Ok(Value::String(args[0].type_of().into()))

View file

@ -66,7 +66,7 @@ macro_rules! arithmetic_op {
$self.push(result); $self.push(result);
}}; }};
( $a:ident, $b:ident, $op:tt ) => {{ ( $a:expr, $b:expr, $op:tt ) => {{
match ($a, $b) { match ($a, $b) {
(Value::Integer(i1), Value::Integer(i2)) => Ok(Value::Integer(i1 $op i2)), (Value::Integer(i1), Value::Integer(i2)) => Ok(Value::Integer(i1 $op i2)),
(Value::Float(f1), Value::Float(f2)) => Ok(Value::Float(f1 $op f2)), (Value::Float(f1), Value::Float(f2)) => Ok(Value::Float(f1 $op f2)),