difftreelog
fix destructure
in: master
4 files changed
crates/jrsonnet-evaluator/src/evaluate/destructure.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/evaluate/destructure.rs
+++ b/crates/jrsonnet-evaluator/src/evaluate/destructure.rs
@@ -142,7 +142,7 @@
Ok(field)
} else {
let (fctx, expr) = default.as_ref().expect("shape is checked");
- Ok(evaluate(fctx.clone().unwrap(), expr)?)
+ Ok(crate::evaluate(fctx.clone().unwrap(), expr)?)
}
})
};
crates/jrsonnet-evaluator/src/evaluate/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/evaluate/mod.rs
+++ b/crates/jrsonnet-evaluator/src/evaluate/mod.rs
@@ -142,7 +142,7 @@
false,
) {
let fctx = Pending::new();
- let mut new_bindings = FxHashMap::with_capacity(var.binds_len());
+ let mut new_bindings = FxHashMap::with_capacity(into.binds_len());
let obj = obj.clone();
let value = Thunk::evaluated(Val::Arr(ArrValue::lazy(vec![
Thunk::evaluated(Val::string(field.clone())),
@@ -150,7 +150,7 @@
"field exists, as field name was obtained from object.fields()",
)),
])));
- destruct(var, value, fctx.clone(), &mut new_bindings)?;
+ destruct(into, value, fctx.clone(), &mut new_bindings)?;
let ctx = ctx.clone().extend_bindings(new_bindings).into_future(fctx);
evaluate_comp(ctx, &specs[1..], callback)?;
crates/jrsonnet-ir-parser/Cargo.tomldiffbeforeafterboth1[package]2name = "jrsonnet-ir-parser"3authors.workspace = true4edition.workspace = true5license.workspace = true6repository.workspace = true7version.workspace = true89[features]10exp-null-coaelse = ["jrsonnet-ir/exp-null-coaelse"]1112[dependencies]13insta.workspace = true14jrsonnet-gcmodule.workspace = true15jrsonnet-ir.workspace = true16jrsonnet-lexer = { version = "0.5.0-pre97", path = "../jrsonnet-lexer" }1718[lints]19workspace = true1[package]2name = "jrsonnet-ir-parser"3authors.workspace = true4edition.workspace = true5license.workspace = true6repository.workspace = true7version.workspace = true89[features]10exp-null-coaelse = ["jrsonnet-ir/exp-null-coaelse"]11exp-destruct = ["jrsonnet-ir/exp-destruct"]1213[dependencies]14insta.workspace = true15jrsonnet-gcmodule.workspace = true16jrsonnet-ir.workspace = true17jrsonnet-lexer = { version = "0.5.0-pre97", path = "../jrsonnet-lexer" }1819[lints]20workspace = truecrates/jrsonnet-ir-parser/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-ir-parser/src/lib.rs
+++ b/crates/jrsonnet-ir-parser/src/lib.rs
@@ -3,9 +3,9 @@
use jrsonnet_gcmodule::Acyclic;
use jrsonnet_ir::{
unescape, ArgsDesc, AssertExpr, AssertStmt, BinaryOp, BinaryOpType, BindSpec, CompSpec,
- Destruct, Expr, ExprParam, ExprParams, FieldMember, FieldName, ForSpecData, IStr, IfElse,
- IfSpecData, ImportKind, IndexPart, LiteralType, Member, ObjBody, ObjComp, ObjMembers, Slice,
- SliceDesc, Source, Span, Spanned, UnaryOpType, Visibility,
+ Destruct, DestructRest, Expr, ExprParam, ExprParams, FieldMember, FieldName, ForSpecData, IStr,
+ IfElse, IfSpecData, ImportKind, IndexPart, LiteralType, Member, ObjBody, ObjComp, ObjMembers,
+ Slice, SliceDesc, Source, Span, Spanned, UnaryOpType, Visibility,
};
use jrsonnet_lexer::{collect_lexed_str_block, Lexeme, Lexer, SyntaxKind, T};
@@ -316,7 +316,114 @@
}
fn destruct(p: &mut Parser<'_>) -> R<Destruct> {
- Ok(Destruct::Full(p.expect_ident()?))
+ if p.at_ident() {
+ return Ok(Destruct::Full(p.expect_ident()?));
+ }
+ #[cfg(not(feature = "exp-destruct"))]
+ return Err(p.error(format!(
+ "expected identifier, got {}",
+ p.current_desc()
+ )));
+ #[cfg(feature = "exp-destruct")]
+ {
+ if p.try_eat(T![?]) {
+ return Ok(Destruct::Skip);
+ }
+ if p.at(T!['[']) {
+ return destruct_array(p);
+ }
+ if p.at(T!['{']) {
+ return destruct_object(p);
+ }
+ Err(p.error(format!(
+ "expected destructure pattern, got {}",
+ p.current_desc()
+ )))
+ }
+}
+
+#[cfg(feature = "exp-destruct")]
+fn destruct_rest(p: &mut Parser<'_>) -> R<DestructRest> {
+ p.eat(T![...])?;
+ if p.at_ident() {
+ Ok(DestructRest::Keep(p.expect_ident()?))
+ } else {
+ Ok(DestructRest::Drop)
+ }
+}
+
+#[cfg(feature = "exp-destruct")]
+fn destruct_array(p: &mut Parser<'_>) -> R<Destruct> {
+ p.eat(T!['['])?;
+ let mut start = Vec::new();
+ let mut rest = None;
+ let mut end = Vec::new();
+ if !p.at(T![']']) {
+ loop {
+ if p.at(T![...]) {
+ rest = Some(destruct_rest(p)?);
+ if p.try_eat(T![,]) {
+ if !p.at(T![']']) {
+ loop {
+ end.push(destruct(p)?);
+ if !p.try_eat(T![,]) {
+ break;
+ }
+ if p.at(T![']']) {
+ break;
+ }
+ }
+ }
+ }
+ break;
+ }
+ start.push(destruct(p)?);
+ if !p.try_eat(T![,]) {
+ break;
+ }
+ if p.at(T![']']) {
+ break;
+ }
+ }
+ }
+ p.eat(T![']'])?;
+ Ok(Destruct::Array { start, rest, end })
+}
+
+#[cfg(feature = "exp-destruct")]
+fn destruct_object(p: &mut Parser<'_>) -> R<Destruct> {
+ p.eat(T!['{'])?;
+ let mut fields = Vec::new();
+ let mut rest = None;
+ if !p.at(T!['}']) {
+ loop {
+ if p.at(T![...]) {
+ rest = Some(destruct_rest(p)?);
+ p.try_eat(T![,]);
+ break;
+ }
+ let name = p.expect_ident()?;
+ let into = if p.try_eat(T![:]) {
+ Some(destruct(p)?)
+ } else {
+ None
+ };
+ let default = if p.try_eat(T![=]) {
+ Some(Rc::new(spanned(p, expr)?))
+ } else {
+ None
+ };
+ fields.push((name, into, default));
+ if !p.try_eat(T![,]) {
+ break;
+ }
+ if p.at(T!['}']) {
+ break;
+ }
+ }
+ }
+ p.eat(T!['}'])?;
+ Ok(Destruct::Object { fields, rest })
}
fn params(p: &mut Parser<'_>) -> R<ExprParams> {
@@ -383,6 +490,15 @@
}
fn bind(p: &mut Parser<'_>) -> R<BindSpec> {
+ #[cfg(feature = "exp-destruct")]
+ {
+ if !p.at_ident() {
+ let d = destruct(p)?;
+ p.eat(T![=])?;
+ let value = Rc::new(expr(p)?);
+ return Ok(BindSpec::Field { into: d, value });
+ }
+ }
let name = p.expect_ident()?;
if p.try_eat(T!['(']) {
let ps = params(p)?;