Attempts to add // math operator (#5759)

* attempts to add `div` math operator

* allows `//` to be used too

* fmt:

* clippy issue

* returns appropriate type

* returns appropriate type 2

* fmt

* ensure consistency; rename to `fdiv`

* Update parser.rs
This commit is contained in:
pwygab
2022-06-13 18:54:47 +08:00
committed by GitHub
parent 43a218240c
commit caafd26deb
9 changed files with 236 additions and 1 deletions

View File

@ -30,7 +30,10 @@ impl Expression {
match operator {
Operator::Pow => 100,
Operator::Multiply | Operator::Divide | Operator::Modulo => 95,
Operator::Multiply
| Operator::Divide
| Operator::Modulo
| Operator::FloorDivision => 95,
Operator::Plus | Operator::Minus => 90,
Operator::NotRegexMatch
| Operator::RegexMatch

View File

@ -20,6 +20,7 @@ pub enum Operator {
In,
NotIn,
Modulo,
FloorDivision,
And,
Or,
Pow,
@ -43,6 +44,7 @@ impl Display for Operator {
Operator::In => write!(f, "in"),
Operator::NotIn => write!(f, "not-in"),
Operator::Modulo => write!(f, "mod"),
Operator::FloorDivision => write!(f, "fdiv"),
Operator::And => write!(f, "&&"),
Operator::Or => write!(f, "||"),
Operator::Pow => write!(f, "**"),

View File

@ -1769,6 +1769,119 @@ impl Value {
}),
}
}
pub fn floor_div(&self, op: Span, rhs: &Value, span: Span) -> Result<Value, ShellError> {
match (self, rhs) {
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => {
if *rhs != 0 {
Ok(Value::Int {
val: (*lhs as f64 / *rhs as f64)
.max(std::i64::MIN as f64)
.min(std::i64::MAX as f64)
.floor() as i64,
span,
})
} else {
Err(ShellError::DivisionByZero(op))
}
}
(Value::Int { val: lhs, .. }, Value::Float { val: rhs, .. }) => {
if *rhs != 0.0 {
Ok(Value::Int {
val: (*lhs as f64 / *rhs)
.max(std::i64::MIN as f64)
.min(std::i64::MAX as f64)
.floor() as i64,
span,
})
} else {
Err(ShellError::DivisionByZero(op))
}
}
(Value::Float { val: lhs, .. }, Value::Int { val: rhs, .. }) => {
if *rhs != 0 {
Ok(Value::Int {
val: (*lhs / *rhs as f64)
.max(std::i64::MIN as f64)
.min(std::i64::MAX as f64)
.floor() as i64,
span,
})
} else {
Err(ShellError::DivisionByZero(op))
}
}
(Value::Float { val: lhs, .. }, Value::Float { val: rhs, .. }) => {
if *rhs != 0.0 {
Ok(Value::Int {
val: (lhs / rhs)
.max(std::i64::MIN as f64)
.min(std::i64::MAX as f64)
.floor() as i64,
span,
})
} else {
Err(ShellError::DivisionByZero(op))
}
}
(Value::Filesize { val: lhs, .. }, Value::Filesize { val: rhs, .. }) => {
if *rhs != 0 {
Ok(Value::Int {
val: (*lhs as f64 / *rhs as f64)
.max(std::i64::MIN as f64)
.min(std::i64::MAX as f64)
.floor() as i64,
span,
})
} else {
Err(ShellError::DivisionByZero(op))
}
}
(Value::Duration { val: lhs, .. }, Value::Duration { val: rhs, .. }) => {
if *rhs != 0 {
Ok(Value::Int {
val: (*lhs as f64 / *rhs as f64)
.max(std::i64::MIN as f64)
.min(std::i64::MAX as f64)
.floor() as i64,
span,
})
} else {
Err(ShellError::DivisionByZero(op))
}
}
(Value::Filesize { val: lhs, .. }, Value::Int { val: rhs, .. }) => {
if *rhs != 0 {
Ok(Value::Filesize {
val: lhs / rhs,
span,
})
} else {
Err(ShellError::DivisionByZero(op))
}
}
(Value::Duration { val: lhs, .. }, Value::Int { val: rhs, .. }) => {
if *rhs != 0 {
Ok(Value::Duration {
val: lhs / rhs,
span,
})
} else {
Err(ShellError::DivisionByZero(op))
}
}
(Value::CustomValue { val: lhs, span }, rhs) => {
lhs.operation(*span, Operator::Divide, op, rhs)
}
_ => 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 lt(&self, op: Span, rhs: &Value, span: Span) -> Result<Value, ShellError> {
if let (Value::CustomValue { val: lhs, span }, rhs) = (self, rhs) {
return lhs.operation(*span, Operator::LessThan, op, rhs);