added pow operator, and filesize math (#2976)

* added pow operator, and filesize math

* removed + and - arms, removed some pow, pow higher precedence

* Update value.rs

Co-authored-by: Jonathan Turner <jonathandturner@users.noreply.github.com>
This commit is contained in:
Darren Schroeder 2021-01-29 07:44:02 -06:00 committed by GitHub
parent 47c4b8e88a
commit b052d524da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 45 additions and 5 deletions

View File

@ -257,6 +257,7 @@ fn get_result_shape_of(
} }
} }
Operator::Modulo => SyntaxShape::Number, Operator::Modulo => SyntaxShape::Number,
Operator::Pow => SyntaxShape::Number,
}) })
} }
@ -860,7 +861,7 @@ impl VarSyntaxShapeDeductor {
} }
} }
} }
Operator::Multiply | Operator::Divide => { Operator::Multiply | Operator::Divide | Operator::Pow => {
if let Some(shape) = self.get_shape_of_binary_arg_or_insert_dependency( if let Some(shape) = self.get_shape_of_binary_arg_or_insert_dependency(
(var, expr), (var, expr),
bin_spanned, bin_spanned,

View File

@ -8,7 +8,7 @@ use nu_protocol::ShellTypeName;
use nu_protocol::{Primitive, Type, UntaggedValue}; use nu_protocol::{Primitive, Type, UntaggedValue};
use nu_source::{DebugDocBuilder, PrettyDebug, Span, Tagged}; use nu_source::{DebugDocBuilder, PrettyDebug, Span, Tagged};
use nu_table::TextStyle; use nu_table::TextStyle;
use num_traits::Zero; use num_traits::{ToPrimitive, Zero};
use std::collections::HashMap; use std::collections::HashMap;
pub struct Date; pub struct Date;
@ -119,6 +119,11 @@ pub fn compute_values(
}?; }?;
Ok(UntaggedValue::Primitive(Primitive::Filesize(result))) Ok(UntaggedValue::Primitive(Primitive::Filesize(result)))
} }
(Primitive::Filesize(x), Primitive::Int(y)) => match operator {
Operator::Multiply => Ok(UntaggedValue::Primitive(Primitive::Int(x * y))),
Operator::Divide => Ok(UntaggedValue::Primitive(Primitive::Int(x / y))),
_ => Err((left.type_name(), right.type_name())),
},
(Primitive::Int(x), Primitive::Int(y)) => match operator { (Primitive::Int(x), Primitive::Int(y)) => match operator {
Operator::Plus => Ok(UntaggedValue::Primitive(Primitive::Int(x + y))), Operator::Plus => Ok(UntaggedValue::Primitive(Primitive::Int(x + y))),
Operator::Minus => Ok(UntaggedValue::Primitive(Primitive::Int(x - y))), Operator::Minus => Ok(UntaggedValue::Primitive(Primitive::Int(x - y))),
@ -142,6 +147,13 @@ pub fn compute_values(
Ok(UntaggedValue::Primitive(Primitive::Int(x % y))) Ok(UntaggedValue::Primitive(Primitive::Int(x % y)))
} }
} }
Operator::Pow => {
let prim_u32 = ToPrimitive::to_u32(y);
match prim_u32 {
Some(num) => Ok(UntaggedValue::Primitive(Primitive::Int(x.pow(num)))),
_ => Err((left.type_name(), right.type_name())),
}
}
_ => Err((left.type_name(), right.type_name())), _ => Err((left.type_name(), right.type_name())),
}, },
(Primitive::Decimal(x), Primitive::Int(y)) => { (Primitive::Decimal(x), Primitive::Int(y)) => {
@ -161,6 +173,16 @@ pub fn compute_values(
} }
Ok(x % bigdecimal::BigDecimal::from(y.clone())) Ok(x % bigdecimal::BigDecimal::from(y.clone()))
} }
// leaving this here for the hope that bigdecimal will one day support pow/powf/fpow
// Operator::Pow => {
// let xp = bigdecimal::ToPrimitive::to_f64(x).unwrap_or(0.0);
// let yp = bigdecimal::ToPrimitive::to_f64(y).unwrap_or(0.0);
// let pow = bigdecimal::FromPrimitive::from_f64(xp.powf(yp));
// match pow {
// Some(p) => Ok(p),
// None => Err((left.type_name(), right.type_name())),
// }
// }
_ => Err((left.type_name(), right.type_name())), _ => Err((left.type_name(), right.type_name())),
}?; }?;
Ok(UntaggedValue::Primitive(Primitive::Decimal(result))) Ok(UntaggedValue::Primitive(Primitive::Decimal(result)))
@ -182,7 +204,11 @@ pub fn compute_values(
} }
Ok(bigdecimal::BigDecimal::from(x.clone()) % y) Ok(bigdecimal::BigDecimal::from(x.clone()) % y)
} }
// big decimal doesn't support pow yet
// Operator::Pow => {
// let yp = bigdecimal::ToPrimitive::to_u32(y).unwrap_or(0);
// Ok(bigdecimal::BigDecimal::from(x.pow(yp)))
// }
_ => Err((left.type_name(), right.type_name())), _ => Err((left.type_name(), right.type_name())),
}?; }?;
Ok(UntaggedValue::Primitive(Primitive::Decimal(result))) Ok(UntaggedValue::Primitive(Primitive::Decimal(result)))
@ -204,7 +230,16 @@ pub fn compute_values(
} }
Ok(x % y) Ok(x % y)
} }
// big decimal doesn't support pow yet
// Operator::Pow => {
// let xp = bigdecimal::ToPrimitive::to_f64(x).unwrap_or(0.0);
// let yp = bigdecimal::ToPrimitive::to_f64(y).unwrap_or(0.0);
// let pow = bigdecimal::FromPrimitive::from_f64(xp.powf(yp));
// match pow {
// Some(p) => Ok(p),
// None => Err((left.type_name(), right.type_name())),
// }
// }
_ => Err((left.type_name(), right.type_name())), _ => Err((left.type_name(), right.type_name())),
}?; }?;
Ok(UntaggedValue::Primitive(Primitive::Decimal(result))) Ok(UntaggedValue::Primitive(Primitive::Decimal(result)))

View File

@ -25,6 +25,7 @@ pub fn apply_operator(
Operator::Plus => value::compute_values(op, left, right), Operator::Plus => value::compute_values(op, left, right),
Operator::Minus => value::compute_values(op, left, right), Operator::Minus => value::compute_values(op, left, right),
Operator::Multiply => value::compute_values(op, left, right), Operator::Multiply => value::compute_values(op, left, right),
Operator::Pow => value::compute_values(op, left, right),
Operator::Divide => value::compute_values(op, left, right).map(|res| match res { Operator::Divide => value::compute_values(op, left, right).map(|res| match res {
UntaggedValue::Error(_) => UntaggedValue::Error(ShellError::labeled_error( UntaggedValue::Error(_) => UntaggedValue::Error(ShellError::labeled_error(
"Evaluation error", "Evaluation error",

View File

@ -307,6 +307,7 @@ fn parse_operator(lite_arg: &Spanned<String>) -> (SpannedExpression, Option<Pars
"mod" => Operator::Modulo, "mod" => Operator::Modulo,
"&&" => Operator::And, "&&" => Operator::And,
"||" => Operator::Or, "||" => Operator::Or,
"**" => Operator::Pow,
_ => { _ => {
return ( return (
garbage(lite_arg.span), garbage(lite_arg.span),

View File

@ -656,7 +656,8 @@ impl SpannedExpression {
// Higher precedence binds tighter // Higher precedence binds tighter
match operator { match operator {
Operator::Multiply | Operator::Divide | Operator::Modulo => 100, Operator::Pow => 100,
Operator::Multiply | Operator::Divide | Operator::Modulo => 95,
Operator::Plus | Operator::Minus => 90, Operator::Plus | Operator::Minus => 90,
Operator::NotContains Operator::NotContains
| Operator::Contains | Operator::Contains
@ -848,6 +849,7 @@ pub enum Operator {
Modulo, Modulo,
And, And,
Or, Or,
Pow,
} }
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Clone, Hash, Deserialize, Serialize, new)] #[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Clone, Hash, Deserialize, Serialize, new)]