difftreelog
fix(parser) desugar == to std.equals
in: master
4 files changed
crates/jsonnet-evaluator/src/evaluate.rsdiffbeforeafterboth5};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}114110115pub 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)?,123124 (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),126114127 (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 context130 .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 )?,149116150 // Bool X Bool117 // Bool X Bool151 (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),153154 (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 Num164 (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),167130168 (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),169132172 (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),174175 (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),177137178 (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 }193153194 // Arr X Arr195 (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(),crates/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"]
crates/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,
crates/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]