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
7[features]7[features]
8default = []8default = []
9# Trace peg token parsing9# Trace peg token parsing
10trace = ["peg/trace"]10# trace = ["peg/trace"]
11# TODO:11# TODO:
12# serialize = ["serde"]12# serialize = ["serde"]
1313
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
230 --230 --
231 a:(@) _ "&" _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::BitAnd, b))}231 a:(@) _ "&" _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::BitAnd, b))}
232 --232 --
233 a:(@) _ "==" _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Eq, b))}233 a:(@) _ "==" _ b:@ {loc_expr_todo!(Expr::Apply(
234 el!(Expr::Index(
235 el!(Expr::Var("std".to_owned())),
236 el!(Expr::Str("equals".to_owned()))
237 )), ArgsDesc(vec![Arg(None, a), Arg(None, b)])
238 ))}
234 a:(@) _ "!=" _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Ne, b))}239 a:(@) _ "!=" _ b:@ {loc_expr_todo!(Expr::UnaryOp(UnaryOpType::Not, el!(Expr::Apply(
240 el!(Expr::Index(
241 el!(Expr::Var("std".to_owned())),
242 el!(Expr::Str("equals".to_owned()))
243 )), ArgsDesc(vec![Arg(None, a), Arg(None, b)])
244 ))))}
235 --245 --
236 a:(@) _ "<" _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Lt, b))}246 a:(@) _ "<" _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Lt, b))}
237 a:(@) _ ">" _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Gt, b))}247 a:(@) _ ">" _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Gt, b))}
389 );399 );
390 }400 }
391
392 #[test]
393 fn suffix_comparsion() {
394 use Expr::*;
395 assert_eq!(
396 parse!("std.type(a) == \"string\""),
397 el!(BinaryOp(
398 el!(Apply(
399 el!(Index(
400 el!(Var("std".to_owned())),
401 el!(Str("type".to_owned()))
402 )),
403 ArgsDesc(vec![Arg(None, el!(Var("a".to_owned())))])
404 )),
405 BinaryOpType::Eq,
406 el!(Str("string".to_owned()))
407 ))
408 );
409 }
410401
411 #[test]402 #[test]
412 fn array_comp() {403 fn array_comp() {
429 )420 )
430 }421 }
431
432 #[test]
433 fn array_comp_with_ifs() {
434 use Expr::*;
435 assert_eq!(
436 parse!("[k for k in std.objectFields(patch) if patch[k] == null]"),
437 el!(ArrComp(
438 el!(Var("k".to_owned())),
439 vec![
440 CompSpec::ForSpec(ForSpecData(
441 "k".to_owned(),
442 el!(Apply(
443 el!(Index(
444 el!(Var("std".to_owned())),
445 el!(Str("objectFields".to_owned()))
446 )),
447 ArgsDesc(vec![Arg(None, el!(Var("patch".to_owned())))])
448 ))
449 )),
450 CompSpec::IfSpec(IfSpecData(el!(BinaryOp(
451 el!(Index(
452 el!(Var("patch".to_owned())),
453 el!(Var("k".to_owned()))
454 )),
455 BinaryOpType::Eq,
456 el!(Literal(LiteralType::Null))
457 ))))
458 ]
459 ))
460 );
461 }
462422
463 #[test]423 #[test]
464 fn reserved() {424 fn reserved() {