Add modulo operator and simplify in/not-in (#2505)

This commit is contained in:
Jonathan Turner 2020-09-07 12:12:55 +12:00 committed by GitHub
parent c973850571
commit 986b427038
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 35 additions and 6 deletions

View File

@ -33,6 +33,14 @@ pub fn apply_operator(
)),
_ => res,
}),
Operator::Modulo => value::compute_values(op, left, right).map(|res| match res {
UntaggedValue::Error(_) => UntaggedValue::Error(ShellError::labeled_error(
"Evaluation error",
"division by zero",
&right.tag.span,
)),
_ => res,
}),
Operator::In => table_contains(left, right).map(UntaggedValue::boolean),
Operator::NotIn => table_contains(left, right).map(|x| UntaggedValue::boolean(!x)),
Operator::And => match (left.as_bool(), right.as_bool()) {

View File

@ -161,6 +161,18 @@ fn parens_precedence() {
assert_eq!(actual.out, "12");
}
#[test]
fn modulo() {
let actual = nu!(
cwd: "tests/fixtures/formats", pipeline(
r#"
= 9 mod 2
"#
));
assert_eq!(actual.out, "1");
}
#[test]
fn duration_math() {
let actual = nu!(

View File

@ -31,7 +31,7 @@ fn row() {
r#"
open caballeros.csv
| merge { open new_caballeros.csv }
| where country in: ["Guayaquil Ecuador" "New Zealand"]
| where country in ["Guayaquil Ecuador" "New Zealand"]
| get luck
| math sum
| echo $it

View File

@ -27,7 +27,7 @@ fn filters_with_nothing_comparison() {
fn where_in_table() {
let actual = nu!(
cwd: "tests/fixtures/formats",
r#"echo '[{"name": "foo", "size": 3}, {"name": "foo", "size": 2}, {"name": "bar", "size": 4}]' | from json | where name in: ["foo"] | get size | math sum | echo $it"#
r#"echo '[{"name": "foo", "size": 3}, {"name": "foo", "size": 2}, {"name": "bar", "size": 4}]' | from json | where name in ["foo"] | get size | math sum | echo $it"#
);
assert_eq!(actual.out, "5");
@ -37,7 +37,7 @@ fn where_in_table() {
fn where_not_in_table() {
let actual = nu!(
cwd: "tests/fixtures/formats",
r#"echo '[{"name": "foo", "size": 3}, {"name": "foo", "size": 2}, {"name": "bar", "size": 4}]' | from json | where name not-in: ["foo"] | get size | math sum | echo $it"#
r#"echo '[{"name": "foo", "size": 3}, {"name": "foo", "size": 2}, {"name": "bar", "size": 4}]' | from json | where name not-in ["foo"] | get size | math sum | echo $it"#
);
assert_eq!(actual.out, "4");

View File

@ -131,6 +131,13 @@ pub fn compute_values(
)))
}
}
Operator::Modulo => {
if y.is_zero() {
Ok(zero_division_error())
} else {
Ok(UntaggedValue::Primitive(Primitive::Int(x % y)))
}
}
_ => Err((left.type_name(), right.type_name())),
},
(Primitive::Decimal(x), Primitive::Int(y)) => {

View File

@ -286,8 +286,9 @@ fn parse_operator(lite_arg: &Spanned<String>) -> (SpannedExpression, Option<Pars
"-" => Operator::Minus,
"*" => Operator::Multiply,
"/" => Operator::Divide,
"in:" => Operator::In,
"not-in:" => Operator::NotIn,
"in" => Operator::In,
"not-in" => Operator::NotIn,
"mod" => Operator::Modulo,
"&&" => Operator::And,
"||" => Operator::Or,
_ => {

View File

@ -575,7 +575,7 @@ impl SpannedExpression {
// Higher precedence binds tighter
match operator {
Operator::Multiply | Operator::Divide => 100,
Operator::Multiply | Operator::Divide | Operator::Modulo => 100,
Operator::Plus | Operator::Minus => 90,
Operator::NotContains
| Operator::Contains
@ -848,6 +848,7 @@ pub enum Operator {
Divide,
In,
NotIn,
Modulo,
And,
Or,
}