diff options
Diffstat (limited to 'tvix/eval/src/vm.rs')
-rw-r--r-- | tvix/eval/src/vm.rs | 33 |
1 files changed, 20 insertions, 13 deletions
diff --git a/tvix/eval/src/vm.rs b/tvix/eval/src/vm.rs index 87adfe5611a4..52627a1fea14 100644 --- a/tvix/eval/src/vm.rs +++ b/tvix/eval/src/vm.rs @@ -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, - - (lhs, rhs) => return Err($self.error(ErrorKind::Incomparable { + 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)), + + // 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> { |