git.delta.rocks / jrsonnet / refs/commits / f9925f61b616

difftreelog

fix(parser) desugar == to std.equals

Лач2020-06-04parent: #8c59188.patch.diff
in: master

4 files changed

modifiedcrates/jsonnet-evaluator/src/evaluate.rsdiffbeforeafterboth
--- a/crates/jsonnet-evaluator/src/evaluate.rs
+++ b/crates/jsonnet-evaluator/src/evaluate.rs
@@ -5,9 +5,8 @@
 };
 use closure::closure;
 use jsonnet_parser::{
-	el, Arg, ArgsDesc, AssertStmt, BinaryOpType, BindSpec, CompSpec, Expr, FieldMember,
-	ForSpecData, IfSpecData, LiteralType, LocExpr, Member, ObjBody, ParamsDesc, UnaryOpType,
-	Visibility,
+	ArgsDesc, AssertStmt, BinaryOpType, BindSpec, CompSpec, Expr, FieldMember, ForSpecData,
+	IfSpecData, LiteralType, LocExpr, Member, ObjBody, ParamsDesc, UnaryOpType, Visibility,
 };
 use std::{
 	collections::{BTreeMap, HashMap},
@@ -102,55 +101,20 @@
 		match (evaluate(context.clone(), &a)?.unwrap_if_lazy()?, op, b) {
 			(Val::Bool(true), BinaryOpType::Or, _o) => Val::Bool(true),
 			(Val::Bool(false), BinaryOpType::And, _o) => Val::Bool(false),
-			(a, op, eb) => evaluate_binary_op_normal(
-				context.clone(),
-				&a,
-				op,
-				&evaluate(context, eb)?.unwrap_if_lazy()?,
-			)?,
+			(a, op, eb) => {
+				evaluate_binary_op_normal(&a, op, &evaluate(context, eb)?.unwrap_if_lazy()?)?
+			}
 		},
 	)
 }
 
-pub fn evaluate_binary_op_normal(
-	context: Context,
-	a: &Val,
-	op: BinaryOpType,
-	b: &Val,
-) -> Result<Val> {
+pub fn evaluate_binary_op_normal(a: &Val, op: BinaryOpType, b: &Val) -> Result<Val> {
 	Ok(match (a, op, b) {
 		(a, BinaryOpType::Add, b) => evaluate_add_op(a, b)?,
-
-		(Val::Str(v1), BinaryOpType::Eq, Val::Str(v2)) => Val::Bool(v1 == v2),
-		(Val::Str(v1), BinaryOpType::Ne, Val::Str(v2)) => Val::Bool(v1 != v2),
 
 		(Val::Str(v1), BinaryOpType::Mul, Val::Num(v2)) => Val::Str(v1.repeat(*v2 as usize)),
-		(Val::Str(format), BinaryOpType::Mod, args) => evaluate(
-			context
-				.with_var("__tmp__format__".to_owned(), Val::Str(format.to_owned()))?
-				.with_var(
-					"__tmp__args__".to_owned(),
-					match args {
-						Val::Arr(v) => Val::Arr(v.clone()),
-						v => Val::Arr(vec![v.clone()]),
-					},
-				)?,
-			&el!(Expr::Apply(
-				el!(Expr::Index(
-					el!(Expr::Var("std".to_owned())),
-					el!(Expr::Str("format".to_owned()))
-				)),
-				ArgsDesc(vec![
-					Arg(None, el!(Expr::Var("__tmp__format__".to_owned()))),
-					Arg(None, el!(Expr::Var("__tmp__args__".to_owned())))
-				])
-			)),
-		)?,
 
 		// Bool X Bool
-		(Val::Bool(a), BinaryOpType::Eq, Val::Bool(b)) => Val::Bool(a == b),
-		(Val::Bool(a), BinaryOpType::Ne, Val::Bool(b)) => Val::Bool(a != b),
-
 		(Val::Bool(a), BinaryOpType::And, Val::Bool(b)) => Val::Bool(*a && *b),
 		(Val::Bool(a), BinaryOpType::Or, Val::Bool(b)) => Val::Bool(*a || *b),
 
@@ -163,7 +127,6 @@
 		// Num X Num
 		(Val::Num(v1), BinaryOpType::Mul, Val::Num(v2)) => Val::Num(v1 * v2),
 		(Val::Num(v1), BinaryOpType::Div, Val::Num(v2)) => Val::Num(v1 / v2),
-		(Val::Num(v1), BinaryOpType::Mod, Val::Num(v2)) => Val::Num(v1 % v2),
 
 		(Val::Num(v1), BinaryOpType::Sub, Val::Num(v2)) => Val::Num(v1 - v2),
 
@@ -171,9 +134,6 @@
 		(Val::Num(v1), BinaryOpType::Gt, Val::Num(v2)) => Val::Bool(v1 > v2),
 		(Val::Num(v1), BinaryOpType::Lte, Val::Num(v2)) => Val::Bool(v1 <= v2),
 		(Val::Num(v1), BinaryOpType::Gte, Val::Num(v2)) => Val::Bool(v1 >= v2),
-
-		(Val::Num(v1), BinaryOpType::Eq, Val::Num(v2)) => Val::Bool((v1 - v2).abs() < f64::EPSILON),
-		(Val::Num(v1), BinaryOpType::Ne, Val::Num(v2)) => Val::Bool((v1 - v2).abs() > f64::EPSILON),
 
 		(Val::Num(v1), BinaryOpType::BitAnd, Val::Num(v2)) => {
 			Val::Num(((*v1 as i32) & (*v2 as i32)) as f64)
@@ -191,28 +151,6 @@
 			Val::Num(((*v1 as i32) >> (*v2 as i32)) as f64)
 		}
 
-		// Arr X Arr
-		(Val::Arr(a), BinaryOpType::Eq, Val::Arr(b)) => {
-			if a.len() != b.len() {
-				Val::Bool(false)
-			} else {
-				for i in 0..a.len() {
-					if let Val::Bool(v) = evaluate_binary_op_normal(
-						context.clone(),
-						&a[i].clone().unwrap_if_lazy()?,
-						op,
-						&b[i].clone().unwrap_if_lazy()?,
-					)? {
-						if !v {
-							return Ok(Val::Bool(false));
-						}
-					} else {
-						unreachable!()
-					}
-				}
-				return Ok(Val::Bool(true));
-			}
-		}
 		_ => panic!("no rules for binary operation: {:?} {:?} {:?}", a, op, b),
 	})
 }
@@ -385,7 +323,7 @@
 		Index(value, index) => {
 			match (
 				evaluate(context.clone(), value)?.unwrap_if_lazy()?,
-				evaluate(context.clone(), index)?,
+				evaluate(context, index)?,
 			) {
 				(Val::Obj(v), Val::Str(s)) => {
 					if let Some(v) = v.get(&s)? {
@@ -506,9 +444,17 @@
 							panic!("bad objectFieldsEx call");
 						}
 					}
+					("std", "primitiveEquals") => {
+						assert_eq!(args.len(), 2);
+						let (a, b) = (
+							evaluate(context.clone(), &args[0].1)?,
+							evaluate(context, &args[1].1)?,
+						);
+						Val::Bool(a == b)
+					}
 					(ns, name) => panic!("Intristic not found: {}.{}", ns, name),
 				},
-				Val::Func(f) => push(locexpr.clone(), "function call".to_owned(), || {
+				Val::Func(f) => push(locexpr, "function call".to_owned(), || {
 					f.evaluate(
 						args.clone()
 							.into_iter()
@@ -528,10 +474,11 @@
 		}
 		Function(params, body) => evaluate_method(context, body, params.clone()),
 		AssertExpr(AssertStmt(value, msg), returned) => {
-			if push(value.clone(), "assertion condition".to_owned(), || {
+			let assertion_result = push(value.clone(), "assertion condition".to_owned(), || {
 				evaluate(context.clone(), &value)?
 					.try_cast_bool("assertion condition should be boolean")
-			})? {
+			})?;
+			if assertion_result {
 				push(
 					returned.clone(),
 					"assert 'return' branch".to_owned(),
@@ -555,9 +502,10 @@
 			cond_then,
 			cond_else,
 		} => {
-			if push(cond.0.clone(), "if condition".to_owned(), || {
+			let condition_result = push(cond.0.clone(), "if condition".to_owned(), || {
 				evaluate(context.clone(), &cond.0)?.try_cast_bool("if condition should be boolean")
-			})? {
+			})?;
+			if condition_result {
 				push(
 					cond_then.clone(),
 					"if condition 'then' branch".to_owned(),
modifiedcrates/jsonnet-parser/Cargo.tomldiffbeforeafterboth
--- a/crates/jsonnet-parser/Cargo.toml
+++ b/crates/jsonnet-parser/Cargo.toml
@@ -7,7 +7,7 @@
 [features]
 default = []
 # Trace peg token parsing
-trace = ["peg/trace"]
+# trace = ["peg/trace"]
 # TODO:
 # serialize = ["serde"]
 
modifiedcrates/jsonnet-parser/src/expr.rsdiffbeforeafterboth
50pub enum BinaryOpType {50pub enum BinaryOpType {
51 Mul,51 Mul,
52 Div,52 Div,
53 // Mod is desugared to stdlib53 // Mod is desugared to std.mod
54 // Mod,54 // Mod,
55 Add,55 Add,
56 Sub,56 Sub,
6565
66 In,66 In,
6767
68 Eq,68 // Eq/Ne is desugared to std.equals
69 Ne,69 // Eq,
70 // Ne,
7071
71 BitAnd,72 BitAnd,
72 BitOr,73 BitOr,
modifiedcrates/jsonnet-parser/src/lib.rsdiffbeforeafterboth
--- a/crates/jsonnet-parser/src/lib.rs
+++ b/crates/jsonnet-parser/src/lib.rs
@@ -230,8 +230,18 @@
 				--
 				a:(@) _ "&" _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::BitAnd, b))}
 				--
-				a:(@) _ "==" _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Eq, b))}
-				a:(@) _ "!=" _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Ne, b))}
+				a:(@) _ "==" _ b:@ {loc_expr_todo!(Expr::Apply(
+					el!(Expr::Index(
+						el!(Expr::Var("std".to_owned())),
+						el!(Expr::Str("equals".to_owned()))
+					)), ArgsDesc(vec![Arg(None, a), Arg(None, b)])
+				))}
+				a:(@) _ "!=" _ b:@ {loc_expr_todo!(Expr::UnaryOp(UnaryOpType::Not, el!(Expr::Apply(
+					el!(Expr::Index(
+						el!(Expr::Var("std".to_owned())),
+						el!(Expr::Str("equals".to_owned()))
+					)), ArgsDesc(vec![Arg(None, a), Arg(None, b)])
+				))))}
 				--
 				a:(@) _ "<" _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Lt, b))}
 				a:(@) _ ">" _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Gt, b))}
@@ -385,25 +395,6 @@
 				el!(Expr::Num(2.0)),
 				BinaryOpType::Sub,
 				el!(Expr::Num(22.0))
-			))
-		);
-	}
-
-	#[test]
-	fn suffix_comparsion() {
-		use Expr::*;
-		assert_eq!(
-			parse!("std.type(a) == \"string\""),
-			el!(BinaryOp(
-				el!(Apply(
-					el!(Index(
-						el!(Var("std".to_owned())),
-						el!(Str("type".to_owned()))
-					)),
-					ArgsDesc(vec![Arg(None, el!(Var("a".to_owned())))])
-				)),
-				BinaryOpType::Eq,
-				el!(Str("string".to_owned()))
 			))
 		);
 	}
@@ -427,37 +418,6 @@
 				))]
 			)),
 		)
-	}
-
-	#[test]
-	fn array_comp_with_ifs() {
-		use Expr::*;
-		assert_eq!(
-			parse!("[k for k in std.objectFields(patch) if patch[k] == null]"),
-			el!(ArrComp(
-				el!(Var("k".to_owned())),
-				vec![
-					CompSpec::ForSpec(ForSpecData(
-						"k".to_owned(),
-						el!(Apply(
-							el!(Index(
-								el!(Var("std".to_owned())),
-								el!(Str("objectFields".to_owned()))
-							)),
-							ArgsDesc(vec![Arg(None, el!(Var("patch".to_owned())))])
-						))
-					)),
-					CompSpec::IfSpec(IfSpecData(el!(BinaryOp(
-						el!(Index(
-							el!(Var("patch".to_owned())),
-							el!(Var("k".to_owned()))
-						)),
-						BinaryOpType::Eq,
-						el!(Literal(LiteralType::Null))
-					))))
-				]
-			))
-		);
 	}
 
 	#[test]