--- a/crates/jrsonnet-evaluator/src/evaluate/mod.rs +++ b/crates/jrsonnet-evaluator/src/evaluate/mod.rs @@ -149,11 +149,13 @@ } #[cfg(feature = "exp-object-iteration")] Val::Obj(obj) => { - for field in obj.fields( + let fields = obj.fields( // TODO: Should there be ability to preserve iteration order? #[cfg(feature = "exp-preserve-order")] false, - ) { + ); + guaranteed_reserve = guaranteed_reserve.max(1) * fields.len(); + for field in fields { let fctx = Pending::new(); let mut new_bindings = FxHashMap::with_capacity(into.binds_len()); let obj = obj.clone(); @@ -176,6 +178,36 @@ Ok(()) } +fn evaluate_arr_comp(ctx: Context, expr: &Rc, comp_specs: &[CompSpec]) -> Result { + 'eager: { + let mut out = Vec::new(); + + if evaluate_comp(ctx.clone(), comp_specs, 0, &mut |ctx, reserve| { + if reserve != 0 { + out.reserve(reserve); + } + out.push(evaluate(ctx, expr)?); + Ok(()) + }) + .is_err() + { + break 'eager; + } + + return Ok(ArrValue::new(out)); + }; + let mut out = Vec::new(); + evaluate_comp(ctx, comp_specs, 0, &mut |ctx, reserve| { + if reserve != 0 { + out.reserve(reserve); + } + let expr = expr.clone(); + out.push(Thunk!(move || evaluate(ctx, &expr))); + Ok(()) + })?; + Ok(ArrValue::new(out)) +} + trait CloneableUnbound: Unbound + Clone {} impl CloneableUnbound for V where V: Unbound + Clone {} @@ -646,18 +678,7 @@ Val::Arr(ArrValue::expr(ctx, items.clone())) } } - ArrComp(expr, comp_specs) => { - let mut out = Vec::new(); - evaluate_comp(ctx, comp_specs, 0, &mut |ctx, reserve| { - if reserve != 0 { - out.reserve(reserve); - } - let expr = expr.clone(); - out.push(Thunk!(move || evaluate(ctx, &expr))); - Ok(()) - })?; - Val::arr(out) - } + ArrComp(expr, comp_specs) => Val::Arr(evaluate_arr_comp(ctx, expr, comp_specs)?), Obj(body) => Val::Obj(evaluate_object(None, ctx, body)?), ObjExtend(a, b) => { let base = evaluate(ctx.clone(), a)?;