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
5};5};
6use closure::closure;6use closure::closure;
7use jsonnet_parser::{7use jsonnet_parser::{
8 el, Arg, ArgsDesc, AssertStmt, BinaryOpType, BindSpec, CompSpec, Expr, FieldMember,8 ArgsDesc, AssertStmt, BinaryOpType, BindSpec, CompSpec, Expr, FieldMember, ForSpecData,
9 ForSpecData, IfSpecData, LiteralType, LocExpr, Member, ObjBody, ParamsDesc, UnaryOpType,9 IfSpecData, LiteralType, LocExpr, Member, ObjBody, ParamsDesc, UnaryOpType, Visibility,
10 Visibility,
11};10};
102 match (evaluate(context.clone(), &a)?.unwrap_if_lazy()?, op, b) {101 match (evaluate(context.clone(), &a)?.unwrap_if_lazy()?, op, b) {
103 (Val::Bool(true), BinaryOpType::Or, _o) => Val::Bool(true),102 (Val::Bool(true), BinaryOpType::Or, _o) => Val::Bool(true),
104 (Val::Bool(false), BinaryOpType::And, _o) => Val::Bool(false),103 (Val::Bool(false), BinaryOpType::And, _o) => Val::Bool(false),
105 (a, op, eb) => evaluate_binary_op_normal(104 (a, op, eb) => {
106 context.clone(),
107 &a,105 evaluate_binary_op_normal(&a, op, &evaluate(context, eb)?.unwrap_if_lazy()?)?
108 op,106 }
109 &evaluate(context, eb)?.unwrap_if_lazy()?,
110 )?,
111 },107 },
112 )108 )
113}109}
114110
115pub fn evaluate_binary_op_normal(111pub fn evaluate_binary_op_normal(a: &Val, op: BinaryOpType, b: &Val) -> Result<Val> {
116 context: Context,
117 a: &Val,
118 op: BinaryOpType,
119 b: &Val,
120) -> Result<Val> {
121 Ok(match (a, op, b) {112 Ok(match (a, op, b) {
122 (a, BinaryOpType::Add, b) => evaluate_add_op(a, b)?,113 (a, BinaryOpType::Add, b) => evaluate_add_op(a, b)?,
123
124 (Val::Str(v1), BinaryOpType::Eq, Val::Str(v2)) => Val::Bool(v1 == v2),
125 (Val::Str(v1), BinaryOpType::Ne, Val::Str(v2)) => Val::Bool(v1 != v2),
126114
127 (Val::Str(v1), BinaryOpType::Mul, Val::Num(v2)) => Val::Str(v1.repeat(*v2 as usize)),115 (Val::Str(v1), BinaryOpType::Mul, Val::Num(v2)) => Val::Str(v1.repeat(*v2 as usize)),
128 (Val::Str(format), BinaryOpType::Mod, args) => evaluate(
129 context
130 .with_var("__tmp__format__".to_owned(), Val::Str(format.to_owned()))?
131 .with_var(
132 "__tmp__args__".to_owned(),
133 match args {
134 Val::Arr(v) => Val::Arr(v.clone()),
135 v => Val::Arr(vec![v.clone()]),
136 },
137 )?,
138 &el!(Expr::Apply(
139 el!(Expr::Index(
140 el!(Expr::Var("std".to_owned())),
141 el!(Expr::Str("format".to_owned()))
142 )),
143 ArgsDesc(vec![
144 Arg(None, el!(Expr::Var("__tmp__format__".to_owned()))),
145 Arg(None, el!(Expr::Var("__tmp__args__".to_owned())))
146 ])
147 )),
148 )?,
149116
150 // Bool X Bool117 // Bool X Bool
151 (Val::Bool(a), BinaryOpType::Eq, Val::Bool(b)) => Val::Bool(a == b),
152 (Val::Bool(a), BinaryOpType::Ne, Val::Bool(b)) => Val::Bool(a != b),
153
154 (Val::Bool(a), BinaryOpType::And, Val::Bool(b)) => Val::Bool(*a && *b),118 (Val::Bool(a), BinaryOpType::And, Val::Bool(b)) => Val::Bool(*a && *b),
155 (Val::Bool(a), BinaryOpType::Or, Val::Bool(b)) => Val::Bool(*a || *b),119 (Val::Bool(a), BinaryOpType::Or, Val::Bool(b)) => Val::Bool(*a || *b),
163 // Num X Num127 // Num X Num
164 (Val::Num(v1), BinaryOpType::Mul, Val::Num(v2)) => Val::Num(v1 * v2),128 (Val::Num(v1), BinaryOpType::Mul, Val::Num(v2)) => Val::Num(v1 * v2),
165 (Val::Num(v1), BinaryOpType::Div, Val::Num(v2)) => Val::Num(v1 / v2),129 (Val::Num(v1), BinaryOpType::Div, Val::Num(v2)) => Val::Num(v1 / v2),
166 (Val::Num(v1), BinaryOpType::Mod, Val::Num(v2)) => Val::Num(v1 % v2),
167130
168 (Val::Num(v1), BinaryOpType::Sub, Val::Num(v2)) => Val::Num(v1 - v2),131 (Val::Num(v1), BinaryOpType::Sub, Val::Num(v2)) => Val::Num(v1 - v2),
169132
172 (Val::Num(v1), BinaryOpType::Lte, Val::Num(v2)) => Val::Bool(v1 <= v2),135 (Val::Num(v1), BinaryOpType::Lte, Val::Num(v2)) => Val::Bool(v1 <= v2),
173 (Val::Num(v1), BinaryOpType::Gte, Val::Num(v2)) => Val::Bool(v1 >= v2),136 (Val::Num(v1), BinaryOpType::Gte, Val::Num(v2)) => Val::Bool(v1 >= v2),
174
175 (Val::Num(v1), BinaryOpType::Eq, Val::Num(v2)) => Val::Bool((v1 - v2).abs() < f64::EPSILON),
176 (Val::Num(v1), BinaryOpType::Ne, Val::Num(v2)) => Val::Bool((v1 - v2).abs() > f64::EPSILON),
177137
178 (Val::Num(v1), BinaryOpType::BitAnd, Val::Num(v2)) => {138 (Val::Num(v1), BinaryOpType::BitAnd, Val::Num(v2)) => {
179 Val::Num(((*v1 as i32) & (*v2 as i32)) as f64)139 Val::Num(((*v1 as i32) & (*v2 as i32)) as f64)
191 Val::Num(((*v1 as i32) >> (*v2 as i32)) as f64)151 Val::Num(((*v1 as i32) >> (*v2 as i32)) as f64)
192 }152 }
193153
194 // Arr X Arr
195 (Val::Arr(a), BinaryOpType::Eq, Val::Arr(b)) => {
196 if a.len() != b.len() {
197 Val::Bool(false)
198 } else {
199 for i in 0..a.len() {
200 if let Val::Bool(v) = evaluate_binary_op_normal(
201 context.clone(),
202 &a[i].clone().unwrap_if_lazy()?,
203 op,
204 &b[i].clone().unwrap_if_lazy()?,
205 )? {
206 if !v {
207 return Ok(Val::Bool(false));
208 }
209 } else {
210 unreachable!()
211 }
212 }
213 return Ok(Val::Bool(true));
214 }
215 }
216 _ => panic!("no rules for binary operation: {:?} {:?} {:?}", a, op, b),154 _ => panic!("no rules for binary operation: {:?} {:?} {:?}", a, op, b),
217 })155 })
218}156}
385 Index(value, index) => {323 Index(value, index) => {
386 match (324 match (
387 evaluate(context.clone(), value)?.unwrap_if_lazy()?,325 evaluate(context.clone(), value)?.unwrap_if_lazy()?,
388 evaluate(context.clone(), index)?,326 evaluate(context, index)?,
389 ) {327 ) {
390 (Val::Obj(v), Val::Str(s)) => {328 (Val::Obj(v), Val::Str(s)) => {
391 if let Some(v) = v.get(&s)? {329 if let Some(v) = v.get(&s)? {
506 panic!("bad objectFieldsEx call");444 panic!("bad objectFieldsEx call");
507 }445 }
508 }446 }
447 ("std", "primitiveEquals") => {
448 assert_eq!(args.len(), 2);
449 let (a, b) = (
450 evaluate(context.clone(), &args[0].1)?,
451 evaluate(context, &args[1].1)?,
452 );
453 Val::Bool(a == b)
454 }
509 (ns, name) => panic!("Intristic not found: {}.{}", ns, name),455 (ns, name) => panic!("Intristic not found: {}.{}", ns, name),
510 },456 },
511 Val::Func(f) => push(locexpr.clone(), "function call".to_owned(), || {457 Val::Func(f) => push(locexpr, "function call".to_owned(), || {
512 f.evaluate(458 f.evaluate(
513 args.clone()459 args.clone()
514 .into_iter()460 .into_iter()
528 }474 }
529 Function(params, body) => evaluate_method(context, body, params.clone()),475 Function(params, body) => evaluate_method(context, body, params.clone()),
530 AssertExpr(AssertStmt(value, msg), returned) => {476 AssertExpr(AssertStmt(value, msg), returned) => {
531 if push(value.clone(), "assertion condition".to_owned(), || {477 let assertion_result = push(value.clone(), "assertion condition".to_owned(), || {
532 evaluate(context.clone(), &value)?478 evaluate(context.clone(), &value)?
533 .try_cast_bool("assertion condition should be boolean")479 .try_cast_bool("assertion condition should be boolean")
534 })? {480 })?;
481 if assertion_result {
535 push(482 push(
536 returned.clone(),483 returned.clone(),
537 "assert 'return' branch".to_owned(),484 "assert 'return' branch".to_owned(),
555 cond_then,502 cond_then,
556 cond_else,503 cond_else,
557 } => {504 } => {
558 if push(cond.0.clone(), "if condition".to_owned(), || {505 let condition_result = push(cond.0.clone(), "if condition".to_owned(), || {
559 evaluate(context.clone(), &cond.0)?.try_cast_bool("if condition should be boolean")506 evaluate(context.clone(), &cond.0)?.try_cast_bool("if condition should be boolean")
560 })? {507 })?;
508 if condition_result {
561 push(509 push(
562 cond_then.clone(),510 cond_then.clone(),
563 "if condition 'then' branch".to_owned(),511 "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
--- a/crates/jsonnet-parser/src/expr.rs
+++ b/crates/jsonnet-parser/src/expr.rs
@@ -50,7 +50,7 @@
 pub enum BinaryOpType {
 	Mul,
 	Div,
-	// Mod is desugared to stdlib
+	// Mod is desugared to std.mod
 	// Mod,
 	Add,
 	Sub,
@@ -65,8 +65,9 @@
 
 	In,
 
-	Eq,
-	Ne,
+	// Eq/Ne is desugared to std.equals
+	// Eq,
+	// Ne,
 
 	BitAnd,
 	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]