difftreelog
fix unify handling of field in obj and objcomp
in: master
3 files changed
crates/jrsonnet-evaluator/src/evaluate/mod.rsdiffbeforeafterboth113 UnboundLocals { fctx, locals }113 UnboundLocals { fctx, locals }114}114}115115116#[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 members121 .iter()122 .filter_map(|m| match m {123 Member::BindStmt(bind) => Some(bind.clone()),124 _ => None,125 })126 .collect::<Vec<_>>(),127 );128129 let fctx = Context::new_future();118 ctx: Context,130131 // We have single context for all fields, so we can cache binds132 let uctx = CachedUnbound::new(evaluate_object_locals(fctx.clone(), locals));119 uctx: B,133134 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,159146160 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 };164151165 builder152 builder173 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 }200187201 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 };204191205 builder192 builder213 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();206237 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 members212 .iter()213 .filter_map(|m| match m {214 Member::BindStmt(bind) => Some(bind.clone()),215 _ => None,216 })217 .collect::<Vec<_>>(),218 );219220 let fctx = Context::new_future();221222 // We have single context for all fields, so we can cache binds223 let uctx = CachedUnbound::new(evaluate_object_locals(fctx.clone(), locals));224225 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 handled232 }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}240256241pub 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());259274260 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 builder287 .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 }297298 Ok(())299 })?;276 })?;300277301 let this = builder.build();278 let this = builder.build();crates/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>,
}
crates/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,
})