feat(tvix/eval): Support builtins.lessThan
Extend and export the `cmp_op`, and this becomes trivial. Change-Id: I9c93fa4db0f5a1fc8b56928ea144676f79247de1 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6557 Autosubmit: wpcarro <wpcarro@gmail.com> Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
This commit is contained in:
parent
9e16d70809
commit
890bbf9b1f
4 changed files with 41 additions and 13 deletions
|
@ -16,7 +16,7 @@ use crate::{
|
|||
vm::VM,
|
||||
};
|
||||
|
||||
use crate::arithmetic_op;
|
||||
use crate::{arithmetic_op, cmp_op};
|
||||
|
||||
use self::versions::{VersionPart, VersionPartsIter};
|
||||
|
||||
|
@ -160,6 +160,11 @@ fn pure_builtins() -> Vec<Builtin> {
|
|||
.map(|list| Value::List(NixList::from(list)))
|
||||
.map_err(Into::into)
|
||||
}),
|
||||
Builtin::new(
|
||||
"lessThan",
|
||||
&[false, false],
|
||||
|args, vm| cmp_op!(&*args[0].force(vm)?, &*args[1].force(vm)?, <),
|
||||
),
|
||||
Builtin::new("hasAttr", &[true, true], |args, _| {
|
||||
let k = args[0].to_str()?;
|
||||
let xs = args[1].to_attrs()?;
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
[ true true true true false false false false true true true true false ]
|
|
@ -0,0 +1,15 @@
|
|||
[
|
||||
(builtins.lessThan 2 3)
|
||||
(builtins.lessThan 2.0 3)
|
||||
(builtins.lessThan 2 3.0)
|
||||
(builtins.lessThan 2.0 3.0)
|
||||
(builtins.lessThan 3 2)
|
||||
(builtins.lessThan 3.0 2)
|
||||
(builtins.lessThan 3 2.0)
|
||||
(builtins.lessThan 3.0 2.0)
|
||||
(builtins.lessThan 10 (builtins.add 9 2))
|
||||
(builtins.lessThan (builtins.add 9 1) 11)
|
||||
(builtins.lessThan (builtins.add 9 1) (builtins.add 9 2))
|
||||
(builtins.lessThan "a" "b")
|
||||
(builtins.lessThan "b" "a")
|
||||
]
|
|
@ -94,29 +94,36 @@ macro_rules! arithmetic_op {
|
|||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! cmp_op {
|
||||
( $self:ident, $op:tt ) => {{
|
||||
let b = $self.pop();
|
||||
let a = $self.pop();
|
||||
let result = fallible!($self, cmp_op!(&a, &b, $op));
|
||||
$self.push(result);
|
||||
}};
|
||||
|
||||
( $a:expr, $b:expr, $op:tt ) => {
|
||||
// Comparable (in terms of ordering) values are numbers and
|
||||
// strings. Numbers need to be coerced similarly to arithmetic
|
||||
// ops if mixed types are encountered.
|
||||
let result = match (a, b) {
|
||||
(Value::Integer(i1), Value::Integer(i2)) => i1 $op i2,
|
||||
(Value::Float(f1), Value::Float(f2)) => f1 $op f2,
|
||||
(Value::Integer(i1), Value::Float(f2)) => (i1 as f64) $op f2,
|
||||
(Value::Float(f1), Value::Integer(i2)) => f1 $op (i2 as f64),
|
||||
(Value::String(s1), Value::String(s2)) => s1 $op s2,
|
||||
match ($a, $b) {
|
||||
// same types
|
||||
(Value::Integer(i1), Value::Integer(i2)) => Ok(Value::Bool(i1 $op i2)),
|
||||
(Value::Float(f1), Value::Float(f2)) => Ok(Value::Bool(f1 $op f2)),
|
||||
(Value::String(s1), Value::String(s2)) => Ok(Value::Bool(s1 $op s2)),
|
||||
|
||||
(lhs, rhs) => return Err($self.error(ErrorKind::Incomparable {
|
||||
// different types
|
||||
(Value::Integer(i1), Value::Float(f2)) => Ok(Value::Bool((*i1 as f64) $op *f2)),
|
||||
(Value::Float(f1), Value::Integer(i2)) => Ok(Value::Bool(*f1 $op (*i2 as f64))),
|
||||
|
||||
// unsupported types
|
||||
(lhs, rhs) => Err(ErrorKind::Incomparable {
|
||||
lhs: lhs.type_of(),
|
||||
rhs: rhs.type_of(),
|
||||
})),
|
||||
};
|
||||
|
||||
$self.push(Value::Bool(result));
|
||||
}};
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'o> VM<'o> {
|
||||
|
|
Loading…
Reference in a new issue