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
1414
15 UndefinedExternalVariable(String),15 UndefinedExternalVariable(String),
16
17 FieldMustBeStringGot(ValType),
1618
17 RuntimeError(String),19 RuntimeError(String),
18 StackOverflow,20 StackOverflow,
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
492 );492 );
493 }493 }
494
495 #[test]
496 fn object_comp() {
497 assert_json!(
498 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}"#,
499 "{\"h1_2\": \"0a\",\"h1_3\": \"0a\",\"h1_4\": \"0a\",\"h2_3\": \"a1\",\"h2_4\": \"a1\",\"h3_2\": \"0a\",\"h3_4\": \"a1\"}"
500 )
501 }
494502
495 #[test]503 #[test]
496 fn direct_self() {504 fn direct_self() {
modifiedcrates/jsonnet-parser/src/expr.rsdiffbeforeafterboth
120 key: LocExpr,120 key: LocExpr,
121 value: LocExpr,121 value: LocExpr,
122 post_locals: Vec<BindSpec>,122 post_locals: Vec<BindSpec>,
123 rest: Vec<CompSpec>,123 compspecs: Vec<CompSpec>,
124 },124 },
125}125}
126126
modifiedcrates/jsonnet-parser/src/lib.rsdiffbeforeafterboth
138 key,138 key,
139 value,139 value,
140 post_locals,140 post_locals,
141 rest: [vec![CompSpec::ForSpec(forspec)], others.unwrap_or_default()].concat(),141 compspecs: [vec![CompSpec::ForSpec(forspec)], others.unwrap_or_default()].concat(),
142 }142 }
143 }143 }
144 / members:(member(s) ** comma()) comma()? {expr::ObjBody::MemberList(members)}144 / members:(member(s) ** comma()) comma()? {expr::ObjBody::MemberList(members)}