mirror of
https://github.com/nushell/nushell.git
synced 2025-06-30 14:40:06 +02:00
Add the remaining missing operators
This commit is contained in:
@ -192,7 +192,12 @@ pub fn eval_expression(
|
||||
Operator::NotEqual => lhs.ne(op_span, &rhs),
|
||||
Operator::In => lhs.r#in(op_span, &rhs),
|
||||
Operator::NotIn => lhs.not_in(op_span, &rhs),
|
||||
x => Err(ShellError::UnsupportedOperator(x, op_span)),
|
||||
Operator::Contains => lhs.contains(op_span, &rhs),
|
||||
Operator::NotContains => lhs.not_contains(op_span, &rhs),
|
||||
Operator::Modulo => lhs.modulo(op_span, &rhs),
|
||||
Operator::And => lhs.and(op_span, &rhs),
|
||||
Operator::Or => lhs.or(op_span, &rhs),
|
||||
Operator::Pow => lhs.pow(op_span, &rhs),
|
||||
}
|
||||
}
|
||||
Expr::Subexpression(block_id) => {
|
||||
|
@ -86,7 +86,7 @@ pub fn math_result_type(
|
||||
)
|
||||
}
|
||||
},
|
||||
Operator::Multiply => match (&lhs.ty, &rhs.ty) {
|
||||
Operator::Multiply | Operator::Pow => match (&lhs.ty, &rhs.ty) {
|
||||
(Type::Int, Type::Int) => (Type::Int, None),
|
||||
(Type::Float, Type::Int) => (Type::Float, None),
|
||||
(Type::Int, Type::Float) => (Type::Float, None),
|
||||
@ -108,7 +108,7 @@ pub fn math_result_type(
|
||||
)
|
||||
}
|
||||
},
|
||||
Operator::Divide => match (&lhs.ty, &rhs.ty) {
|
||||
Operator::Divide | Operator::Modulo => match (&lhs.ty, &rhs.ty) {
|
||||
(Type::Int, Type::Int) => (Type::Int, None),
|
||||
(Type::Float, Type::Int) => (Type::Float, None),
|
||||
(Type::Int, Type::Float) => (Type::Float, None),
|
||||
@ -130,6 +130,25 @@ pub fn math_result_type(
|
||||
)
|
||||
}
|
||||
},
|
||||
Operator::And | Operator::Or => match (&lhs.ty, &rhs.ty) {
|
||||
(Type::Bool, Type::Bool) => (Type::Int, None),
|
||||
|
||||
(Type::Unknown, _) => (Type::Unknown, None),
|
||||
(_, Type::Unknown) => (Type::Unknown, None),
|
||||
_ => {
|
||||
*op = Expression::garbage(op.span);
|
||||
(
|
||||
Type::Unknown,
|
||||
Some(ParseError::UnsupportedOperation(
|
||||
op.span,
|
||||
lhs.span,
|
||||
lhs.ty.clone(),
|
||||
rhs.span,
|
||||
rhs.ty.clone(),
|
||||
)),
|
||||
)
|
||||
}
|
||||
},
|
||||
Operator::LessThan => match (&lhs.ty, &rhs.ty) {
|
||||
(Type::Int, Type::Int) => (Type::Bool, None),
|
||||
(Type::Float, Type::Int) => (Type::Bool, None),
|
||||
@ -273,6 +292,42 @@ pub fn math_result_type(
|
||||
)
|
||||
}
|
||||
},
|
||||
Operator::Contains => match (&lhs.ty, &rhs.ty) {
|
||||
(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(),
|
||||
)),
|
||||
)
|
||||
}
|
||||
},
|
||||
Operator::NotContains => match (&lhs.ty, &rhs.ty) {
|
||||
(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(),
|
||||
)),
|
||||
)
|
||||
}
|
||||
},
|
||||
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),
|
||||
@ -317,21 +372,6 @@ pub fn math_result_type(
|
||||
)
|
||||
}
|
||||
},
|
||||
|
||||
_ => {
|
||||
*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);
|
||||
|
@ -872,6 +872,164 @@ impl Value {
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn contains(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
|
||||
let span = span(&[self.span()?, rhs.span()?]);
|
||||
|
||||
match (self, rhs) {
|
||||
(Value::String { val: lhs, .. }, Value::String { val: rhs, .. }) => Ok(Value::Bool {
|
||||
val: lhs.contains(rhs),
|
||||
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()?,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn not_contains(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
|
||||
let span = span(&[self.span()?, rhs.span()?]);
|
||||
|
||||
match (self, rhs) {
|
||||
(Value::String { val: lhs, .. }, Value::String { val: rhs, .. }) => Ok(Value::Bool {
|
||||
val: !lhs.contains(rhs),
|
||||
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()?,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn modulo(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
|
||||
let span = span(&[self.span()?, rhs.span()?]);
|
||||
|
||||
match (self, rhs) {
|
||||
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => {
|
||||
if *rhs != 0 {
|
||||
Ok(Value::Int {
|
||||
val: lhs % rhs,
|
||||
span,
|
||||
})
|
||||
} else {
|
||||
Err(ShellError::DivisionByZero(op))
|
||||
}
|
||||
}
|
||||
(Value::Int { val: lhs, .. }, Value::Float { val: rhs, .. }) => {
|
||||
if *rhs != 0.0 {
|
||||
Ok(Value::Float {
|
||||
val: *lhs as f64 % *rhs,
|
||||
span,
|
||||
})
|
||||
} else {
|
||||
Err(ShellError::DivisionByZero(op))
|
||||
}
|
||||
}
|
||||
(Value::Float { val: lhs, .. }, Value::Int { val: rhs, .. }) => {
|
||||
if *rhs != 0 {
|
||||
Ok(Value::Float {
|
||||
val: *lhs % *rhs as f64,
|
||||
span,
|
||||
})
|
||||
} else {
|
||||
Err(ShellError::DivisionByZero(op))
|
||||
}
|
||||
}
|
||||
(Value::Float { val: lhs, .. }, Value::Float { val: rhs, .. }) => {
|
||||
if *rhs != 0.0 {
|
||||
Ok(Value::Float {
|
||||
val: lhs % rhs,
|
||||
span,
|
||||
})
|
||||
} else {
|
||||
Err(ShellError::DivisionByZero(op))
|
||||
}
|
||||
}
|
||||
|
||||
_ => Err(ShellError::OperatorMismatch {
|
||||
op_span: op,
|
||||
lhs_ty: self.get_type(),
|
||||
lhs_span: self.span()?,
|
||||
rhs_ty: rhs.get_type(),
|
||||
rhs_span: rhs.span()?,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn and(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
|
||||
let span = span(&[self.span()?, rhs.span()?]);
|
||||
|
||||
match (self, rhs) {
|
||||
(Value::Bool { val: lhs, .. }, Value::Bool { val: rhs, .. }) => Ok(Value::Bool {
|
||||
val: *lhs && *rhs,
|
||||
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()?,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn or(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
|
||||
let span = span(&[self.span()?, rhs.span()?]);
|
||||
|
||||
match (self, rhs) {
|
||||
(Value::Bool { val: lhs, .. }, Value::Bool { val: rhs, .. }) => Ok(Value::Bool {
|
||||
val: *lhs || *rhs,
|
||||
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()?,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pow(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
|
||||
let span = span(&[self.span()?, rhs.span()?]);
|
||||
|
||||
match (self, rhs) {
|
||||
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Int {
|
||||
val: lhs.pow(*rhs as u32),
|
||||
span,
|
||||
}),
|
||||
(Value::Int { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Float {
|
||||
val: (*lhs as f64).powf(*rhs),
|
||||
span,
|
||||
}),
|
||||
(Value::Float { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Float {
|
||||
val: lhs.powf(*rhs as f64),
|
||||
span,
|
||||
}),
|
||||
(Value::Float { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Float {
|
||||
val: lhs.powf(*rhs),
|
||||
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
|
||||
|
Reference in New Issue
Block a user