difftreelog
fix ObjExtend should work with non-object lhs
in: master
2 files changed
crates/jrsonnet-evaluator/src/evaluate/mod.rsdiffbeforeafterboth8use self::{8use self::{9 compspec::{evaluate_arr_comp, evaluate_obj_comp},9 compspec::{evaluate_arr_comp, evaluate_obj_comp},10 destructure::evaluate_locals_unbound,10 destructure::evaluate_locals_unbound,11 operator::evaluate_binary_op_special,11 operator::{evaluate_add_op, evaluate_binary_op},12};12};13use crate::{13use crate::{14 CcObjectAssertion, CcUnbound, Context, Error, MaybeUnbound, ObjValue, ObjValueBuilder,14 CcObjectAssertion, CcUnbound, Context, Error, MaybeUnbound, ObjValue, ObjValueBuilder,137 let value = evaluate(ctx, value)?;137 let value = evaluate(ctx, value)?;138 evaluate_unary_op(*op, &value)?138 evaluate_unary_op(*op, &value)?139 }139 }140 LExpr::BinaryOp { lhs, op, rhs } => evaluate_binary_op_special(ctx, lhs, *op, rhs)?,140 LExpr::BinaryOp { lhs, op, rhs } => evaluate_binary_op(ctx, lhs, *op, rhs)?,141 LExpr::LocalExpr(l) => {141 LExpr::LocalExpr(l) => {142 ctx = ctx142 ctx = ctx143 .pack_captures_sup_this(&l.frame_shape)143 .pack_captures_sup_this(&l.frame_shape)202 LExpr::ObjExtend(lhs, body) => {202 LExpr::ObjExtend(lhs, body) => {203 let lhs_val = evaluate(ctx.clone(), lhs)?;203 let lhs_val = evaluate(ctx.clone(), lhs)?;204 let Val::Obj(lhs_obj) = lhs_val else {204 let Val::Obj(lhs_obj) = lhs_val else {205 bail!(TypeMismatch(205 return evaluate_add_op(&lhs_val, &evaluate_obj_body(None, ctx, body)?);206 "object extend lhs",207 vec![ValType::Obj],208 lhs_val.value_type(),209 ))210 };206 };211 evaluate_obj_body(Some(lhs_obj), ctx, body)?207 evaluate_obj_body(Some(lhs_obj), ctx, body)?crates/jrsonnet-evaluator/src/evaluate/operator.rsdiffbeforeafterboth159 })159 })160}160}161162pub fn evaluate_binary_op_special(163 ctx: Context,164 a: &LExpr,165 op: BinaryOpType,166 b: &LExpr,167) -> Result<Val> {168 use BinaryOpType::*;169 use Val::*;170171 Ok(match (evaluate(ctx.clone(), a)?, op, b) {172 (Bool(true), Or, _) => Val::Bool(true),173 (Bool(false), And, _) => Val::Bool(false),174 #[cfg(feature = "exp-null-coaelse")]175 (Null, NullCoaelse, eb) => evaluate(ctx, eb)?,176 #[cfg(feature = "exp-null-coaelse")]177 (a, NullCoaelse, _) => a,178 (a, In, LExpr::Super) => {179 let sup_this = ctx.try_sup_this()?;180 if !sup_this.has_super() {181 return Ok(Val::Bool(false));182 }183 return Ok(Val::Bool(sup_this.field_in_super(a.to_string()?)));184 }185 (a, op, eb) => evaluate_binary_op_normal(&a, op, &evaluate(ctx, eb)?)?,186 })187}188161189pub fn evaluate_compare_op(a: &Val, b: &Val, op: BinaryOpType) -> Result<Ordering> {162pub fn evaluate_compare_op(a: &Val, b: &Val, op: BinaryOpType) -> Result<Ordering> {190 use Val::*;163 use Val::*;216 })189 })217}190}218191192/// Short-circuit operators (`||`, `&&`, `??`) and `in super`193pub fn evaluate_binary_op(ctx: Context, a: &LExpr, op: BinaryOpType, b: &LExpr) -> Result<Val> {194 use BinaryOpType::*;195 use Val::*;196197 Ok(match (evaluate(ctx.clone(), a)?, op, b) {198 (Bool(true), Or, _) => Val::Bool(true),199 (Bool(false), And, _) => Val::Bool(false),200 #[cfg(feature = "exp-null-coaelse")]201 (Null, NullCoaelse, eb) => evaluate(ctx, eb)?,202 #[cfg(feature = "exp-null-coaelse")]203 (a, NullCoaelse, _) => a,204 (a, In, LExpr::Super) => {205 let sup_this = ctx.try_sup_this()?;206 if !sup_this.has_super() {207 return Ok(Val::Bool(false));208 }209 return Ok(Val::Bool(sup_this.field_in_super(a.to_string()?)));210 }211 (a, op, eb) => evaluate_binary_op_eager(&a, op, &evaluate(ctx, eb)?)?,212 })213}214215/// Evaluation of non-short-circuiting binary operators216/// short-circuit operators will be thrown out of here.219pub fn evaluate_binary_op_normal(a: &Val, op: BinaryOpType, b: &Val) -> Result<Val> {217fn evaluate_binary_op_eager(a: &Val, op: BinaryOpType, b: &Val) -> Result<Val> {220 use BinaryOpType::*;218 use BinaryOpType::*;221 use Val::*;219 use Val::*;222 Ok(match (a, op, b) {220 Ok(match (a, op, b) {228 (a, Lte, b) => Bool(evaluate_compare_op(a, b, Lte)?.is_le()),226 (a, Lte, b) => Bool(evaluate_compare_op(a, b, Lte)?.is_le()),229 (a, Gte, b) => Bool(evaluate_compare_op(a, b, Gte)?.is_ge()),227 (a, Gte, b) => Bool(evaluate_compare_op(a, b, Gte)?.is_ge()),230228231 (Str(a), In, Obj(obj)) => Bool(obj.has_field_ex(a.clone().into_flat(), true)),229 (Str(a), In, Obj(obj)) => {230 // standalone super obj should not reach this path, because of short-circuit impl231 Bool(obj.has_field_ex(a.clone().into_flat(), true))232 }232233233 // Bool X Bool234 // Bool X Bool234 (Bool(a), And, Bool(b)) => Bool(*a && *b),235 (Bool(a), And, Bool(b)) => {236 assert!(*a, "a == false would return from short-circuit impl");237 Bool(*b)238 }235 (Bool(a), Or, Bool(b)) => Bool(*a || *b),239 (Bool(a), Or, Bool(b)) => {240 assert!(!a, "a == true would return from short-circuit impl");241 Bool(*b)242 }243244 #[cfg(feature = "exp-null-coaelse")]245 (_, NullCoaelse, _) => panic!("?? should return from short-circuit impl"),236246237 (a, Add, b) => evaluate_add_op(a, b)?,247 (a, Add, b) => evaluate_add_op(a, b)?,238 (a, Sub, b) => evaluate_sub_op(a, b)?,248 (a, Sub, b) => evaluate_sub_op(a, b)?,