git.delta.rocks / jrsonnet / refs/commits / 1b7795b5f1ce

difftreelog

feat destructure in comprehensions

Yaroslav Bolyukin2022-11-09parent: #c3b4574.patch.diff
in: master

3 files changed

modifiedcrates/jrsonnet-evaluator/src/evaluate/mod.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/evaluate/mod.rs
+++ b/crates/jrsonnet-evaluator/src/evaluate/mod.rs
@@ -8,6 +8,7 @@
 };
 use jrsonnet_types::ValType;
 
+use self::destructure::destruct;
 use crate::{
 	destructure::evaluate_dest,
 	error::Error::*,
@@ -63,12 +64,16 @@
 		}
 		Some(CompSpec::ForSpec(ForSpecData(var, expr))) => match evaluate(ctx.clone(), expr)? {
 			Val::Arr(list) => {
-				for item in list.iter() {
-					evaluate_comp(
-						ctx.clone().with_var(var.clone(), item?.clone()),
-						&specs[1..],
-						callback,
-					)?;
+				for item in list.iter_lazy() {
+					let fctx = Pending::new();
+					let mut new_bindings = GcHashMap::new();
+					destruct(var, item, fctx.clone(), &mut new_bindings)?;
+					let ctx = ctx
+						.clone()
+						.extend(new_bindings, None, None, None)
+						.into_future(fctx);
+
+					evaluate_comp(ctx, &specs[1..], callback)?;
 				}
 			}
 			_ => throw!(InComprehensionCanOnlyIterateOverArray),
@@ -78,6 +83,7 @@
 }
 
 trait CloneableUnbound<T>: Unbound<Bound = T> + Clone {}
+impl<V, T> CloneableUnbound<T> for V where V: Unbound<Bound = T> + Clone {}
 
 fn evaluate_object_locals(
 	fctx: Pending<Context>,
@@ -88,7 +94,6 @@
 		fctx: Pending<Context>,
 		locals: Rc<Vec<BindSpec>>,
 	}
-	impl CloneableUnbound<Context> for UnboundLocals {}
 	impl Unbound for UnboundLocals {
 		type Bound = Context;
 
@@ -117,15 +122,20 @@
 	builder: &mut ObjValueBuilder,
 	ctx: Context,
 	uctx: B,
-	member: &FieldMember,
+	field: &FieldMember,
 ) -> Result<()> {
-	match member {
+	let name = evaluate_field_name(ctx.clone(), &field.name)?;
+	let Some(name) = name else {
+		return Ok(());
+	};
+
+	match field {
 		FieldMember {
-			name,
 			plus,
 			params: None,
 			visibility,
 			value,
+			..
 		} => {
 			#[derive(Trace)]
 			struct UnboundValue<B: Trace> {
@@ -143,11 +153,6 @@
 					)?)
 				}
 			}
-
-			let name = evaluate_field_name(ctx.clone(), name)?;
-			let Some(name) = name else {
-				return Ok(());
-			};
 
 			builder
 				.member(name.clone())
@@ -161,7 +166,6 @@
 				}))?;
 		}
 		FieldMember {
-			name,
 			params: Some(params),
 			value,
 			..
@@ -184,10 +188,6 @@
 					))
 				}
 			}
-
-			let Some(name) = evaluate_field_name(ctx.clone(), name)? else {
-				return Ok(());
-			};
 
 			builder
 				.member(name.clone())
@@ -227,9 +227,6 @@
 			Member::Field(field) => {
 				evaluate_field_member(&mut builder, ctx.clone(), uctx.clone(), &field)?
 			}
-			Member::BindStmt(_) => {
-				// Already handled
-			}
 			Member::AssertStmt(stmt) => {
 				#[derive(Trace)]
 				struct ObjectAssert<B: Trace> {
@@ -247,6 +244,9 @@
 					assert: stmt.clone(),
 				}));
 			}
+			Member::BindStmt(_) => {
+				// Already handled
+			}
 		}
 	}
 	let this = builder.build();
modifiedcrates/jrsonnet-parser/src/expr.rsdiffbeforeafterboth
--- a/crates/jrsonnet-parser/src/expr.rs
+++ b/crates/jrsonnet-parser/src/expr.rs
@@ -253,7 +253,7 @@
 #[cfg_attr(feature = "structdump", derive(Codegen))]
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
 #[derive(Debug, PartialEq, Trace)]
-pub struct ForSpecData(pub IStr, pub LocExpr);
+pub struct ForSpecData(pub Destruct, pub LocExpr);
 
 #[cfg_attr(feature = "structdump", derive(Codegen))]
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
modifiedcrates/jrsonnet-parser/src/lib.rsdiffbeforeafterboth
208 pub rule ifspec(s: &ParserSettings) -> IfSpecData208 pub rule ifspec(s: &ParserSettings) -> IfSpecData
209 = keyword("if") _ expr:expr(s) {IfSpecData(expr)}209 = keyword("if") _ expr:expr(s) {IfSpecData(expr)}
210 pub rule forspec(s: &ParserSettings) -> ForSpecData210 pub rule forspec(s: &ParserSettings) -> ForSpecData
211 = keyword("for") _ id:id() _ keyword("in") _ cond:expr(s) {ForSpecData(id, cond)}211 = keyword("for") _ id:destruct(s) _ keyword("in") _ cond:expr(s) {ForSpecData(id, cond)}
212 pub rule compspec(s: &ParserSettings) -> Vec<expr::CompSpec>212 pub rule compspec(s: &ParserSettings) -> Vec<expr::CompSpec>
213 = s:(i:ifspec(s) { expr::CompSpec::IfSpec(i) } / f:forspec(s) {expr::CompSpec::ForSpec(f)} ) ** _ {s}213 = s:(i:ifspec(s) { expr::CompSpec::IfSpec(i) } / f:forspec(s) {expr::CompSpec::ForSpec(f)} ) ** _ {s}
214 pub rule local_expr(s: &ParserSettings) -> Expr214 pub rule local_expr(s: &ParserSettings) -> Expr
620 16620 16
621 ),621 ),
622 vec![CompSpec::ForSpec(ForSpecData(622 vec![CompSpec::ForSpec(ForSpecData(
623 "x".into(),623 Destruct::Full("x".into()),
624 el!(Var("arr".into()), 26, 29)624 el!(Var("arr".into()), 26, 29)
625 ))]625 ))]
626 ),626 ),