difftreelog
feat object destructuring defaults
in: master
5 files changed
crates/jrsonnet-evaluator/src/dynamic.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/dynamic.rs
+++ b/crates/jrsonnet-evaluator/src/dynamic.rs
@@ -8,6 +8,9 @@
pub fn new() -> Self {
Self(Cc::new(RefCell::new(None)))
}
+ pub fn new_filled(v: T) -> Self {
+ Self(Cc::new(RefCell::new(Some(v))))
+ }
/// # Panics
/// If wrapper is filled already
pub fn fill(self, value: T) {
crates/jrsonnet-evaluator/src/evaluate/destructure.rsdiffbeforeafterboth12};12};131314#[allow(clippy::too_many_lines)]14#[allow(clippy::too_many_lines)]15#[allow(unused_variables)]15pub fn destruct(16pub fn destruct(16 d: &Destruct,17 d: &Destruct,17 parent: Thunk<Val>,18 parent: Thunk<Val>,19 fctx: Pending<Context>,18 new_bindings: &mut GcHashMap<IStr, Thunk<Val>>,20 new_bindings: &mut GcHashMap<IStr, Thunk<Val>>,19) -> Result<()> {21) -> Result<()> {20 match d {22 match d {89 full: full.clone(),91 full: full.clone(),90 index: i,92 index: i,91 })),93 })),94 fctx.clone(),92 new_bindings,95 new_bindings,93 )?;96 )?;94 }97 }119 start: start.len(),122 start: start.len(),120 end: end.len(),123 end: end.len(),121 })),124 })),125 fctx.clone(),122 new_bindings,126 new_bindings,123 )?;127 )?;124 }128 }151 index: i,155 index: i,152 end: end.len(),156 end: end.len(),153 })),157 })),158 fctx.clone(),154 new_bindings,159 new_bindings,155 )?;160 )?;156 }161 }191 }196 }192 let field_names: Vec<_> = fields.iter().map(|f| f.0.clone()).collect();197 let field_names: Vec<_> = fields198 .iter()199 .filter(|f| f.2.is_none())200 .map(|f| f.0.clone())201 .collect();193 let full = Thunk::new(tb!(DataThunk {202 let full = Thunk::new(tb!(DataThunk {196 has_rest: rest.is_some()205 has_rest: rest.is_some()197 }));206 }));198207199 for (field, d) in fields {208 for (field, d, default) in fields {200 #[derive(Trace)]209 #[derive(Trace)]201 struct FieldThunk {210 struct FieldThunk {202 full: Thunk<ObjValue>,211 full: Thunk<ObjValue>,203 field: IStr,212 field: IStr,213 default: Option<(Pending<Context>, LocExpr)>,204 }214 }205 impl ThunkValue for FieldThunk {215 impl ThunkValue for FieldThunk {206 type Output = Val;216 type Output = Val;207217208 fn get(self: Box<Self>, s: State) -> Result<Self::Output> {218 fn get(self: Box<Self>, s: State) -> Result<Self::Output> {209 let full = self.full.evaluate(s.clone())?;219 let full = self.full.evaluate(s.clone())?;210 let field = full.get(s, self.field)?.expect("shape is checked");220 if let Some(field) = full.get(s.clone(), self.field)? {211 Ok(field)221 Ok(field)222 } else {223 let (fctx, expr) = self.default.as_ref().expect("shape is checked");224 Ok(evaluate(s, fctx.clone().unwrap(), &expr)?)225 }212 }226 }213 }227 }214 let value = Thunk::new(tb!(FieldThunk {228 let value = Thunk::new(tb!(FieldThunk {215 full: full.clone(),229 full: full.clone(),216 field: field.clone()230 field: field.clone(),231 default: default.clone().map(|e| (fctx.clone(), e)),217 }));232 }));218 if let Some(d) = d {233 if let Some(d) = d {219 destruct(d, value, new_bindings)?;234 destruct(d, value, fctx.clone(), new_bindings)?;220 } else {235 } else {221 destruct(&Destruct::Full(field.clone()), value, new_bindings)?;236 destruct(237 &Destruct::Full(field.clone()),238 value,239 fctx.clone(),240 new_bindings,241 )?;222 }242 }223 }243 }251 }271 }252 let data = Thunk::new(tb!(EvaluateThunkValue {272 let data = Thunk::new(tb!(EvaluateThunkValue {253 name: into.name(),273 name: into.name(),254 fctx,274 fctx: fctx.clone(),255 expr: value.clone(),275 expr: value.clone(),256 }));276 }));257 destruct(into, data, new_bindings)?;277 destruct(into, data, fctx, new_bindings)?;258 }278 }259 BindSpec::Function {279 BindSpec::Function {260 name,280 name,crates/jrsonnet-evaluator/src/function/parse.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/function/parse.rs
+++ b/crates/jrsonnet-evaluator/src/function/parse.rs
@@ -56,7 +56,12 @@
args.unnamed_iter(s.clone(), ctx.clone(), tailstrict, &mut |id, arg| {
let name = params[id].0.clone();
- destruct(&name, arg, &mut passed_args)?;
+ destruct(
+ &name,
+ arg,
+ Pending::new_filled(ctx.clone()),
+ &mut passed_args,
+ )?;
filled_positionals += 1;
Ok(())
})?;
@@ -96,6 +101,7 @@
name: param.0.name().unwrap_or_else(|| "<destruct>".into()),
value: param.1.clone().expect("default exists"),
})),
+ fctx.clone(),
&mut defaults,
)?;
if param.0.name().is_some() {
@@ -230,6 +236,7 @@
name: param.0.name().unwrap_or_else(|| "<destruct>".into()),
value: v.clone(),
})),
+ fctx.clone(),
&mut bindings,
)?;
} else {
@@ -238,6 +245,7 @@
Thunk::new(tb!(DependsOnUnbound(
param.0.name().unwrap_or_else(|| "<destruct>".into())
))),
+ fctx.clone(),
&mut bindings,
)?;
}
crates/jrsonnet-parser/src/expr.rsdiffbeforeafterboth--- a/crates/jrsonnet-parser/src/expr.rs
+++ b/crates/jrsonnet-parser/src/expr.rs
@@ -188,7 +188,7 @@
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
-#[derive(Debug, Clone, PartialEq, Eq, Trace)]
+#[derive(Debug, Clone, PartialEq, Trace)]
pub enum Destruct {
Full(IStr),
#[cfg(feature = "exp-destruct")]
@@ -201,7 +201,7 @@
},
#[cfg(feature = "exp-destruct")]
Object {
- fields: Vec<(IStr, Option<Destruct>)>,
+ fields: Vec<(IStr, Option<Destruct>, Option<LocExpr>)>,
rest: Option<DestructRest>,
},
}
crates/jrsonnet-parser/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-parser/src/lib.rs
+++ b/crates/jrsonnet-parser/src/lib.rs
@@ -1,4 +1,4 @@
-#![allow(clippy::redundant_closure_call)]
+#![allow(clippy::redundant_closure_call, clippy::derive_partial_eq_without_eq)]
use std::rc::Rc;
@@ -109,7 +109,7 @@
}
pub rule destruct_object(s: &ParserSettings) -> expr::Destruct
= "{" _
- fields:(name:id() _ into:(":" _ into:destruct(s) {into})? {(name, into)})**comma()
+ fields:(name:id() into:(_ ":" _ into:destruct(s) {into})? default:(_ "=" _ v:expr(s) {v})? {(name, into, default)})**comma()
rest:(
comma() rest:destruct_rest()? {rest}
/ comma()? {None}