git.delta.rocks / jrsonnet / refs/commits / 9f3d17001fc1

difftreelog

feat obj comp support

Лач2020-06-11parent: #abdb122.patch.diff
in: master

5 files changed

modifiedcrates/jsonnet-evaluator/src/error.rsdiffbeforeafterboth
--- a/crates/jsonnet-evaluator/src/error.rs
+++ b/crates/jsonnet-evaluator/src/error.rs
@@ -14,6 +14,8 @@
 
 	UndefinedExternalVariable(String),
 
+	FieldMustBeStringGot(ValType),
+
 	RuntimeError(String),
 	StackOverflow,
 	FractionalIndex,
modifiedcrates/jsonnet-evaluator/src/evaluate.rsdiffbeforeafterboth
1use crate::{1use crate::{
2 context_creator, create_error, future_wrapper, lazy_val, push, with_state, Context,2 context_creator, create_error, future_wrapper, lazy_val, push, with_state, Context,
3 ContextCreator, FuncDesc, LazyBinding, LazyVal, ObjMember, ObjValue, Result, Val,3 ContextCreator, Error, FuncDesc, LazyBinding, LazyVal, ObjMember, ObjValue, Result, Val,
4};4};
5use closure::closure;5use closure::closure;
6use jsonnet_parser::{6use jsonnet_parser::{
167future_wrapper!(HashMap<String, LazyBinding>, FutureNewBindings);167future_wrapper!(HashMap<String, LazyBinding>, FutureNewBindings);
168future_wrapper!(ObjValue, FutureObjValue);168future_wrapper!(ObjValue, FutureObjValue);
169169
170#[inline(always)]
170pub fn evaluate_comp(171pub fn evaluate_comp<T>(
171 context: Context,172 context: Context,
172 value: &LocExpr,173 value: &impl Fn(Context) -> Result<T>,
173 specs: &[CompSpec],174 specs: &[CompSpec],
174) -> Result<Option<Vec<Val>>> {175) -> Result<Option<Vec<T>>> {
175 Ok(match specs.get(0) {176 Ok(match specs.get(0) {
176 None => Some(vec![evaluate(context, &value)?]),177 None => Some(vec![value(context)?]),
177 Some(CompSpec::IfSpec(IfSpecData(cond))) => {178 Some(CompSpec::IfSpec(IfSpecData(cond))) => {
178 if evaluate(context.clone(), &cond)?.try_cast_bool("if spec")? {179 if evaluate(context.clone(), &cond)?.try_cast_bool("if spec")? {
179 evaluate_comp(context, value, &specs[1..])?180 evaluate_comp(context, value, &specs[1..])?
193 &specs[1..],194 &specs[1..],
194 )?);195 )?);
195 }196 }
196 Some(out.iter().flatten().flatten().cloned().collect())197 Some(out.into_iter().flatten().flatten().collect())
197 }198 }
198 _ => panic!("for expression evaluated to non-iterable value"),199 _ => panic!("for expression evaluated to non-iterable value"),
199 }200 }
208 let new_bindings = FutureNewBindings::new();209 let new_bindings = FutureNewBindings::new();
209 let future_this = FutureObjValue::new();210 let future_this = FutureObjValue::new();
210 let context_creator = context_creator!(211 let context_creator = context_creator!(
211 closure!(clone context, clone new_bindings, clone future_this, |this: Option<ObjValue>, super_obj: Option<ObjValue>| {212 closure!(clone context, clone new_bindings, |this: Option<ObjValue>, super_obj: Option<ObjValue>| {
212 Ok(context.clone().extend_unbound(213 Ok(context.clone().extend_unbound(
213 new_bindings.clone().unwrap(),214 new_bindings.clone().unwrap(),
214 context.clone().dollar().clone().or_else(||this.clone()),215 context.clone().dollar().clone().or_else(||this.clone()),
301 }302 }
302 future_this.fill(ObjValue::new(None, Rc::new(new_members)))303 future_this.fill(ObjValue::new(None, Rc::new(new_members)))
303 }304 }
305 ObjBody::ObjComp {
306 pre_locals,
307 key,
308 value,
309 post_locals,
310 compspecs,
304 _ => todo!(),311 } => {
312 let future_this = FutureObjValue::new();
313 let mut new_members = BTreeMap::new();
314 for (k, v) in evaluate_comp(
315 context.clone(),
316 &|ctx| {
317 let new_bindings = FutureNewBindings::new();
318 let context_creator = context_creator!(
319 closure!(clone context, clone new_bindings, |this: Option<ObjValue>, super_obj: Option<ObjValue>| {
320 Ok(context.clone().extend_unbound(
321 new_bindings.clone().unwrap(),
322 context.clone().dollar().clone().or_else(||this.clone()),
323 None,
324 super_obj
325 )?)
326 })
327 );
328 let mut bindings: HashMap<String, LazyBinding> = HashMap::new();
329 for (n, b) in pre_locals
330 .iter()
331 .chain(post_locals.iter())
332 .map(|b| evaluate_binding(b, context_creator.clone()))
333 {
334 bindings.insert(n, b);
335 }
336 let bindings = new_bindings.fill(bindings);
337 let ctx = ctx.extend_unbound(bindings, None, None, None)?;
338 let key = evaluate(ctx.clone(), &key)?;
339 let value = LazyBinding::Bindable(Rc::new(
340 closure!(clone ctx, clone value, |this, _super_obj| {
341 Ok(LazyVal::new_resolved(evaluate(ctx.extend(HashMap::new(), None, this, None)?, &value)?))
342 }),
343 ));
344
345 Ok((key, value))
346 },
347 &compspecs,
348 )?
349 .unwrap()
350 {
351 match k {
352 Val::Null => {}
353 Val::Str(n) => {
354 new_members.insert(
355 n,
356 ObjMember {
357 add: false,
358 visibility: Visibility::Normal,
359 invoke: v,
360 },
361 );
362 }
363 v => create_error(Error::FieldMustBeStringGot(v.value_type()?))?,
364 }
365 }
366
367 future_this.fill(ObjValue::new(None, Rc::new(new_members)))
368 }
305 })369 })
306}370}
307371
405 }469 }
406 ArrComp(expr, compspecs) => Val::Arr(470 ArrComp(expr, compspecs) => Val::Arr(
407 // First compspec should be forspec, so no "None" possible here471 // First compspec should be forspec, so no "None" possible here
408 evaluate_comp(context, expr, compspecs)?.unwrap(),472 evaluate_comp(context, &|ctx| evaluate(ctx, expr), compspecs)?.unwrap(),
409 ),473 ),
410 Obj(body) => Val::Obj(evaluate_object(context, body.clone())?),474 Obj(body) => Val::Obj(evaluate_object(context, body.clone())?),
411 ObjExtend(s, t) => evaluate_add_op(475 ObjExtend(s, t) => evaluate_add_op(
modifiedcrates/jsonnet-evaluator/src/lib.rsdiffbeforeafterboth
--- a/crates/jsonnet-evaluator/src/lib.rs
+++ b/crates/jsonnet-evaluator/src/lib.rs
@@ -493,6 +493,14 @@
 	}
 
 	#[test]
+	fn object_comp() {
+		assert_json!(
+			r#"{local t = "a", ["h"+i+"_"+z]: if "h"+(i-1)+"_"+z in self then t+1 else 0+t for i in [1,2,3] for z in [2,3,4] if z != i}"#,
+			"{\"h1_2\": \"0a\",\"h1_3\": \"0a\",\"h1_4\": \"0a\",\"h2_3\": \"a1\",\"h2_4\": \"a1\",\"h3_2\": \"0a\",\"h3_4\": \"a1\"}"
+		)
+	}
+
+	#[test]
 	fn direct_self() {
 		println!(
 			"{:#?}",
modifiedcrates/jsonnet-parser/src/expr.rsdiffbeforeafterboth
--- a/crates/jsonnet-parser/src/expr.rs
+++ b/crates/jsonnet-parser/src/expr.rs
@@ -120,7 +120,7 @@
 		key: LocExpr,
 		value: LocExpr,
 		post_locals: Vec<BindSpec>,
-		rest: Vec<CompSpec>,
+		compspecs: Vec<CompSpec>,
 	},
 }
 
modifiedcrates/jsonnet-parser/src/lib.rsdiffbeforeafterboth
--- a/crates/jsonnet-parser/src/lib.rs
+++ b/crates/jsonnet-parser/src/lib.rs
@@ -138,7 +138,7 @@
 					key,
 					value,
 					post_locals,
-					rest: [vec![CompSpec::ForSpec(forspec)], others.unwrap_or_default()].concat(),
+					compspecs: [vec![CompSpec::ForSpec(forspec)], others.unwrap_or_default()].concat(),
 				}
 			}
 			/ members:(member(s) ** comma()) comma()? {expr::ObjBody::MemberList(members)}