Add basic in operator support

This commit is contained in:
Arthur Targaryen
2021-10-09 00:53:28 +02:00
parent 563a0b92b5
commit 8783cf0138
4 changed files with 95 additions and 1 deletions

View File

@ -190,6 +190,7 @@ pub fn eval_expression(
Operator::GreaterThanOrEqual => lhs.gte(op_span, &rhs),
Operator::Equal => lhs.eq(op_span, &rhs),
Operator::NotEqual => lhs.ne(op_span, &rhs),
Operator::In => lhs.r#in(op_span, &rhs),
x => Err(ShellError::UnsupportedOperator(x, op_span)),
}
}

View File

@ -273,6 +273,27 @@ pub fn math_result_type(
)
}
},
Operator::In => match (&lhs.ty, &rhs.ty) {
(t, Type::List(u)) if type_compatible(t, u) => (Type::Bool, None),
(Type::Int | Type::Float, Type::Range) => (Type::Bool, None),
(Type::String, Type::String) => (Type::Bool, None),
(Type::Unknown, _) => (Type::Bool, None),
(_, Type::Unknown) => (Type::Bool, None),
_ => {
*op = Expression::garbage(op.span);
(
Type::Unknown,
Some(ParseError::UnsupportedOperation(
op.span,
lhs.span,
lhs.ty.clone(),
rhs.span,
rhs.ty.clone(),
)),
)
}
},
_ => {
*op = Expression::garbage(op.span);

View File

@ -13,7 +13,7 @@ pub use unit::*;
use std::fmt::Debug;
use crate::ast::{CellPath, PathMember};
use crate::ast::{CellPath, PathMember, RangeInclusion};
use crate::{span, BlockId, Span, Type};
use crate::ShellError;
@ -1014,6 +1014,44 @@ impl Value {
}),
}
}
pub fn r#in(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
let span = span(&[self.span(), rhs.span()]);
match (self, rhs) {
(lhs, Value::Range { val: rhs, .. }) => Ok(Value::Bool {
val: lhs
.gte(Span::unknown(), &rhs.from)
.map_or(false, |v| v.is_true())
&& match rhs.inclusion {
RangeInclusion::Inclusive => lhs
.lte(Span::unknown(), &rhs.to)
.map_or(false, |v| v.is_true()),
RangeInclusion::RightExclusive => lhs
.lt(Span::unknown(), &rhs.to)
.map_or(false, |v| v.is_true()),
},
span,
}),
(Value::String { val: lhs, .. }, Value::String { val: rhs, .. }) => Ok(Value::Bool {
val: rhs.contains(lhs),
span,
}),
(lhs, Value::List { vals: rhs, .. }) => Ok(Value::Bool {
val: rhs
.iter()
.any(|x| lhs.eq(Span::unknown(), x).map_or(false, |v| v.is_true())),
span,
}),
_ => Err(ShellError::OperatorMismatch {
op_span: op,
lhs_ty: self.get_type(),
lhs_span: self.span(),
rhs_ty: rhs.get_type(),
rhs_span: rhs.span(),
}),
}
}
}
/// Format a duration in nanoseconds into a string