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
--- a/crates/jrsonnet-evaluator/src/evaluate/mod.rs
+++ b/crates/jrsonnet-evaluator/src/evaluate/mod.rs
@@ -113,6 +113,97 @@
 	UnboundLocals { fctx, locals }
 }
 
+pub fn evaluate_field_member<B: Unbound<Bound = Context> + Clone>(
+	builder: &mut ObjValueBuilder,
+	ctx: Context,
+	uctx: B,
+	member: &FieldMember,
+) -> Result<()> {
+	match member {
+		FieldMember {
+			name,
+			plus,
+			params: None,
+			visibility,
+			value,
+		} => {
+			#[derive(Trace)]
+			struct UnboundValue<B: Trace> {
+				uctx: B,
+				value: LocExpr,
+				name: IStr,
+			}
+			impl<B: Unbound<Bound = Context>> Unbound for UnboundValue<B> {
+				type Bound = Val;
+				fn bind(&self, sup: Option<ObjValue>, this: Option<ObjValue>) -> Result<Val> {
+					Ok(evaluate_named(
+						self.uctx.bind(sup, this)?,
+						&self.value,
+						self.name.clone(),
+					)?)
+				}
+			}
+
+			let name = evaluate_field_name(ctx.clone(), name)?;
+			let Some(name) = name else {
+				return Ok(());
+			};
+
+			builder
+				.member(name.clone())
+				.with_add(*plus)
+				.with_visibility(*visibility)
+				.with_location(value.1.clone())
+				.bindable(tb!(UnboundValue {
+					uctx: uctx.clone(),
+					value: value.clone(),
+					name: name.clone()
+				}))?;
+		}
+		FieldMember {
+			name,
+			params: Some(params),
+			value,
+			..
+		} => {
+			#[derive(Trace)]
+			struct UnboundMethod<B: Trace> {
+				uctx: B,
+				value: LocExpr,
+				params: ParamsDesc,
+				name: IStr,
+			}
+			impl<B: Unbound<Bound = Context>> Unbound for UnboundMethod<B> {
+				type Bound = Val;
+				fn bind(&self, sup: Option<ObjValue>, this: Option<ObjValue>) -> Result<Val> {
+					Ok(evaluate_method(
+						self.uctx.bind(sup, this)?,
+						self.name.clone(),
+						self.params.clone(),
+						self.value.clone(),
+					))
+				}
+			}
+
+			let Some(name) = evaluate_field_name(ctx.clone(), name)? else {
+				return Ok(());
+			};
+
+			builder
+				.member(name.clone())
+				.hide()
+				.with_location(value.1.clone())
+				.bindable(tb!(UnboundMethod {
+					uctx: uctx.clone(),
+					value: value.clone(),
+					params: params.clone(),
+					name: name.clone()
+				}))?;
+		}
+	}
+	Ok(())
+}
+
 #[allow(clippy::too_many_lines)]
 pub fn evaluate_member_list_object(ctx: Context, members: &[Member]) -> Result<ObjValue> {
 	let mut builder = ObjValueBuilder::new();
@@ -133,87 +224,12 @@
 
 	for member in members.iter() {
 		match member {
-			Member::Field(FieldMember {
-				name,
-				plus,
-				params: None,
-				visibility,
-				value,
-			}) => {
-				#[derive(Trace)]
-				struct UnboundValue<B: Trace> {
-					uctx: B,
-					value: LocExpr,
-					name: IStr,
-				}
-				impl<B: Unbound<Bound = Context>> Unbound for UnboundValue<B> {
-					type Bound = Val;
-					fn bind(&self, sup: Option<ObjValue>, this: Option<ObjValue>) -> Result<Val> {
-						Ok(evaluate_named(
-							self.uctx.bind(sup, this)?,
-							&self.value,
-							self.name.clone(),
-						)?)
-					}
-				}
-
-				let name = evaluate_field_name(ctx.clone(), name)?;
-				let Some(name) = name else {
-					continue;
-				};
-
-				builder
-					.member(name.clone())
-					.with_add(*plus)
-					.with_visibility(*visibility)
-					.with_location(value.1.clone())
-					.bindable(tb!(UnboundValue {
-						uctx: uctx.clone(),
-						value: value.clone(),
-						name: name.clone()
-					}))?;
+			Member::Field(field) => {
+				evaluate_field_member(&mut builder, ctx.clone(), uctx.clone(), &field)?
 			}
-			Member::Field(FieldMember {
-				name,
-				params: Some(params),
-				value,
-				..
-			}) => {
-				#[derive(Trace)]
-				struct UnboundMethod<B: Trace> {
-					uctx: B,
-					value: LocExpr,
-					params: ParamsDesc,
-					name: IStr,
-				}
-				impl<B: Unbound<Bound = Context>> Unbound for UnboundMethod<B> {
-					type Bound = Val;
-					fn bind(&self, sup: Option<ObjValue>, this: Option<ObjValue>) -> Result<Val> {
-						Ok(evaluate_method(
-							self.uctx.bind(sup, this)?,
-							self.name.clone(),
-							self.params.clone(),
-							self.value.clone(),
-						))
-					}
-				}
-
-				let Some(name) = evaluate_field_name(ctx.clone(), name)? else {
-					continue;
-				};
-
-				builder
-					.member(name.clone())
-					.hide()
-					.with_location(value.1.clone())
-					.bindable(tb!(UnboundMethod {
-						uctx: uctx.clone(),
-						value: value.clone(),
-						params: params.clone(),
-						name: name.clone()
-					}))?;
+			Member::BindStmt(_) => {
+				// Already handled
 			}
-			Member::BindStmt(_) => {}
 			Member::AssertStmt(stmt) => {
 				#[derive(Trace)]
 				struct ObjectAssert<B: Trace> {
@@ -252,50 +268,11 @@
 			);
 			let mut ctxs = vec![];
 			evaluate_comp(ctx, &obj.compspecs, &mut |ctx| {
-				let key = evaluate(ctx.clone(), &obj.key)?;
 				let fctx = Context::new_future();
-				ctxs.push((ctx, fctx.clone()));
+				ctxs.push((ctx.clone(), fctx.clone()));
 				let uctx = evaluate_object_locals(fctx, locals.clone());
 
-				match key {
-					Val::Null => {}
-					Val::Str(n) => {
-						#[derive(Trace)]
-						struct UnboundValue<B: Trace> {
-							uctx: B,
-							value: LocExpr,
-						}
-						impl<B: Unbound<Bound = Context>> Unbound for UnboundValue<B> {
-							type Bound = Val;
-							fn bind(
-								&self,
-								sup: Option<ObjValue>,
-								this: Option<ObjValue>,
-							) -> Result<Val> {
-								Ok(evaluate(
-									self.uctx.bind(sup, this.clone())?.extend(
-										GcHashMap::new(),
-										None,
-										None,
-										this,
-									),
-									&self.value,
-								)?)
-							}
-						}
-						builder
-							.member(n)
-							.with_location(obj.value.1.clone())
-							.with_add(obj.plus)
-							.bindable(tb!(UnboundValue {
-								uctx,
-								value: obj.value.clone(),
-							}))?;
-					}
-					v => throw!(FieldMustBeStringGot(v.value_type())),
-				}
-
-				Ok(())
+				evaluate_field_member(&mut builder, ctx, uctx, &obj.field)
 			})?;
 
 			let this = builder.build();
modifiedcrates/jrsonnet-parser/src/expr.rsdiffbeforeafterboth
before · crates/jrsonnet-parser/src/expr.rs
1use std::{2	fmt::{self, Debug, Display},3	ops::Deref,4	rc::Rc,5};67use jrsonnet_gcmodule::Trace;8use jrsonnet_interner::IStr;9#[cfg(feature = "serde")]10use serde::{Deserialize, Serialize};11#[cfg(feature = "structdump")]12use structdump::Codegen;1314use crate::source::Source;1516#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]17#[cfg_attr(feature = "structdump", derive(Codegen))]18#[derive(Debug, PartialEq, Trace)]19pub enum FieldName {20	/// {fixed: 2}21	Fixed(IStr),22	/// {["dyn"+"amic"]: 3}23	Dyn(LocExpr),24}2526#[cfg_attr(feature = "structdump", derive(Codegen))]27#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]28#[derive(Debug, Clone, Copy, PartialEq, Eq, Trace)]29pub enum Visibility {30	/// :31	Normal,32	/// ::33	Hidden,34	/// :::35	Unhide,36}3738impl Visibility {39	pub fn is_visible(&self) -> bool {40		matches!(self, Self::Normal | Self::Unhide)41	}42}4344#[cfg_attr(feature = "structdump", derive(Codegen))]45#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]46#[derive(Clone, Debug, PartialEq, Trace)]47pub struct AssertStmt(pub LocExpr, pub Option<LocExpr>);4849#[cfg_attr(feature = "structdump", derive(Codegen))]50#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]51#[derive(Debug, PartialEq, Trace)]52pub struct FieldMember {53	pub name: FieldName,54	pub plus: bool,55	pub params: Option<ParamsDesc>,56	pub visibility: Visibility,57	pub value: LocExpr,58}5960#[cfg_attr(feature = "structdump", derive(Codegen))]61#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]62#[derive(Debug, PartialEq, Trace)]63pub enum Member {64	Field(FieldMember),65	BindStmt(BindSpec),66	AssertStmt(AssertStmt),67}6869#[cfg_attr(feature = "structdump", derive(Codegen))]70#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]71#[derive(Debug, Clone, Copy, PartialEq, Eq, Trace)]72pub enum UnaryOpType {73	Plus,74	Minus,75	BitNot,76	Not,77}7879impl Display for UnaryOpType {80	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {81		use UnaryOpType::*;82		write!(83			f,84			"{}",85			match self {86				Plus => "+",87				Minus => "-",88				BitNot => "~",89				Not => "!",90			}91		)92	}93}9495#[cfg_attr(feature = "structdump", derive(Codegen))]96#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]97#[derive(Debug, Clone, Copy, PartialEq, Eq, Trace)]98pub enum BinaryOpType {99	Mul,100	Div,101102	/// Implemented as intrinsic, put here for completeness103	Mod,104105	Add,106	Sub,107108	Lhs,109	Rhs,110111	Lt,112	Gt,113	Lte,114	Gte,115116	BitAnd,117	BitOr,118	BitXor,119120	Eq,121	Neq,122123	And,124	Or,125126	// Equialent to std.objectHasEx(a, b, true)127	In,128}129130impl Display for BinaryOpType {131	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {132		use BinaryOpType::*;133		write!(134			f,135			"{}",136			match self {137				Mul => "*",138				Div => "/",139				Mod => "%",140				Add => "+",141				Sub => "-",142				Lhs => "<<",143				Rhs => ">>",144				Lt => "<",145				Gt => ">",146				Lte => "<=",147				Gte => ">=",148				BitAnd => "&",149				BitOr => "|",150				BitXor => "^",151				Eq => "==",152				Neq => "!=",153				And => "&&",154				Or => "||",155				In => "in",156			}157		)158	}159}160161/// name, default value162#[cfg_attr(feature = "structdump", derive(Codegen))]163#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]164#[derive(Debug, PartialEq, Trace)]165pub struct Param(pub Destruct, pub Option<LocExpr>);166167/// Defined function parameters168#[cfg_attr(feature = "structdump", derive(Codegen))]169#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]170#[derive(Debug, Clone, PartialEq, Trace)]171pub struct ParamsDesc(pub Rc<Vec<Param>>);172173impl Deref for ParamsDesc {174	type Target = Vec<Param>;175	fn deref(&self) -> &Self::Target {176		&self.0177	}178}179180#[cfg_attr(feature = "structdump", derive(Codegen))]181#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]182#[derive(Debug, PartialEq, Trace)]183pub struct ArgsDesc {184	pub unnamed: Vec<LocExpr>,185	pub named: Vec<(IStr, LocExpr)>,186}187impl ArgsDesc {188	pub fn new(unnamed: Vec<LocExpr>, named: Vec<(IStr, LocExpr)>) -> Self {189		Self { unnamed, named }190	}191}192193#[cfg_attr(feature = "structdump", derive(Codegen))]194#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]195#[derive(Debug, Clone, PartialEq, Eq, Trace)]196pub enum DestructRest {197	/// ...rest198	Keep(IStr),199	/// ...200	Drop,201}202203#[cfg_attr(feature = "structdump", derive(Codegen))]204#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]205#[derive(Debug, Clone, PartialEq, Trace)]206pub enum Destruct {207	Full(IStr),208	#[cfg(feature = "exp-destruct")]209	Skip,210	#[cfg(feature = "exp-destruct")]211	Array {212		start: Vec<Destruct>,213		rest: Option<DestructRest>,214		end: Vec<Destruct>,215	},216	#[cfg(feature = "exp-destruct")]217	Object {218		fields: Vec<(IStr, Option<Destruct>, Option<LocExpr>)>,219		rest: Option<DestructRest>,220	},221}222impl Destruct {223	/// Name of destructure, used for function parameter names224	pub fn name(&self) -> Option<IStr> {225		match self {226			Self::Full(name) => Some(name.clone()),227			#[cfg(feature = "exp-destruct")]228			_ => None,229		}230	}231}232233#[cfg_attr(feature = "structdump", derive(Codegen))]234#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]235#[derive(Debug, Clone, PartialEq, Trace)]236pub enum BindSpec {237	Field {238		into: Destruct,239		value: LocExpr,240	},241	Function {242		name: IStr,243		params: ParamsDesc,244		value: LocExpr,245	},246}247248#[cfg_attr(feature = "structdump", derive(Codegen))]249#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]250#[derive(Debug, PartialEq, Trace)]251pub struct IfSpecData(pub LocExpr);252253#[cfg_attr(feature = "structdump", derive(Codegen))]254#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]255#[derive(Debug, PartialEq, Trace)]256pub struct ForSpecData(pub IStr, pub LocExpr);257258#[cfg_attr(feature = "structdump", derive(Codegen))]259#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]260#[derive(Debug, PartialEq, Trace)]261pub enum CompSpec {262	IfSpec(IfSpecData),263	ForSpec(ForSpecData),264}265266#[cfg_attr(feature = "structdump", derive(Codegen))]267#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]268#[derive(Debug, PartialEq, Trace)]269pub struct ObjComp {270	pub pre_locals: Vec<BindSpec>,271	pub key: LocExpr,272	pub plus: bool,273	pub value: LocExpr,274	pub post_locals: Vec<BindSpec>,275	pub compspecs: Vec<CompSpec>,276}277278#[cfg_attr(feature = "structdump", derive(Codegen))]279#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]280#[derive(Debug, PartialEq, Trace)]281pub enum ObjBody {282	MemberList(Vec<Member>),283	ObjComp(ObjComp),284}285286#[cfg_attr(feature = "structdump", derive(Codegen))]287#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]288#[derive(Debug, PartialEq, Eq, Clone, Copy, Trace)]289pub enum LiteralType {290	This,291	Super,292	Dollar,293	Null,294	True,295	False,296}297298#[cfg_attr(feature = "structdump", derive(Codegen))]299#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]300#[derive(Debug, PartialEq, Trace)]301pub struct SliceDesc {302	pub start: Option<LocExpr>,303	pub end: Option<LocExpr>,304	pub step: Option<LocExpr>,305}306307/// Syntax base308#[cfg_attr(feature = "structdump", derive(Codegen))]309#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]310#[derive(Debug, PartialEq, Trace)]311pub enum Expr {312	Literal(LiteralType),313314	/// String value: "hello"315	Str(IStr),316	/// Number: 1, 2.0, 2e+20317	Num(f64),318	/// Variable name: test319	Var(IStr),320321	/// Array of expressions: [1, 2, "Hello"]322	Arr(Vec<LocExpr>),323	/// Array comprehension:324	/// ```jsonnet325	///  ingredients: [326	///    { kind: kind, qty: 4 / 3 }327	///    for kind in [328	///      'Honey Syrup',329	///      'Lemon Juice',330	///      'Farmers Gin',331	///    ]332	///  ],333	/// ```334	ArrComp(LocExpr, Vec<CompSpec>),335336	/// Object: {a: 2}337	Obj(ObjBody),338	/// Object extension: var1 {b: 2}339	ObjExtend(LocExpr, ObjBody),340341	/// (obj)342	Parened(LocExpr),343344	/// -2345	UnaryOp(UnaryOpType, LocExpr),346	/// 2 - 2347	BinaryOp(LocExpr, BinaryOpType, LocExpr),348	/// assert 2 == 2 : "Math is broken"349	AssertExpr(AssertStmt, LocExpr),350	/// local a = 2; { b: a }351	LocalExpr(Vec<BindSpec>, LocExpr),352353	/// import "hello"354	Import(IStr),355	/// importStr "file.txt"356	ImportStr(IStr),357	/// importBin "file.txt"358	ImportBin(IStr),359	/// error "I'm broken"360	ErrorStmt(LocExpr),361	/// a(b, c)362	Apply(LocExpr, ArgsDesc, bool),363	/// a[b]364	Index(LocExpr, LocExpr),365	/// function(x) x366	Function(ParamsDesc, LocExpr),367	/// if true == false then 1 else 2368	IfElse {369		cond: IfSpecData,370		cond_then: LocExpr,371		cond_else: Option<LocExpr>,372	},373	Slice(LocExpr, SliceDesc),374}375376/// file, begin offset, end offset377#[cfg_attr(feature = "structdump", derive(Codegen))]378#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]379#[derive(Clone, PartialEq, Eq, Trace)]380#[trace(skip)]381#[repr(C)]382pub struct ExprLocation(pub Source, pub u32, pub u32);383impl ExprLocation {384	pub fn belongs_to(&self, other: &ExprLocation) -> bool {385		other.0 == self.0 && other.1 <= self.1 && other.2 >= self.2386	}387}388389#[cfg(target_pointer_width = "64")]390static_assertions::assert_eq_size!(ExprLocation, [u8; 16]);391392impl Debug for ExprLocation {393	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {394		write!(f, "{:?}:{:?}-{:?}", self.0, self.1, self.2)395	}396}397398/// Holds AST expression and its location in source file399#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]400#[cfg_attr(feature = "structdump", derive(Codegen))]401#[derive(Clone, PartialEq, Trace)]402pub struct LocExpr(pub Rc<Expr>, pub ExprLocation);403404#[cfg(target_pointer_width = "64")]405static_assertions::assert_eq_size!(LocExpr, [u8; 24]);406407impl Debug for LocExpr {408	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {409		if f.alternate() {410			write!(f, "{:#?}", self.0)?;411		} else {412			write!(f, "{:?}", self.0)?;413		}414		write!(f, " from {:?}", self.1)?;415		Ok(())416	}417}
after · crates/jrsonnet-parser/src/expr.rs
1use std::{2	fmt::{self, Debug, Display},3	ops::Deref,4	rc::Rc,5};67use jrsonnet_gcmodule::Trace;8use jrsonnet_interner::IStr;9#[cfg(feature = "serde")]10use serde::{Deserialize, Serialize};11#[cfg(feature = "structdump")]12use structdump::Codegen;1314use crate::source::Source;1516#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]17#[cfg_attr(feature = "structdump", derive(Codegen))]18#[derive(Debug, PartialEq, Trace)]19pub enum FieldName {20	/// {fixed: 2}21	Fixed(IStr),22	/// {["dyn"+"amic"]: 3}23	Dyn(LocExpr),24}2526#[cfg_attr(feature = "structdump", derive(Codegen))]27#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]28#[derive(Debug, Clone, Copy, PartialEq, Eq, Trace)]29pub enum Visibility {30	/// :31	Normal,32	/// ::33	Hidden,34	/// :::35	Unhide,36}3738impl Visibility {39	pub fn is_visible(&self) -> bool {40		matches!(self, Self::Normal | Self::Unhide)41	}42}4344#[cfg_attr(feature = "structdump", derive(Codegen))]45#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]46#[derive(Clone, Debug, PartialEq, Trace)]47pub struct AssertStmt(pub LocExpr, pub Option<LocExpr>);4849#[cfg_attr(feature = "structdump", derive(Codegen))]50#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]51#[derive(Debug, PartialEq, Trace)]52pub struct FieldMember {53	pub name: FieldName,54	pub plus: bool,55	pub params: Option<ParamsDesc>,56	pub visibility: Visibility,57	pub value: LocExpr,58}5960#[cfg_attr(feature = "structdump", derive(Codegen))]61#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]62#[derive(Debug, PartialEq, Trace)]63pub enum Member {64	Field(FieldMember),65	BindStmt(BindSpec),66	AssertStmt(AssertStmt),67}6869#[cfg_attr(feature = "structdump", derive(Codegen))]70#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]71#[derive(Debug, Clone, Copy, PartialEq, Eq, Trace)]72pub enum UnaryOpType {73	Plus,74	Minus,75	BitNot,76	Not,77}7879impl Display for UnaryOpType {80	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {81		use UnaryOpType::*;82		write!(83			f,84			"{}",85			match self {86				Plus => "+",87				Minus => "-",88				BitNot => "~",89				Not => "!",90			}91		)92	}93}9495#[cfg_attr(feature = "structdump", derive(Codegen))]96#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]97#[derive(Debug, Clone, Copy, PartialEq, Eq, Trace)]98pub enum BinaryOpType {99	Mul,100	Div,101102	/// Implemented as intrinsic, put here for completeness103	Mod,104105	Add,106	Sub,107108	Lhs,109	Rhs,110111	Lt,112	Gt,113	Lte,114	Gte,115116	BitAnd,117	BitOr,118	BitXor,119120	Eq,121	Neq,122123	And,124	Or,125126	// Equialent to std.objectHasEx(a, b, true)127	In,128}129130impl Display for BinaryOpType {131	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {132		use BinaryOpType::*;133		write!(134			f,135			"{}",136			match self {137				Mul => "*",138				Div => "/",139				Mod => "%",140				Add => "+",141				Sub => "-",142				Lhs => "<<",143				Rhs => ">>",144				Lt => "<",145				Gt => ">",146				Lte => "<=",147				Gte => ">=",148				BitAnd => "&",149				BitOr => "|",150				BitXor => "^",151				Eq => "==",152				Neq => "!=",153				And => "&&",154				Or => "||",155				In => "in",156			}157		)158	}159}160161/// name, default value162#[cfg_attr(feature = "structdump", derive(Codegen))]163#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]164#[derive(Debug, PartialEq, Trace)]165pub struct Param(pub Destruct, pub Option<LocExpr>);166167/// Defined function parameters168#[cfg_attr(feature = "structdump", derive(Codegen))]169#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]170#[derive(Debug, Clone, PartialEq, Trace)]171pub struct ParamsDesc(pub Rc<Vec<Param>>);172173impl Deref for ParamsDesc {174	type Target = Vec<Param>;175	fn deref(&self) -> &Self::Target {176		&self.0177	}178}179180#[cfg_attr(feature = "structdump", derive(Codegen))]181#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]182#[derive(Debug, PartialEq, Trace)]183pub struct ArgsDesc {184	pub unnamed: Vec<LocExpr>,185	pub named: Vec<(IStr, LocExpr)>,186}187impl ArgsDesc {188	pub fn new(unnamed: Vec<LocExpr>, named: Vec<(IStr, LocExpr)>) -> Self {189		Self { unnamed, named }190	}191}192193#[cfg_attr(feature = "structdump", derive(Codegen))]194#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]195#[derive(Debug, Clone, PartialEq, Eq, Trace)]196pub enum DestructRest {197	/// ...rest198	Keep(IStr),199	/// ...200	Drop,201}202203#[cfg_attr(feature = "structdump", derive(Codegen))]204#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]205#[derive(Debug, Clone, PartialEq, Trace)]206pub enum Destruct {207	Full(IStr),208	#[cfg(feature = "exp-destruct")]209	Skip,210	#[cfg(feature = "exp-destruct")]211	Array {212		start: Vec<Destruct>,213		rest: Option<DestructRest>,214		end: Vec<Destruct>,215	},216	#[cfg(feature = "exp-destruct")]217	Object {218		fields: Vec<(IStr, Option<Destruct>, Option<LocExpr>)>,219		rest: Option<DestructRest>,220	},221}222impl Destruct {223	/// Name of destructure, used for function parameter names224	pub fn name(&self) -> Option<IStr> {225		match self {226			Self::Full(name) => Some(name.clone()),227			#[cfg(feature = "exp-destruct")]228			_ => None,229		}230	}231}232233#[cfg_attr(feature = "structdump", derive(Codegen))]234#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]235#[derive(Debug, Clone, PartialEq, Trace)]236pub enum BindSpec {237	Field {238		into: Destruct,239		value: LocExpr,240	},241	Function {242		name: IStr,243		params: ParamsDesc,244		value: LocExpr,245	},246}247248#[cfg_attr(feature = "structdump", derive(Codegen))]249#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]250#[derive(Debug, PartialEq, Trace)]251pub struct IfSpecData(pub LocExpr);252253#[cfg_attr(feature = "structdump", derive(Codegen))]254#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]255#[derive(Debug, PartialEq, Trace)]256pub struct ForSpecData(pub IStr, pub LocExpr);257258#[cfg_attr(feature = "structdump", derive(Codegen))]259#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]260#[derive(Debug, PartialEq, Trace)]261pub enum CompSpec {262	IfSpec(IfSpecData),263	ForSpec(ForSpecData),264}265266#[cfg_attr(feature = "structdump", derive(Codegen))]267#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]268#[derive(Debug, PartialEq, Trace)]269pub struct ObjComp {270	pub pre_locals: Vec<BindSpec>,271	pub field: FieldMember,272	pub post_locals: Vec<BindSpec>,273	pub compspecs: Vec<CompSpec>,274}275276#[cfg_attr(feature = "structdump", derive(Codegen))]277#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]278#[derive(Debug, PartialEq, Trace)]279pub enum ObjBody {280	MemberList(Vec<Member>),281	ObjComp(ObjComp),282}283284#[cfg_attr(feature = "structdump", derive(Codegen))]285#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]286#[derive(Debug, PartialEq, Eq, Clone, Copy, Trace)]287pub enum LiteralType {288	This,289	Super,290	Dollar,291	Null,292	True,293	False,294}295296#[cfg_attr(feature = "structdump", derive(Codegen))]297#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]298#[derive(Debug, PartialEq, Trace)]299pub struct SliceDesc {300	pub start: Option<LocExpr>,301	pub end: Option<LocExpr>,302	pub step: Option<LocExpr>,303}304305/// Syntax base306#[cfg_attr(feature = "structdump", derive(Codegen))]307#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]308#[derive(Debug, PartialEq, Trace)]309pub enum Expr {310	Literal(LiteralType),311312	/// String value: "hello"313	Str(IStr),314	/// Number: 1, 2.0, 2e+20315	Num(f64),316	/// Variable name: test317	Var(IStr),318319	/// Array of expressions: [1, 2, "Hello"]320	Arr(Vec<LocExpr>),321	/// Array comprehension:322	/// ```jsonnet323	///  ingredients: [324	///    { kind: kind, qty: 4 / 3 }325	///    for kind in [326	///      'Honey Syrup',327	///      'Lemon Juice',328	///      'Farmers Gin',329	///    ]330	///  ],331	/// ```332	ArrComp(LocExpr, Vec<CompSpec>),333334	/// Object: {a: 2}335	Obj(ObjBody),336	/// Object extension: var1 {b: 2}337	ObjExtend(LocExpr, ObjBody),338339	/// (obj)340	Parened(LocExpr),341342	/// -2343	UnaryOp(UnaryOpType, LocExpr),344	/// 2 - 2345	BinaryOp(LocExpr, BinaryOpType, LocExpr),346	/// assert 2 == 2 : "Math is broken"347	AssertExpr(AssertStmt, LocExpr),348	/// local a = 2; { b: a }349	LocalExpr(Vec<BindSpec>, LocExpr),350351	/// import "hello"352	Import(IStr),353	/// importStr "file.txt"354	ImportStr(IStr),355	/// importBin "file.txt"356	ImportBin(IStr),357	/// error "I'm broken"358	ErrorStmt(LocExpr),359	/// a(b, c)360	Apply(LocExpr, ArgsDesc, bool),361	/// a[b]362	Index(LocExpr, LocExpr),363	/// function(x) x364	Function(ParamsDesc, LocExpr),365	/// if true == false then 1 else 2366	IfElse {367		cond: IfSpecData,368		cond_then: LocExpr,369		cond_else: Option<LocExpr>,370	},371	Slice(LocExpr, SliceDesc),372}373374/// file, begin offset, end offset375#[cfg_attr(feature = "structdump", derive(Codegen))]376#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]377#[derive(Clone, PartialEq, Eq, Trace)]378#[trace(skip)]379#[repr(C)]380pub struct ExprLocation(pub Source, pub u32, pub u32);381impl ExprLocation {382	pub fn belongs_to(&self, other: &ExprLocation) -> bool {383		other.0 == self.0 && other.1 <= self.1 && other.2 >= self.2384	}385}386387#[cfg(target_pointer_width = "64")]388static_assertions::assert_eq_size!(ExprLocation, [u8; 16]);389390impl Debug for ExprLocation {391	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {392		write!(f, "{:?}:{:?}-{:?}", self.0, self.1, self.2)393	}394}395396/// Holds AST expression and its location in source file397#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]398#[cfg_attr(feature = "structdump", derive(Codegen))]399#[derive(Clone, PartialEq, Trace)]400pub struct LocExpr(pub Rc<Expr>, pub ExprLocation);401402#[cfg(target_pointer_width = "64")]403static_assertions::assert_eq_size!(LocExpr, [u8; 24]);404405impl Debug for LocExpr {406	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {407		if f.alternate() {408			write!(f, "{:#?}", self.0)?;409		} else {410			write!(f, "{:?}", self.0)?;411		}412		write!(f, " from {:?}", self.1)?;413		Ok(())414	}415}
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,
 				})