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

difftreelog

fix unify handling of field in obj and objcomp

Yaroslav Bolyukin2022-11-09parent: #26153bc.patch.diff
in: master

3 files changed

modifiedcrates/jrsonnet-evaluator/src/evaluate/mod.rsdiffbeforeafterboth
113 UnboundLocals { fctx, locals }113 UnboundLocals { fctx, locals }
114}114}
115115
116#[allow(clippy::too_many_lines)]
117pub fn evaluate_member_list_object(ctx: Context, members: &[Member]) -> Result<ObjValue> {116pub fn evaluate_field_member<B: Unbound<Bound = Context> + Clone>(
118 let mut builder = ObjValueBuilder::new();117 builder: &mut ObjValueBuilder,
119 let locals = Rc::new(
120 members
121 .iter()
122 .filter_map(|m| match m {
123 Member::BindStmt(bind) => Some(bind.clone()),
124 _ => None,
125 })
126 .collect::<Vec<_>>(),
127 );
128
129 let fctx = Context::new_future();118 ctx: Context,
130
131 // We have single context for all fields, so we can cache binds
132 let uctx = CachedUnbound::new(evaluate_object_locals(fctx.clone(), locals));119 uctx: B,
133
134 for member in members.iter() {120 member: &FieldMember,
121) -> Result<()> {
135 match member {122 match member {
136 Member::Field(FieldMember {123 FieldMember {
137 name,124 name,
138 plus,125 plus,
139 params: None,126 params: None,
140 visibility,127 visibility,
141 value,128 value,
142 }) => {129 } => {
143 #[derive(Trace)]130 #[derive(Trace)]
144 struct UnboundValue<B: Trace> {131 struct UnboundValue<B: Trace> {
145 uctx: B,132 uctx: B,
159146
160 let name = evaluate_field_name(ctx.clone(), name)?;147 let name = evaluate_field_name(ctx.clone(), name)?;
161 let Some(name) = name else {148 let Some(name) = name else {
162 continue;149 return Ok(());
163 };150 };
164151
165 builder152 builder
173 name: name.clone()160 name: name.clone()
174 }))?;161 }))?;
175 }162 }
176 Member::Field(FieldMember {163 FieldMember {
177 name,164 name,
178 params: Some(params),165 params: Some(params),
179 value,166 value,
180 ..167 ..
181 }) => {168 } => {
182 #[derive(Trace)]169 #[derive(Trace)]
183 struct UnboundMethod<B: Trace> {170 struct UnboundMethod<B: Trace> {
184 uctx: B,171 uctx: B,
199 }186 }
200187
201 let Some(name) = evaluate_field_name(ctx.clone(), name)? else {188 let Some(name) = evaluate_field_name(ctx.clone(), name)? else {
202 continue;189 return Ok(());
203 };190 };
204191
205 builder192 builder
213 name: name.clone()200 name: name.clone()
214 }))?;201 }))?;
215 }202 }
216 Member::BindStmt(_) => {}
217 Member::AssertStmt(stmt) => {
218 #[derive(Trace)]
219 struct ObjectAssert<B: Trace> {
220 uctx: B,
221 assert: AssertStmt,
222 }
223 impl<B: Unbound<Bound = Context>> ObjectAssertion for ObjectAssert<B> {
224 fn run(&self, sup: Option<ObjValue>, this: Option<ObjValue>) -> Result<()> {
225 let ctx = self.uctx.bind(sup, this)?;
226 evaluate_assert(ctx, &self.assert)
227 }
228 }
229 builder.assert(tb!(ObjectAssert {
230 uctx: uctx.clone(),
231 assert: stmt.clone(),
232 }));
233 }
234 }203 }
204 Ok(())
235 }205}
236 let this = builder.build();206
237 fctx.fill(ctx.extend(GcHashMap::new(), None, None, Some(this.clone())));207#[allow(clippy::too_many_lines)]
238 Ok(this)208pub fn evaluate_member_list_object(ctx: Context, members: &[Member]) -> Result<ObjValue> {
239}209 let mut builder = ObjValueBuilder::new();
210 let locals = Rc::new(
211 members
212 .iter()
213 .filter_map(|m| match m {
214 Member::BindStmt(bind) => Some(bind.clone()),
215 _ => None,
216 })
217 .collect::<Vec<_>>(),
218 );
219
220 let fctx = Context::new_future();
221
222 // We have single context for all fields, so we can cache binds
223 let uctx = CachedUnbound::new(evaluate_object_locals(fctx.clone(), locals));
224
225 for member in members.iter() {
226 match member {
227 Member::Field(field) => {
228 evaluate_field_member(&mut builder, ctx.clone(), uctx.clone(), &field)?
229 }
230 Member::BindStmt(_) => {
231 // Already handled
232 }
233 Member::AssertStmt(stmt) => {
234 #[derive(Trace)]
235 struct ObjectAssert<B: Trace> {
236 uctx: B,
237 assert: AssertStmt,
238 }
239 impl<B: Unbound<Bound = Context>> ObjectAssertion for ObjectAssert<B> {
240 fn run(&self, sup: Option<ObjValue>, this: Option<ObjValue>) -> Result<()> {
241 let ctx = self.uctx.bind(sup, this)?;
242 evaluate_assert(ctx, &self.assert)
243 }
244 }
245 builder.assert(tb!(ObjectAssert {
246 uctx: uctx.clone(),
247 assert: stmt.clone(),
248 }));
249 }
250 }
251 }
252 let this = builder.build();
253 fctx.fill(ctx.extend(GcHashMap::new(), None, None, Some(this.clone())));
254 Ok(this)
255}
240256
241pub fn evaluate_object(ctx: Context, object: &ObjBody) -> Result<ObjValue> {257pub fn evaluate_object(ctx: Context, object: &ObjBody) -> Result<ObjValue> {
242 Ok(match object {258 Ok(match object {
252 );268 );
253 let mut ctxs = vec![];269 let mut ctxs = vec![];
254 evaluate_comp(ctx, &obj.compspecs, &mut |ctx| {270 evaluate_comp(ctx, &obj.compspecs, &mut |ctx| {
255 let key = evaluate(ctx.clone(), &obj.key)?;
256 let fctx = Context::new_future();271 let fctx = Context::new_future();
257 ctxs.push((ctx, fctx.clone()));272 ctxs.push((ctx.clone(), fctx.clone()));
258 let uctx = evaluate_object_locals(fctx, locals.clone());273 let uctx = evaluate_object_locals(fctx, locals.clone());
259274
260 match key {
261 Val::Null => {}
262 Val::Str(n) => {
263 #[derive(Trace)]
264 struct UnboundValue<B: Trace> {
265 uctx: B,
266 value: LocExpr,
267 }
268 impl<B: Unbound<Bound = Context>> Unbound for UnboundValue<B> {
269 type Bound = Val;
270 fn bind(
271 &self,
272 sup: Option<ObjValue>,
273 this: Option<ObjValue>,
274 ) -> Result<Val> {
275 Ok(evaluate(275 evaluate_field_member(&mut builder, ctx, uctx, &obj.field)
276 self.uctx.bind(sup, this.clone())?.extend(
277 GcHashMap::new(),
278 None,
279 None,
280 this,
281 ),
282 &self.value,
283 )?)
284 }
285 }
286 builder
287 .member(n)
288 .with_location(obj.value.1.clone())
289 .with_add(obj.plus)
290 .bindable(tb!(UnboundValue {
291 uctx,
292 value: obj.value.clone(),
293 }))?;
294 }
295 v => throw!(FieldMustBeStringGot(v.value_type())),
296 }
297
298 Ok(())
299 })?;276 })?;
300277
301 let this = builder.build();278 let this = builder.build();
modifiedcrates/jrsonnet-parser/src/expr.rsdiffbeforeafterboth
--- a/crates/jrsonnet-parser/src/expr.rs
+++ b/crates/jrsonnet-parser/src/expr.rs
@@ -268,9 +268,7 @@
 #[derive(Debug, PartialEq, Trace)]
 pub struct ObjComp {
 	pub pre_locals: Vec<BindSpec>,
-	pub key: LocExpr,
-	pub plus: bool,
-	pub value: LocExpr,
+	pub field: FieldMember,
 	pub post_locals: Vec<BindSpec>,
 	pub compspecs: Vec<CompSpec>,
 }
modifiedcrates/jrsonnet-parser/src/lib.rsdiffbeforeafterboth
--- a/crates/jrsonnet-parser/src/lib.rs
+++ b/crates/jrsonnet-parser/src/lib.rs
@@ -194,14 +194,12 @@
 			/ assertion:assertion(s) {expr::Member::AssertStmt(assertion)}
 			/ field:field(s) {expr::Member::Field(field)}
 		pub rule objinside(s: &ParserSettings) -> expr::ObjBody
-			= pre_locals:(b: obj_local(s) comma() {b})* "[" _ key:expr(s) _ "]" _ plus:"+"? _ ":" _ value:expr(s) post_locals:(comma() b:obj_local(s) {b})* _ ("," _)? forspec:forspec(s) others:(_ rest:compspec(s) {rest})? {
+			= pre_locals:(b: obj_local(s) comma() {b})* field:field(s) post_locals:(comma() b:obj_local(s) {b})* _ ("," _)? forspec:forspec(s) others:(_ rest:compspec(s) {rest})? {
 				let mut compspecs = vec![CompSpec::ForSpec(forspec)];
 				compspecs.extend(others.unwrap_or_default());
 				expr::ObjBody::ObjComp(expr::ObjComp{
 					pre_locals,
-					key,
-					plus: plus.is_some(),
-					value,
+					field,
 					post_locals,
 					compspecs,
 				})