git.delta.rocks / jrsonnet / refs/commits / 53ec857983ef

difftreelog

refactor skip desugaring for in operator

Yaroslav Bolyukin2021-07-04parent: #f047fb1.patch.diff
in: master

3 files changed

modifiedcrates/jrsonnet-evaluator/src/evaluate/operator.rsdiffbeforeafterboth
before · crates/jrsonnet-evaluator/src/evaluate/operator.rs
1use crate::{equals, evaluate, Context, Val};2use crate::{error::Error::*, throw, Result};3use jrsonnet_parser::{BinaryOpType, LocExpr, UnaryOpType};45pub fn evaluate_unary_op(op: UnaryOpType, b: &Val) -> Result<Val> {6	use UnaryOpType::*;7	use Val::*;8	Ok(match (op, b) {9		(Not, Bool(v)) => Bool(!v),10		(Minus, Num(n)) => Num(-*n),11		(BitNot, Num(n)) => Num(!(*n as i32) as f64),12		(op, o) => throw!(UnaryOperatorDoesNotOperateOnType(op, o.value_type())),13	})14}1516pub fn evaluate_add_op(a: &Val, b: &Val) -> Result<Val> {17	use Val::*;18	Ok(match (a, b) {19		(Str(v1), Str(v2)) => Str(((**v1).to_owned() + v2).into()),2021		// Can't use generic json serialization way, because it depends on number to string concatenation (std.jsonnet:890)22		(Num(n), Str(o)) => Str(format!("{}{}", n, o).into()),23		(Str(o), Num(n)) => Str(format!("{}{}", o, n).into()),2425		(Str(s), o) => Str(format!("{}{}", s, o.clone().to_string()?).into()),26		(o, Str(s)) => Str(format!("{}{}", o.clone().to_string()?, s).into()),2728		(Obj(v1), Obj(v2)) => Obj(v2.extend_from(v1.clone())),29		(Arr(a), Arr(b)) => {30			let mut out = Vec::with_capacity(a.len() + b.len());31			out.extend(a.iter_lazy());32			out.extend(b.iter_lazy());33			Arr(out.into())34		}35		(Num(v1), Num(v2)) => Val::new_checked_num(v1 + v2)?,36		_ => throw!(BinaryOperatorDoesNotOperateOnValues(37			BinaryOpType::Add,38			a.value_type(),39			b.value_type(),40		)),41	})42}4344pub fn evaluate_binary_op_special(45	context: Context,46	a: &LocExpr,47	op: BinaryOpType,48	b: &LocExpr,49) -> Result<Val> {50	use BinaryOpType::*;51	use Val::*;52	Ok(match (evaluate(context.clone(), a)?, op, b) {53		(Bool(true), Or, _o) => Val::Bool(true),54		(Bool(false), And, _o) => Val::Bool(false),55		(a, op, eb) => evaluate_binary_op_normal(&a, op, &evaluate(context, eb)?)?,56	})57}5859pub fn evaluate_binary_op_normal(a: &Val, op: BinaryOpType, b: &Val) -> Result<Val> {60	use BinaryOpType::*;61	use Val::*;62	Ok(match (a, op, b) {63		(a, Add, b) => evaluate_add_op(a, b)?,6465		(a, Eq, b) => Bool(equals(a, b)?),66		(a, Neq, b) => Bool(!equals(a, b)?),6768		(Str(v1), Mul, Num(v2)) => Str(v1.repeat(*v2 as usize).into()),6970		// Bool X Bool71		(Bool(a), And, Bool(b)) => Bool(*a && *b),72		(Bool(a), Or, Bool(b)) => Bool(*a || *b),7374		// Str X Str75		(Str(v1), Lt, Str(v2)) => Bool(v1 < v2),76		(Str(v1), Gt, Str(v2)) => Bool(v1 > v2),77		(Str(v1), Lte, Str(v2)) => Bool(v1 <= v2),78		(Str(v1), Gte, Str(v2)) => Bool(v1 >= v2),7980		// Num X Num81		(Num(v1), Mul, Num(v2)) => Val::new_checked_num(v1 * v2)?,82		(Num(v1), Div, Num(v2)) => {83			if *v2 <= f64::EPSILON {84				throw!(DivisionByZero)85			}86			Val::new_checked_num(v1 / v2)?87		}8889		(Num(v1), Sub, Num(v2)) => Val::new_checked_num(v1 - v2)?,9091		(Num(v1), Lt, Num(v2)) => Bool(v1 < v2),92		(Num(v1), Gt, Num(v2)) => Bool(v1 > v2),93		(Num(v1), Lte, Num(v2)) => Bool(v1 <= v2),94		(Num(v1), Gte, Num(v2)) => Bool(v1 >= v2),9596		(Num(v1), BitAnd, Num(v2)) => Num(((*v1 as i32) & (*v2 as i32)) as f64),97		(Num(v1), BitOr, Num(v2)) => Num(((*v1 as i32) | (*v2 as i32)) as f64),98		(Num(v1), BitXor, Num(v2)) => Num(((*v1 as i32) ^ (*v2 as i32)) as f64),99		(Num(v1), Lhs, Num(v2)) => {100			if *v2 < 0.0 {101				throw!(RuntimeError("shift by negative exponent".into()))102			}103			Num(((*v1 as i32) << (*v2 as i32)) as f64)104		}105		(Num(v1), Rhs, Num(v2)) => {106			if *v2 < 0.0 {107				throw!(RuntimeError("shift by negative exponent".into()))108			}109			Num(((*v1 as i32) >> (*v2 as i32)) as f64)110		}111112		_ => throw!(BinaryOperatorDoesNotOperateOnValues(113			op,114			a.value_type(),115			b.value_type(),116		)),117	})118}
modifiedcrates/jrsonnet-parser/src/expr.rsdiffbeforeafterboth
--- a/crates/jrsonnet-parser/src/expr.rs
+++ b/crates/jrsonnet-parser/src/expr.rs
@@ -127,6 +127,9 @@
 
 	And,
 	Or,
+
+	// Equialent to std.objectHasEx(a, b, true)
+	In,
 }
 
 impl Display for BinaryOpType {
@@ -154,6 +157,7 @@
 				Neq => "!=",
 				And => "&&",
 				Or => "||",
+				In => "in",
 			}
 		)
 	}
modifiedcrates/jrsonnet-parser/src/lib.rsdiffbeforeafterboth
--- a/crates/jrsonnet-parser/src/lib.rs
+++ b/crates/jrsonnet-parser/src/lib.rs
@@ -217,38 +217,37 @@
 		rule unaryop(x: rule<()>) -> ()
 			= quiet!{ x() } / expected!("<unary op>")
 
+
+		use BinaryOpType::*;
 		rule expr(s: &ParserSettings) -> LocExpr
 			= start:position!() a:precedence! {
-				a:(@) _ binop(<"||">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Or, b))}
+				a:(@) _ binop(<"||">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, Or, b))}
 				--
-				a:(@) _ binop(<"&&">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::And, b))}
+				a:(@) _ binop(<"&&">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, And, b))}
 				--
-				a:(@) _ binop(<"|">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::BitOr, b))}
+				a:(@) _ binop(<"|">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BitOr, b))}
 				--
-				a:@ _ binop(<"^">) _ b:(@) {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::BitXor, b))}
+				a:@ _ binop(<"^">) _ b:(@) {loc_expr_todo!(Expr::BinaryOp(a, BitXor, b))}
 				--
-				a:(@) _ binop(<"&">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::BitAnd, b))}
+				a:(@) _ binop(<"&">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BitAnd, b))}
 				--
-				a:(@) _ binop(<"==">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Eq, b))}
-				a:(@) _ binop(<"!=">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Neq, b))}
+				a:(@) _ binop(<"==">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, Eq, b))}
+				a:(@) _ binop(<"!=">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, Neq, b))}
 				--
-				a:(@) _ binop(<"<">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Lt, b))}
-				a:(@) _ binop(<">">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Gt, b))}
-				a:(@) _ binop(<"<=">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Lte, b))}
-				a:(@) _ binop(<">=">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Gte, b))}
-				a:(@) _ binop(<keyword("in")>) _ b:@ {loc_expr_todo!(Expr::Apply(
-					el!(Expr::Intrinsic("objectHasEx".into())), ArgsDesc(vec![Arg(None, b), Arg(None, a), Arg(None, el!(Expr::Literal(LiteralType::True)))]),
-					true
-				))}
+				a:(@) _ binop(<"<">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, Lt, b))}
+				a:(@) _ binop(<">">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, Gt, b))}
+				a:(@) _ binop(<"<=">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, Lte, b))}
+				a:(@) _ binop(<">=">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, Gte, b))}
+				a:(@) _ binop(<keyword("in")>) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, In, b))}
 				--
-				a:(@) _ binop(<"<<">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Lhs, b))}
-				a:(@) _ binop(<">>">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Rhs, b))}
+				a:(@) _ binop(<"<<">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, Lhs, b))}
+				a:(@) _ binop(<">>">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, Rhs, b))}
 				--
-				a:(@) _ binop(<"+">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Add, b))}
-				a:(@) _ binop(<"-">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Sub, b))}
+				a:(@) _ binop(<"+">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, Add, b))}
+				a:(@) _ binop(<"-">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, Sub, b))}
 				--
-				a:(@) _ binop(<"*">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Mul, b))}
-				a:(@) _ binop(<"/">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Div, b))}
+				a:(@) _ binop(<"*">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, Mul, b))}
+				a:(@) _ binop(<"/">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, Div, b))}
 				a:(@) _ binop(<"%">) _ b:@ {loc_expr_todo!(Expr::Apply(
 					el!(Expr::Intrinsic("mod".into())), ArgsDesc(vec![Arg(None, a), Arg(None, b)]),
 					false
@@ -306,6 +305,7 @@
 	use super::{expr::*, parse};
 	use crate::ParserSettings;
 	use std::path::PathBuf;
+	use BinaryOpType::*;
 
 	macro_rules! parse {
 		($s:expr) => {
@@ -326,10 +326,10 @@
 		pub fn basic_math() -> LocExpr {
 			el!(Expr::BinaryOp(
 				el!(Expr::Num(2.0)),
-				BinaryOpType::Add,
+				Add,
 				el!(Expr::BinaryOp(
 					el!(Expr::Num(2.0)),
-					BinaryOpType::Mul,
+					Mul,
 					el!(Expr::Num(2.0)),
 				)),
 			))
@@ -417,10 +417,10 @@
 			parse!("2+2*2"),
 			el!(Expr::BinaryOp(
 				el!(Expr::Num(2.0)),
-				BinaryOpType::Add,
+				Add,
 				el!(Expr::BinaryOp(
 					el!(Expr::Num(2.0)),
-					BinaryOpType::Mul,
+					Mul,
 					el!(Expr::Num(2.0))
 				))
 			))
@@ -438,7 +438,7 @@
 			parse!("2+(2+2*2)"),
 			el!(Expr::BinaryOp(
 				el!(Expr::Num(2.0)),
-				BinaryOpType::Add,
+				Add,
 				el!(Expr::Parened(expressions::basic_math())),
 			))
 		);
@@ -451,10 +451,10 @@
 			parse!("2//comment\n+//comment\n3/*test*/*/*test*/4"),
 			el!(Expr::BinaryOp(
 				el!(Expr::Num(2.0)),
-				BinaryOpType::Add,
+				Add,
 				el!(Expr::BinaryOp(
 					el!(Expr::Num(3.0)),
-					BinaryOpType::Mul,
+					Mul,
 					el!(Expr::Num(4.0))
 				))
 			))
@@ -468,7 +468,7 @@
 			parse!("2/*\\*/+*/ - 22"),
 			el!(Expr::BinaryOp(
 				el!(Expr::Num(2.0)),
-				BinaryOpType::Sub,
+				Sub,
 				el!(Expr::Num(22.0))
 			))
 		);
@@ -520,7 +520,7 @@
 			parse!("!a && !b"),
 			el!(BinaryOp(
 				el!(UnaryOp(UnaryOpType::Not, el!(Var("a".into())))),
-				BinaryOpType::And,
+				And,
 				el!(UnaryOp(UnaryOpType::Not, el!(Var("b".into()))))
 			))
 		);
@@ -533,7 +533,7 @@
 			parse!("!a / !b"),
 			el!(BinaryOp(
 				el!(UnaryOp(UnaryOpType::Not, el!(Var("a".into())))),
-				BinaryOpType::Div,
+				Div,
 				el!(UnaryOp(UnaryOpType::Not, el!(Var("b".into()))))
 			))
 		);