git.delta.rocks / jrsonnet / refs/commits / b6f9e8309dbc

difftreelog

fix destructure

mzvklmvoYaroslav Bolyukin2026-03-23parent: #a34df9d.patch.diff
in: master

4 files changed

modifiedcrates/jrsonnet-evaluator/src/evaluate/destructure.rsdiffbeforeafterboth
142 Ok(field)142 Ok(field)
143 } else {143 } else {
144 let (fctx, expr) = default.as_ref().expect("shape is checked");144 let (fctx, expr) = default.as_ref().expect("shape is checked");
145 Ok(evaluate(fctx.clone().unwrap(), expr)?)145 Ok(crate::evaluate(fctx.clone().unwrap(), expr)?)
146 }146 }
147 })147 })
148 };148 };
modifiedcrates/jrsonnet-evaluator/src/evaluate/mod.rsdiffbeforeafterboth
142 false,142 false,
143 ) {143 ) {
144 let fctx = Pending::new();144 let fctx = Pending::new();
145 let mut new_bindings = FxHashMap::with_capacity(var.binds_len());145 let mut new_bindings = FxHashMap::with_capacity(into.binds_len());
146 let obj = obj.clone();146 let obj = obj.clone();
147 let value = Thunk::evaluated(Val::Arr(ArrValue::lazy(vec![147 let value = Thunk::evaluated(Val::Arr(ArrValue::lazy(vec![
148 Thunk::evaluated(Val::string(field.clone())),148 Thunk::evaluated(Val::string(field.clone())),
149 Thunk!(move || obj.get(field).transpose().expect(149 Thunk!(move || obj.get(field).transpose().expect(
150 "field exists, as field name was obtained from object.fields()",150 "field exists, as field name was obtained from object.fields()",
151 )),151 )),
152 ])));152 ])));
153 destruct(var, value, fctx.clone(), &mut new_bindings)?;153 destruct(into, value, fctx.clone(), &mut new_bindings)?;
154 let ctx = ctx.clone().extend_bindings(new_bindings).into_future(fctx);154 let ctx = ctx.clone().extend_bindings(new_bindings).into_future(fctx);
155155
156 evaluate_comp(ctx, &specs[1..], callback)?;156 evaluate_comp(ctx, &specs[1..], callback)?;
modifiedcrates/jrsonnet-ir-parser/Cargo.tomldiffbeforeafterboth
88
9[features]9[features]
10exp-null-coaelse = ["jrsonnet-ir/exp-null-coaelse"]10exp-null-coaelse = ["jrsonnet-ir/exp-null-coaelse"]
11exp-destruct = ["jrsonnet-ir/exp-destruct"]
1112
12[dependencies]13[dependencies]
13insta.workspace = true14insta.workspace = true
modifiedcrates/jrsonnet-ir-parser/src/lib.rsdiffbeforeafterboth
3use jrsonnet_gcmodule::Acyclic;3use jrsonnet_gcmodule::Acyclic;
4use jrsonnet_ir::{4use jrsonnet_ir::{
5 unescape, ArgsDesc, AssertExpr, AssertStmt, BinaryOp, BinaryOpType, BindSpec, CompSpec,5 unescape, ArgsDesc, AssertExpr, AssertStmt, BinaryOp, BinaryOpType, BindSpec, CompSpec,
6 Destruct, Expr, ExprParam, ExprParams, FieldMember, FieldName, ForSpecData, IStr, IfElse,6 Destruct, DestructRest, Expr, ExprParam, ExprParams, FieldMember, FieldName, ForSpecData, IStr,
7 IfSpecData, ImportKind, IndexPart, LiteralType, Member, ObjBody, ObjComp, ObjMembers, Slice,7 IfElse, IfSpecData, ImportKind, IndexPart, LiteralType, Member, ObjBody, ObjComp, ObjMembers,
8 SliceDesc, Source, Span, Spanned, UnaryOpType, Visibility,8 Slice, SliceDesc, Source, Span, Spanned, UnaryOpType, Visibility,
9};9};
10use jrsonnet_lexer::{collect_lexed_str_block, Lexeme, Lexer, SyntaxKind, T};10use jrsonnet_lexer::{collect_lexed_str_block, Lexeme, Lexer, SyntaxKind, T};
1111
316}316}
317317
318fn destruct(p: &mut Parser<'_>) -> R<Destruct> {318fn destruct(p: &mut Parser<'_>) -> R<Destruct> {
319 Ok(Destruct::Full(p.expect_ident()?))319 if p.at_ident() {
320 return Ok(Destruct::Full(p.expect_ident()?));
321 }
322 #[cfg(not(feature = "exp-destruct"))]
323 return Err(p.error(format!(
324 "expected identifier, got {}",
325 p.current_desc()
326 )));
327 #[cfg(feature = "exp-destruct")]
328 {
329 if p.try_eat(T![?]) {
330 return Ok(Destruct::Skip);
331 }
332 if p.at(T!['[']) {
333 return destruct_array(p);
334 }
335 if p.at(T!['{']) {
336 return destruct_object(p);
337 }
338 Err(p.error(format!(
339 "expected destructure pattern, got {}",
340 p.current_desc()
341 )))
342 }
320}343}
321344
345#[cfg(feature = "exp-destruct")]
346fn destruct_rest(p: &mut Parser<'_>) -> R<DestructRest> {
347 p.eat(T![...])?;
348 if p.at_ident() {
349 Ok(DestructRest::Keep(p.expect_ident()?))
350 } else {
351 Ok(DestructRest::Drop)
352 }
353}
354
355#[cfg(feature = "exp-destruct")]
356fn destruct_array(p: &mut Parser<'_>) -> R<Destruct> {
357 p.eat(T!['['])?;
358 let mut start = Vec::new();
359 let mut rest = None;
360 let mut end = Vec::new();
361 if !p.at(T![']']) {
362 loop {
363 if p.at(T![...]) {
364 rest = Some(destruct_rest(p)?);
365 if p.try_eat(T![,]) {
366 if !p.at(T![']']) {
367 loop {
368 end.push(destruct(p)?);
369 if !p.try_eat(T![,]) {
370 break;
371 }
372 if p.at(T![']']) {
373 break;
374 }
375 }
376 }
377 }
378 break;
379 }
380 start.push(destruct(p)?);
381 if !p.try_eat(T![,]) {
382 break;
383 }
384 if p.at(T![']']) {
385 break;
386 }
387 }
388 }
389 p.eat(T![']'])?;
390 Ok(Destruct::Array { start, rest, end })
391}
392
393#[cfg(feature = "exp-destruct")]
394fn destruct_object(p: &mut Parser<'_>) -> R<Destruct> {
395 p.eat(T!['{'])?;
396 let mut fields = Vec::new();
397 let mut rest = None;
398 if !p.at(T!['}']) {
399 loop {
400 if p.at(T![...]) {
401 rest = Some(destruct_rest(p)?);
402 p.try_eat(T![,]);
403 break;
404 }
405 let name = p.expect_ident()?;
406 let into = if p.try_eat(T![:]) {
407 Some(destruct(p)?)
408 } else {
409 None
410 };
411 let default = if p.try_eat(T![=]) {
412 Some(Rc::new(spanned(p, expr)?))
413 } else {
414 None
415 };
416 fields.push((name, into, default));
417 if !p.try_eat(T![,]) {
418 break;
419 }
420 if p.at(T!['}']) {
421 break;
422 }
423 }
424 }
425 p.eat(T!['}'])?;
426 Ok(Destruct::Object { fields, rest })
427}
428
322fn params(p: &mut Parser<'_>) -> R<ExprParams> {429fn params(p: &mut Parser<'_>) -> R<ExprParams> {
323 if p.at(T![')']) {430 if p.at(T![')']) {
383}490}
384491
385fn bind(p: &mut Parser<'_>) -> R<BindSpec> {492fn bind(p: &mut Parser<'_>) -> R<BindSpec> {
493 #[cfg(feature = "exp-destruct")]
494 {
495 if !p.at_ident() {
496 let d = destruct(p)?;
497 p.eat(T![=])?;
498 let value = Rc::new(expr(p)?);
499 return Ok(BindSpec::Field { into: d, value });
500 }
501 }
386 let name = p.expect_ident()?;502 let name = p.expect_ident()?;
387 if p.try_eat(T!['(']) {503 if p.try_eat(T!['(']) {
388 let ps = params(p)?;504 let ps = params(p)?;