difftreelog
fix(evaluator) arrays should be lazy
in: master
2 files changed
crates/jsonnet-evaluator/src/evaluate.rsdiffbeforeafterboth--- a/crates/jsonnet-evaluator/src/evaluate.rs
+++ b/crates/jsonnet-evaluator/src/evaluate.rs
@@ -121,6 +121,7 @@
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)),
@@ -146,27 +147,26 @@
)),
)?,
+ // 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),
+ // Str X Str
+ (Val::Str(v1), BinaryOpType::Lt, Val::Str(v2)) => Val::Bool(v1 < v2),
+ (Val::Str(v1), BinaryOpType::Gt, Val::Str(v2)) => Val::Bool(v1 > v2),
+ (Val::Str(v1), BinaryOpType::Lte, Val::Str(v2)) => Val::Bool(v1 <= v2),
+ (Val::Str(v1), BinaryOpType::Gte, Val::Str(v2)) => Val::Bool(v1 >= v2),
+
+ // 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),
- (Val::Num(v1), BinaryOpType::Lhs, Val::Num(v2)) => {
- Val::Num(((*v1 as i32) << (*v2 as i32)) as f64)
- }
- (Val::Num(v1), BinaryOpType::Rhs, Val::Num(v2)) => {
- Val::Num(((*v1 as i32) >> (*v2 as i32)) as f64)
- }
-
- (Val::Str(v1), BinaryOpType::Lt, Val::Str(v2)) => Val::Bool(v1 < v2),
- (Val::Str(v1), BinaryOpType::Gt, Val::Str(v2)) => Val::Bool(v1 > v2),
- (Val::Str(v1), BinaryOpType::Lte, Val::Str(v2)) => Val::Bool(v1 <= v2),
- (Val::Str(v1), BinaryOpType::Gte, Val::Str(v2)) => Val::Bool(v1 >= v2),
-
(Val::Num(v1), BinaryOpType::Lt, Val::Num(v2)) => Val::Bool(v1 < v2),
(Val::Num(v1), BinaryOpType::Gt, Val::Num(v2)) => Val::Bool(v1 > v2),
(Val::Num(v1), BinaryOpType::Lte, Val::Num(v2)) => Val::Bool(v1 <= v2),
@@ -184,8 +184,35 @@
(Val::Num(v1), BinaryOpType::BitXor, Val::Num(v2)) => {
Val::Num(((*v1 as i32) ^ (*v2 as i32)) as f64)
}
- (a, BinaryOpType::Eq, b) => Val::Bool(a == b),
- (a, BinaryOpType::Ne, b) => Val::Bool(a != b),
+ (Val::Num(v1), BinaryOpType::Lhs, Val::Num(v2)) => {
+ Val::Num(((*v1 as i32) << (*v2 as i32)) as f64)
+ }
+ (Val::Num(v1), BinaryOpType::Rhs, Val::Num(v2)) => {
+ 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),
})
}
@@ -212,7 +239,7 @@
Val::Arr(list) => {
let mut out = Vec::new();
for item in list {
- let item = item.clone();
+ let item = item.clone().unwrap_if_lazy()?;
out.push(evaluate_comp(
context.with_var(var.clone(), item)?,
value,
@@ -372,7 +399,8 @@
(Val::Arr(v), Val::Num(n)) => v
.get(n as usize)
.unwrap_or_else(|| panic!("out of bounds"))
- .clone(),
+ .clone()
+ .unwrap_if_lazy()?,
(Val::Str(s), Val::Num(n)) => {
Val::Str(s.chars().skip(n as usize).take(1).collect())
}
@@ -402,7 +430,11 @@
Arr(items) => {
let mut out = Vec::with_capacity(items.len());
for item in items {
- out.push(evaluate(context.clone(), item)?);
+ out.push(Val::Lazy(lazy_val!(
+ closure!(clone context, clone item, || {
+ evaluate(context.clone(), &item)
+ })
+ )));
}
Val::Arr(out)
}
crates/jsonnet-evaluator/src/val.rsdiffbeforeafterboth44}44}45impl Debug for LazyVal {45impl Debug for LazyVal {46 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {46 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {47 if self.0.cached.borrow().is_some() {48 write!(f, "{:?}", self.0.cached.borrow().clone().unwrap())49 } else {47 write!(f, "Lazy")50 write!(f, "Lazy")48 }51 }52 }49}53}50impl PartialEq for LazyVal {54impl PartialEq for LazyVal {