Skip to content

Commit a3d43fd

Browse files
committed
Try to handle Division better
1 parent dd83bcf commit a3d43fd

File tree

1 file changed

+63
-32
lines changed

1 file changed

+63
-32
lines changed

primitives/src/targeting/eval.rs

Lines changed: 63 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -194,39 +194,23 @@ fn eval(input: &Input, output: &mut Output, rule: &Rule) -> Result<Option<Value>
194194
// basic operators
195195
let value = match function {
196196
Function::Div(first_rule, second_rule) => {
197-
let value = match first_rule.eval(input, output)?.ok_or(Error::TypeError)? {
198-
Value::Number(first_number) => {
199-
match second_rule.eval(input, output)?.ok_or(Error::TypeError)? {
200-
Value::Number(second_number) => {
201-
if let Some(num) = first_number.as_f64() {
202-
let divided =
203-
num.div(second_number.as_f64().ok_or(Error::TypeError)?);
204-
205-
Value::Number(Number::from_f64(divided).ok_or(Error::TypeError)?)
206-
} else if let Some(num) = first_number.as_i64() {
207-
let rhs = second_number.as_i64().ok_or(Error::TypeError)?;
208-
let divided = num.checked_div(rhs).ok_or(Error::TypeError)?;
209-
210-
Value::Number(divided.into())
211-
} else if let Some(num) = first_number.as_u64() {
212-
let rhs = second_number.as_u64().ok_or(Error::TypeError)?;
213-
let divided = num.checked_div(rhs).ok_or(Error::TypeError)?;
214-
215-
Value::Number(divided.into())
216-
} else {
217-
return Err(Error::TypeError);
218-
}
219-
}
220-
_ => return Err(Error::TypeError),
221-
}
222-
}
223-
Value::BigNum(first_bignum) => {
224-
let second_bignum = second_rule
225-
.eval(input, output)?
226-
.ok_or(Error::TypeError)?
227-
.try_bignum()?;
197+
let first_eval = first_rule.eval(input, output)?.ok_or(Error::TypeError)?;
198+
let second_eval = second_rule.eval(input, output)?.ok_or(Error::TypeError)?;
199+
228200

229-
Value::BigNum(first_bignum.div(second_bignum))
201+
let value = match (first_eval, second_eval) {
202+
(Value::BigNum(bignum), second_value) => {
203+
let second_bignum = BigNum::try_from(second_value)?;
204+
205+
Value::BigNum(bignum.div(second_bignum))
206+
},
207+
(lhs_value, Value::BigNum(rhs_bignum)) => {
208+
let lhs_bignum = BigNum::try_from(lhs_value)?;
209+
210+
Value::BigNum(lhs_bignum.div(rhs_bignum))
211+
}
212+
(Value::Number(lhs), Value::Number(rhs)) => {
213+
Value::Number(math_operator(lhs, rhs, MathOperator::Division)?)
230214
}
231215
_ => return Err(Error::TypeError),
232216
};
@@ -318,6 +302,53 @@ fn eval(input: &Input, output: &mut Output, rule: &Rule) -> Result<Option<Value>
318302
Ok(value)
319303
}
320304

305+
enum MathOperator {
306+
Division
307+
}
308+
309+
fn math_operator(lhs: Number, rhs: Number, ops: MathOperator) -> Result<Number, Error> {
310+
match (lhs.as_u64(), rhs.as_u64()) {
311+
(Some(lhs), Some(rhs)) => {
312+
match ops {
313+
MathOperator::Division => {
314+
let divided = lhs.checked_div(rhs).ok_or(Error::TypeError)?;
315+
316+
Ok(divided.into())
317+
}
318+
}
319+
}
320+
_ => {
321+
// i64s
322+
match (lhs.as_i64(), rhs.as_i64()) {
323+
(Some(lhs), Some(rhs)) => {
324+
match ops {
325+
MathOperator::Division => {
326+
let divided = lhs.checked_div(rhs).ok_or(Error::TypeError)?;
327+
328+
Ok(divided.into())
329+
}
330+
}
331+
}
332+
_ => {
333+
// f64s
334+
match (lhs.as_f64(), rhs.as_f64()) {
335+
(Some(lhs), Some(rhs)) => {
336+
match ops {
337+
MathOperator::Division => {
338+
let divided = lhs.div(rhs);
339+
340+
Ok(Number::from_f64(divided).ok_or(Error::TypeError)?)
341+
}
342+
}
343+
}
344+
_ => return Err(Error::TypeError)
345+
}
346+
}
347+
}
348+
}
349+
}
350+
}
351+
321352
#[cfg(test)]
322353
mod test {
323354
use super::*;

0 commit comments

Comments
 (0)