difftreelog
feat more math operations for bigint (#198)
in: master
* feat: properly implement math ops for bigint * feat: remove bigint x string and bigint x num ops every op now requires explicit conversion * fix: remove dead code
1 file changed
crates/jrsonnet-evaluator/src/evaluate/operator.rsdiffbeforeafterboth223use jrsonnet_parser::{BinaryOpType, LocExpr, UnaryOpType};3use jrsonnet_parser::{BinaryOpType, LocExpr, UnaryOpType};445#[cfg(feature = "exp-bigint")]6use num_traits::{FromPrimitive, ToPrimitive};78#[cfg(feature = "exp-bigint")]9use crate::val::NumValue;5use crate::{10use crate::{6 arr::ArrValue,11 arr::ArrValue,7 bail,12 bail,51 })58 })52}59}6061pub fn evaluate_sub_op(a: &Val, b: &Val) -> Result<Val> {62 use Val::*;63 Ok(match (a, b) {64 (Num(v1), Num(v2)) => Val::try_num(v1.get() - v2.get())?,6566 #[cfg(feature = "exp-bigint")]67 (BigInt(a), BigInt(b)) => BigInt(Box::new(&**a - &**b)),6869 // TODO: Support objects and arrays70 _ => bail!(BinaryOperatorDoesNotOperateOnValues(71 BinaryOpType::Sub,72 a.value_type(),73 b.value_type(),74 )),75 })76}7778pub fn evaluate_mul_op(a: &Val, b: &Val) -> Result<Val> {79 use Val::*;80 Ok(match (a, b) {81 (Str(s), Num(c)) => Val::string(s.to_string().repeat(c.get() as usize)),82 (Num(c), Str(s)) => Val::string(s.to_string().repeat(c.get() as usize)),8384 (Num(v1), Num(v2)) => Val::try_num(v1.get() * v2.get())?,8586 #[cfg(feature = "exp-bigint")]87 (BigInt(a), BigInt(b)) => BigInt(Box::new(&**a * &**b)),8889 _ => bail!(BinaryOperatorDoesNotOperateOnValues(90 BinaryOpType::Mul,91 a.value_type(),92 b.value_type(),93 )),94 })95}9697fn is_attempt_to_divide_by_zero(a: &Val, b: &Val) -> bool {98 use Val::*;99 match (a, b) {100 // string format101 (Str(_), _) => false,102103 (_, Num(b)) => return **b == 0.,104 #[cfg(feature = "exp-bigint")]105 (_, BigInt(b)) => return **b == num_bigint::BigInt::ZERO,106107 // something else108 _ => false,109 }110}111112pub fn evaluate_div_op(a: &Val, b: &Val) -> Result<Val> {113 use Val::*;114115 if is_attempt_to_divide_by_zero(a, b) {116 bail!(DivisionByZero);117 }118119 Ok(match (a, b) {120 (Num(a), Num(b)) => Val::try_num(a.get() / b.get())?,121 #[cfg(feature = "exp-bigint")]122 (BigInt(a), BigInt(b)) => BigInt(Box::new(&**a / &**b)),123 (a, b) => bail!(BinaryOperatorDoesNotOperateOnValues(124 BinaryOpType::Div,125 a.value_type(),126 b.value_type()127 )),128 })129}5313054pub fn evaluate_mod_op(a: &Val, b: &Val) -> Result<Val> {131pub fn evaluate_mod_op(a: &Val, b: &Val) -> Result<Val> {55 use Val::*;132 use Val::*;133134 if is_attempt_to_divide_by_zero(a, b) {135 bail!(DivisionByZero);136 }13756 match (a, b) {138 Ok(match (a, b) {57 (Num(a), Num(b)) => {139 (Num(a), Num(b)) => Val::try_num(a.get() % b.get())?,58 if b.get() == 0.0 {140 #[cfg(feature = "exp-bigint")]59 bail!(DivisionByZero)141 (BigInt(a), BigInt(b)) => BigInt(Box::new(&**a % &**b)),60 }61 Ok(Val::try_num(a.get() % b.get())?)62 }63 (Str(str), vals) => {142 (Str(str), vals) => {64 String::into_untyped(std_format(&str.clone().into_flat(), vals.clone())?)143 String::into_untyped(std_format(&str.clone().into_flat(), vals.clone())?)?65 }144 }66 (a, b) => bail!(BinaryOperatorDoesNotOperateOnValues(145 (a, b) => bail!(BinaryOperatorDoesNotOperateOnValues(67 BinaryOpType::Mod,146 BinaryOpType::Mod,68 a.value_type(),147 a.value_type(),69 b.value_type()148 b.value_type()70 )),149 )),71 }150 })72}151}7315274pub fn evaluate_binary_op_special(153pub fn evaluate_binary_op_special(121 use BinaryOpType::*;203 use BinaryOpType::*;122 use Val::*;204 use Val::*;123 Ok(match (a, op, b) {205 Ok(match (a, op, b) {124 (a, Add, b) => evaluate_add_op(a, b)?,125126 (a, Eq, b) => Bool(equals(a, b)?),206 (a, Eq, b) => Bool(equals(a, b)?),127 (a, Neq, b) => Bool(!equals(a, b)?),207 (a, Neq, b) => Bool(!equals(a, b)?),132 (a, Gte, b) => Bool(evaluate_compare_op(a, b, Gte)?.is_ge()),212 (a, Gte, b) => Bool(evaluate_compare_op(a, b, Gte)?.is_ge()),133213134 (Str(a), In, Obj(obj)) => Bool(obj.has_field_ex(a.clone().into_flat(), true)),214 (Str(a), In, Obj(obj)) => Bool(obj.has_field_ex(a.clone().into_flat(), true)),135 (a, Mod, b) => evaluate_mod_op(a, b)?,136137 (Str(v1), Mul, Num(v2)) => Val::string(v1.to_string().repeat(v2.get() as usize)),138215139 // Bool X Bool216 // Bool X Bool140 (Bool(a), And, Bool(b)) => Bool(*a && *b),217 (Bool(a), And, Bool(b)) => Bool(*a && *b),141 (Bool(a), Or, Bool(b)) => Bool(*a || *b),218 (Bool(a), Or, Bool(b)) => Bool(*a || *b),142219143 // Num X Num220 (a, Add, b) => evaluate_add_op(a, b)?,221 (a, Sub, b) => evaluate_sub_op(a, b)?,144 (Num(v1), Mul, Num(v2)) => Val::try_num(v1.get() * v2.get())?,222 (a, Mul, b) => evaluate_mul_op(a, b)?,145 (Num(v1), Div, Num(v2)) => {223 (a, Div, b) => evaluate_div_op(a, b)?,146 if v2.get() == 0.0 {147 bail!(DivisionByZero)148 }149 Val::try_num(v1.get() / v2.get())?150 }151152 (Num(v1), Sub, Num(v2)) => Val::try_num(v1.get() - v2.get())?,224 (a, Mod, b) => evaluate_mod_op(a, b)?,153225154 (Num(v1), BitAnd, Num(v2)) => Val::try_num((v1.get() as i64 & v2.get() as i64) as f64)?,226 (Num(v1), BitAnd, Num(v2)) => Val::try_num((v1.get() as i64 & v2.get() as i64) as f64)?,155 (Num(v1), BitOr, Num(v2)) => Val::try_num((v1.get() as i64 | v2.get() as i64) as f64)?,227 (Num(v1), BitOr, Num(v2)) => Val::try_num((v1.get() as i64 | v2.get() as i64) as f64)?,170 }242 }171243172 // Bigint X Bigint244 // Bigint X Bigint173 #[cfg(feature = "exp-bigint")]174 (BigInt(a), Mul, BigInt(b)) => BigInt(Box::new(&**a * &**b)),175 #[cfg(feature = "exp-bigint")]176 (BigInt(a), Sub, BigInt(b)) => BigInt(Box::new(&**a - &**b)),177178 _ => bail!(BinaryOperatorDoesNotOperateOnValues(245 _ => bail!(BinaryOperatorDoesNotOperateOnValues(179 op,246 op,