git.delta.rocks / jrsonnet / refs/commits / 53ec857983ef

difftreelog

refactor skip desugaring for in operator

Yaroslav Bolyukin2021-07-04parent: #f047fb1.patch.diff
in: master

3 files changed

modifiedcrates/jrsonnet-evaluator/src/evaluate/operator.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/evaluate/operator.rs
+++ b/crates/jrsonnet-evaluator/src/evaluate/operator.rs
@@ -60,6 +60,8 @@
 	use BinaryOpType::*;
 	use Val::*;
 	Ok(match (a, op, b) {
+		(Str(a), In, Obj(obj)) => Bool(obj.has_field_ex(a.clone(), true)),
+
 		(a, Add, b) => evaluate_add_op(a, b)?,
 
 		(a, Eq, b) => Bool(equals(a, b)?),
modifiedcrates/jrsonnet-parser/src/expr.rsdiffbeforeafterboth
before · crates/jrsonnet-parser/src/expr.rs
1use jrsonnet_gc::{unsafe_empty_trace, Finalize, Trace};2use jrsonnet_interner::IStr;3#[cfg(feature = "deserialize")]4use serde::Deserialize;5#[cfg(feature = "serialize")]6use serde::Serialize;7use std::{8	fmt::{Debug, Display},9	ops::Deref,10	path::{Path, PathBuf},11	rc::Rc,12};1314#[cfg_attr(feature = "serialize", derive(Serialize))]15#[cfg_attr(feature = "deserialize", derive(Deserialize))]16#[derive(Debug, PartialEq, Trace)]17#[trivially_drop]18pub enum FieldName {19	/// {fixed: 2}20	Fixed(IStr),21	/// {["dyn"+"amic"]: 3}22	Dyn(LocExpr),23}2425#[cfg_attr(feature = "serialize", derive(Serialize))]26#[cfg_attr(feature = "deserialize", derive(Deserialize))]27#[derive(Debug, Clone, Copy, PartialEq, Trace)]28#[trivially_drop]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 = "serialize", derive(Serialize))]45#[cfg_attr(feature = "deserialize", derive(Deserialize))]46#[derive(Clone, Debug, PartialEq, Trace)]47#[trivially_drop]48pub struct AssertStmt(pub LocExpr, pub Option<LocExpr>);4950#[cfg_attr(feature = "serialize", derive(Serialize))]51#[cfg_attr(feature = "deserialize", derive(Deserialize))]52#[derive(Debug, PartialEq, Trace)]53#[trivially_drop]54pub struct FieldMember {55	pub name: FieldName,56	pub plus: bool,57	pub params: Option<ParamsDesc>,58	pub visibility: Visibility,59	pub value: LocExpr,60}6162#[cfg_attr(feature = "serialize", derive(Serialize))]63#[cfg_attr(feature = "deserialize", derive(Deserialize))]64#[derive(Debug, PartialEq, Trace)]65#[trivially_drop]66pub enum Member {67	Field(FieldMember),68	BindStmt(BindSpec),69	AssertStmt(AssertStmt),70}7172#[cfg_attr(feature = "serialize", derive(Serialize))]73#[cfg_attr(feature = "deserialize", derive(Deserialize))]74#[derive(Debug, Clone, Copy, PartialEq, Trace)]75#[trivially_drop]76pub enum UnaryOpType {77	Plus,78	Minus,79	BitNot,80	Not,81}8283impl Display for UnaryOpType {84	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {85		use UnaryOpType::*;86		write!(87			f,88			"{}",89			match self {90				Plus => "+",91				Minus => "-",92				BitNot => "~",93				Not => "!",94			}95		)96	}97}9899#[cfg_attr(feature = "serialize", derive(Serialize))]100#[cfg_attr(feature = "deserialize", derive(Deserialize))]101#[derive(Debug, Clone, Copy, PartialEq, Trace)]102#[trivially_drop]103pub enum BinaryOpType {104	Mul,105	Div,106107	/// Implemented as intrinsic, put here for completeness108	Mod,109110	Add,111	Sub,112113	Lhs,114	Rhs,115116	Lt,117	Gt,118	Lte,119	Gte,120121	BitAnd,122	BitOr,123	BitXor,124125	Eq,126	Neq,127128	And,129	Or,130}131132impl Display for BinaryOpType {133	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {134		use BinaryOpType::*;135		write!(136			f,137			"{}",138			match self {139				Mul => "*",140				Div => "/",141				Mod => "%",142				Add => "+",143				Sub => "-",144				Lhs => "<<",145				Rhs => ">>",146				Lt => "<",147				Gt => ">",148				Lte => "<=",149				Gte => ">=",150				BitAnd => "&",151				BitOr => "|",152				BitXor => "^",153				Eq => "==",154				Neq => "!=",155				And => "&&",156				Or => "||",157			}158		)159	}160}161162/// name, default value163#[cfg_attr(feature = "serialize", derive(Serialize))]164#[cfg_attr(feature = "deserialize", derive(Deserialize))]165#[derive(Debug, PartialEq, Trace)]166#[trivially_drop]167pub struct Param(pub IStr, pub Option<LocExpr>);168169/// Defined function parameters170#[cfg_attr(feature = "serialize", derive(Serialize))]171#[cfg_attr(feature = "deserialize", derive(Deserialize))]172#[derive(Debug, Clone, PartialEq)]173pub struct ParamsDesc(pub Rc<Vec<Param>>);174175/// Safety:176/// AST is acyclic, and there should be no gc pointers177unsafe impl Trace for ParamsDesc {178	unsafe_empty_trace!();179}180impl Finalize for ParamsDesc {}181182impl Deref for ParamsDesc {183	type Target = Vec<Param>;184	fn deref(&self) -> &Self::Target {185		&self.0186	}187}188189#[cfg_attr(feature = "serialize", derive(Serialize))]190#[cfg_attr(feature = "deserialize", derive(Deserialize))]191#[derive(Debug, PartialEq, Trace)]192#[trivially_drop]193pub struct Arg(pub Option<String>, pub LocExpr);194195#[cfg_attr(feature = "serialize", derive(Serialize))]196#[cfg_attr(feature = "deserialize", derive(Deserialize))]197#[derive(Debug, PartialEq, Trace)]198#[trivially_drop]199pub struct ArgsDesc(pub Vec<Arg>);200201impl Deref for ArgsDesc {202	type Target = Vec<Arg>;203	fn deref(&self) -> &Self::Target {204		&self.0205	}206}207208#[cfg_attr(feature = "serialize", derive(Serialize))]209#[cfg_attr(feature = "deserialize", derive(Deserialize))]210#[derive(Debug, Clone, PartialEq, Trace)]211#[trivially_drop]212pub struct BindSpec {213	pub name: IStr,214	pub params: Option<ParamsDesc>,215	pub value: LocExpr,216}217218#[cfg_attr(feature = "serialize", derive(Serialize))]219#[cfg_attr(feature = "deserialize", derive(Deserialize))]220#[derive(Debug, PartialEq, Trace)]221#[trivially_drop]222pub struct IfSpecData(pub LocExpr);223224#[cfg_attr(feature = "serialize", derive(Serialize))]225#[cfg_attr(feature = "deserialize", derive(Deserialize))]226#[derive(Debug, PartialEq, Trace)]227#[trivially_drop]228pub struct ForSpecData(pub IStr, pub LocExpr);229230#[cfg_attr(feature = "serialize", derive(Serialize))]231#[cfg_attr(feature = "deserialize", derive(Deserialize))]232#[derive(Debug, PartialEq, Trace)]233#[trivially_drop]234pub enum CompSpec {235	IfSpec(IfSpecData),236	ForSpec(ForSpecData),237}238239#[cfg_attr(feature = "serialize", derive(Serialize))]240#[cfg_attr(feature = "deserialize", derive(Deserialize))]241#[derive(Debug, PartialEq, Trace)]242#[trivially_drop]243pub struct ObjComp {244	pub pre_locals: Vec<BindSpec>,245	pub key: LocExpr,246	pub value: LocExpr,247	pub post_locals: Vec<BindSpec>,248	pub compspecs: Vec<CompSpec>,249}250251#[cfg_attr(feature = "serialize", derive(Serialize))]252#[cfg_attr(feature = "deserialize", derive(Deserialize))]253#[derive(Debug, PartialEq, Trace)]254#[trivially_drop]255pub enum ObjBody {256	MemberList(Vec<Member>),257	ObjComp(ObjComp),258}259260#[cfg_attr(feature = "serialize", derive(Serialize))]261#[cfg_attr(feature = "deserialize", derive(Deserialize))]262#[derive(Debug, PartialEq, Clone, Copy, Trace)]263#[trivially_drop]264pub enum LiteralType {265	This,266	Super,267	Dollar,268	Null,269	True,270	False,271}272273#[derive(Debug, PartialEq, Trace)]274#[trivially_drop]275pub struct SliceDesc {276	pub start: Option<LocExpr>,277	pub end: Option<LocExpr>,278	pub step: Option<LocExpr>,279}280281/// Syntax base282#[cfg_attr(feature = "serialize", derive(Serialize))]283#[cfg_attr(feature = "deserialize", derive(Deserialize))]284#[derive(Debug, PartialEq, Trace)]285#[trivially_drop]286pub enum Expr {287	Literal(LiteralType),288289	/// String value: "hello"290	Str(IStr),291	/// Number: 1, 2.0, 2e+20292	Num(f64),293	/// Variable name: test294	Var(IStr),295296	/// Array of expressions: [1, 2, "Hello"]297	Arr(Vec<LocExpr>),298	/// Array comprehension:299	/// ```jsonnet300	///  ingredients: [301	///    { kind: kind, qty: 4 / 3 }302	///    for kind in [303	///      'Honey Syrup',304	///      'Lemon Juice',305	///      'Farmers Gin',306	///    ]307	///  ],308	/// ```309	ArrComp(LocExpr, Vec<CompSpec>),310311	/// Object: {a: 2}312	Obj(ObjBody),313	/// Object extension: var1 {b: 2}314	ObjExtend(LocExpr, ObjBody),315316	/// (obj)317	Parened(LocExpr),318319	/// -2320	UnaryOp(UnaryOpType, LocExpr),321	/// 2 - 2322	BinaryOp(LocExpr, BinaryOpType, LocExpr),323	/// assert 2 == 2 : "Math is broken"324	AssertExpr(AssertStmt, LocExpr),325	/// local a = 2; { b: a }326	LocalExpr(Vec<BindSpec>, LocExpr),327328	/// import "hello"329	Import(PathBuf),330	/// importStr "file.txt"331	ImportStr(PathBuf),332	/// error "I'm broken"333	ErrorStmt(LocExpr),334	/// a(b, c)335	Apply(LocExpr, ArgsDesc, bool),336	/// a[b]337	Index(LocExpr, LocExpr),338	/// function(x) x339	Function(ParamsDesc, LocExpr),340	/// std.primitiveEquals341	Intrinsic(IStr),342	/// if true == false then 1 else 2343	IfElse {344		cond: IfSpecData,345		cond_then: LocExpr,346		cond_else: Option<LocExpr>,347	},348}349350/// file, begin offset, end offset351#[cfg_attr(feature = "serialize", derive(Serialize))]352#[cfg_attr(feature = "deserialize", derive(Deserialize))]353#[derive(Clone, PartialEq, Trace)]354#[trivially_drop]355pub struct ExprLocation(pub Rc<Path>, pub usize, pub usize);356357impl Debug for ExprLocation {358	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {359		write!(f, "{:?}:{:?}-{:?}", self.0, self.1, self.2)360	}361}362363/// Holds AST expression and its location in source file364#[cfg_attr(feature = "serialize", derive(Serialize))]365#[cfg_attr(feature = "deserialize", derive(Deserialize))]366#[derive(Clone, PartialEq)]367pub struct LocExpr(pub Rc<Expr>, pub Option<ExprLocation>);368/// Safety:369/// AST is acyclic, and there should be no gc pointers370unsafe impl Trace for LocExpr {371	unsafe_empty_trace!();372}373impl Finalize for LocExpr {}374375impl Debug for LocExpr {376	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {377		if f.alternate() {378			write!(f, "{:#?}", self.0)?;379		} else {380			write!(f, "{:?}", self.0)?;381		}382		if let Some(loc) = &self.1 {383			write!(f, " from {:?}", loc)?;384		}385		Ok(())386	}387}388389/// Creates LocExpr from Expr and ExprLocation components390#[macro_export]391macro_rules! loc_expr {392	($expr:expr, $need_loc:expr,($name:expr, $start:expr, $end:expr)) => {393		LocExpr(394			std::rc::Rc::new($expr),395			if $need_loc {396				Some(ExprLocation($name, $start, $end))397			} else {398				None399			},400		)401	};402}403404/// Creates LocExpr without location info405#[macro_export]406macro_rules! loc_expr_todo {407	($expr:expr) => {408		LocExpr(Rc::new($expr), None)409	};410}
after · crates/jrsonnet-parser/src/expr.rs
1use jrsonnet_gc::{unsafe_empty_trace, Finalize, Trace};2use jrsonnet_interner::IStr;3#[cfg(feature = "deserialize")]4use serde::Deserialize;5#[cfg(feature = "serialize")]6use serde::Serialize;7use std::{8	fmt::{Debug, Display},9	ops::Deref,10	path::{Path, PathBuf},11	rc::Rc,12};1314#[cfg_attr(feature = "serialize", derive(Serialize))]15#[cfg_attr(feature = "deserialize", derive(Deserialize))]16#[derive(Debug, PartialEq, Trace)]17#[trivially_drop]18pub enum FieldName {19	/// {fixed: 2}20	Fixed(IStr),21	/// {["dyn"+"amic"]: 3}22	Dyn(LocExpr),23}2425#[cfg_attr(feature = "serialize", derive(Serialize))]26#[cfg_attr(feature = "deserialize", derive(Deserialize))]27#[derive(Debug, Clone, Copy, PartialEq, Trace)]28#[trivially_drop]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 = "serialize", derive(Serialize))]45#[cfg_attr(feature = "deserialize", derive(Deserialize))]46#[derive(Clone, Debug, PartialEq, Trace)]47#[trivially_drop]48pub struct AssertStmt(pub LocExpr, pub Option<LocExpr>);4950#[cfg_attr(feature = "serialize", derive(Serialize))]51#[cfg_attr(feature = "deserialize", derive(Deserialize))]52#[derive(Debug, PartialEq, Trace)]53#[trivially_drop]54pub struct FieldMember {55	pub name: FieldName,56	pub plus: bool,57	pub params: Option<ParamsDesc>,58	pub visibility: Visibility,59	pub value: LocExpr,60}6162#[cfg_attr(feature = "serialize", derive(Serialize))]63#[cfg_attr(feature = "deserialize", derive(Deserialize))]64#[derive(Debug, PartialEq, Trace)]65#[trivially_drop]66pub enum Member {67	Field(FieldMember),68	BindStmt(BindSpec),69	AssertStmt(AssertStmt),70}7172#[cfg_attr(feature = "serialize", derive(Serialize))]73#[cfg_attr(feature = "deserialize", derive(Deserialize))]74#[derive(Debug, Clone, Copy, PartialEq, Trace)]75#[trivially_drop]76pub enum UnaryOpType {77	Plus,78	Minus,79	BitNot,80	Not,81}8283impl Display for UnaryOpType {84	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {85		use UnaryOpType::*;86		write!(87			f,88			"{}",89			match self {90				Plus => "+",91				Minus => "-",92				BitNot => "~",93				Not => "!",94			}95		)96	}97}9899#[cfg_attr(feature = "serialize", derive(Serialize))]100#[cfg_attr(feature = "deserialize", derive(Deserialize))]101#[derive(Debug, Clone, Copy, PartialEq, Trace)]102#[trivially_drop]103pub enum BinaryOpType {104	Mul,105	Div,106107	/// Implemented as intrinsic, put here for completeness108	Mod,109110	Add,111	Sub,112113	Lhs,114	Rhs,115116	Lt,117	Gt,118	Lte,119	Gte,120121	BitAnd,122	BitOr,123	BitXor,124125	Eq,126	Neq,127128	And,129	Or,130131	// Equialent to std.objectHasEx(a, b, true)132	In,133}134135impl Display for BinaryOpType {136	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {137		use BinaryOpType::*;138		write!(139			f,140			"{}",141			match self {142				Mul => "*",143				Div => "/",144				Mod => "%",145				Add => "+",146				Sub => "-",147				Lhs => "<<",148				Rhs => ">>",149				Lt => "<",150				Gt => ">",151				Lte => "<=",152				Gte => ">=",153				BitAnd => "&",154				BitOr => "|",155				BitXor => "^",156				Eq => "==",157				Neq => "!=",158				And => "&&",159				Or => "||",160				In => "in",161			}162		)163	}164}165166/// name, default value167#[cfg_attr(feature = "serialize", derive(Serialize))]168#[cfg_attr(feature = "deserialize", derive(Deserialize))]169#[derive(Debug, PartialEq, Trace)]170#[trivially_drop]171pub struct Param(pub IStr, pub Option<LocExpr>);172173/// Defined function parameters174#[cfg_attr(feature = "serialize", derive(Serialize))]175#[cfg_attr(feature = "deserialize", derive(Deserialize))]176#[derive(Debug, Clone, PartialEq)]177pub struct ParamsDesc(pub Rc<Vec<Param>>);178179/// Safety:180/// AST is acyclic, and there should be no gc pointers181unsafe impl Trace for ParamsDesc {182	unsafe_empty_trace!();183}184impl Finalize for ParamsDesc {}185186impl Deref for ParamsDesc {187	type Target = Vec<Param>;188	fn deref(&self) -> &Self::Target {189		&self.0190	}191}192193#[cfg_attr(feature = "serialize", derive(Serialize))]194#[cfg_attr(feature = "deserialize", derive(Deserialize))]195#[derive(Debug, PartialEq, Trace)]196#[trivially_drop]197pub struct Arg(pub Option<String>, pub LocExpr);198199#[cfg_attr(feature = "serialize", derive(Serialize))]200#[cfg_attr(feature = "deserialize", derive(Deserialize))]201#[derive(Debug, PartialEq, Trace)]202#[trivially_drop]203pub struct ArgsDesc(pub Vec<Arg>);204205impl Deref for ArgsDesc {206	type Target = Vec<Arg>;207	fn deref(&self) -> &Self::Target {208		&self.0209	}210}211212#[cfg_attr(feature = "serialize", derive(Serialize))]213#[cfg_attr(feature = "deserialize", derive(Deserialize))]214#[derive(Debug, Clone, PartialEq, Trace)]215#[trivially_drop]216pub struct BindSpec {217	pub name: IStr,218	pub params: Option<ParamsDesc>,219	pub value: LocExpr,220}221222#[cfg_attr(feature = "serialize", derive(Serialize))]223#[cfg_attr(feature = "deserialize", derive(Deserialize))]224#[derive(Debug, PartialEq, Trace)]225#[trivially_drop]226pub struct IfSpecData(pub LocExpr);227228#[cfg_attr(feature = "serialize", derive(Serialize))]229#[cfg_attr(feature = "deserialize", derive(Deserialize))]230#[derive(Debug, PartialEq, Trace)]231#[trivially_drop]232pub struct ForSpecData(pub IStr, pub LocExpr);233234#[cfg_attr(feature = "serialize", derive(Serialize))]235#[cfg_attr(feature = "deserialize", derive(Deserialize))]236#[derive(Debug, PartialEq, Trace)]237#[trivially_drop]238pub enum CompSpec {239	IfSpec(IfSpecData),240	ForSpec(ForSpecData),241}242243#[cfg_attr(feature = "serialize", derive(Serialize))]244#[cfg_attr(feature = "deserialize", derive(Deserialize))]245#[derive(Debug, PartialEq, Trace)]246#[trivially_drop]247pub struct ObjComp {248	pub pre_locals: Vec<BindSpec>,249	pub key: LocExpr,250	pub value: LocExpr,251	pub post_locals: Vec<BindSpec>,252	pub compspecs: Vec<CompSpec>,253}254255#[cfg_attr(feature = "serialize", derive(Serialize))]256#[cfg_attr(feature = "deserialize", derive(Deserialize))]257#[derive(Debug, PartialEq, Trace)]258#[trivially_drop]259pub enum ObjBody {260	MemberList(Vec<Member>),261	ObjComp(ObjComp),262}263264#[cfg_attr(feature = "serialize", derive(Serialize))]265#[cfg_attr(feature = "deserialize", derive(Deserialize))]266#[derive(Debug, PartialEq, Clone, Copy, Trace)]267#[trivially_drop]268pub enum LiteralType {269	This,270	Super,271	Dollar,272	Null,273	True,274	False,275}276277#[derive(Debug, PartialEq, Trace)]278#[trivially_drop]279pub struct SliceDesc {280	pub start: Option<LocExpr>,281	pub end: Option<LocExpr>,282	pub step: Option<LocExpr>,283}284285/// Syntax base286#[cfg_attr(feature = "serialize", derive(Serialize))]287#[cfg_attr(feature = "deserialize", derive(Deserialize))]288#[derive(Debug, PartialEq, Trace)]289#[trivially_drop]290pub enum Expr {291	Literal(LiteralType),292293	/// String value: "hello"294	Str(IStr),295	/// Number: 1, 2.0, 2e+20296	Num(f64),297	/// Variable name: test298	Var(IStr),299300	/// Array of expressions: [1, 2, "Hello"]301	Arr(Vec<LocExpr>),302	/// Array comprehension:303	/// ```jsonnet304	///  ingredients: [305	///    { kind: kind, qty: 4 / 3 }306	///    for kind in [307	///      'Honey Syrup',308	///      'Lemon Juice',309	///      'Farmers Gin',310	///    ]311	///  ],312	/// ```313	ArrComp(LocExpr, Vec<CompSpec>),314315	/// Object: {a: 2}316	Obj(ObjBody),317	/// Object extension: var1 {b: 2}318	ObjExtend(LocExpr, ObjBody),319320	/// (obj)321	Parened(LocExpr),322323	/// -2324	UnaryOp(UnaryOpType, LocExpr),325	/// 2 - 2326	BinaryOp(LocExpr, BinaryOpType, LocExpr),327	/// assert 2 == 2 : "Math is broken"328	AssertExpr(AssertStmt, LocExpr),329	/// local a = 2; { b: a }330	LocalExpr(Vec<BindSpec>, LocExpr),331332	/// import "hello"333	Import(PathBuf),334	/// importStr "file.txt"335	ImportStr(PathBuf),336	/// error "I'm broken"337	ErrorStmt(LocExpr),338	/// a(b, c)339	Apply(LocExpr, ArgsDesc, bool),340	/// a[b]341	Index(LocExpr, LocExpr),342	/// function(x) x343	Function(ParamsDesc, LocExpr),344	/// std.primitiveEquals345	Intrinsic(IStr),346	/// if true == false then 1 else 2347	IfElse {348		cond: IfSpecData,349		cond_then: LocExpr,350		cond_else: Option<LocExpr>,351	},352}353354/// file, begin offset, end offset355#[cfg_attr(feature = "serialize", derive(Serialize))]356#[cfg_attr(feature = "deserialize", derive(Deserialize))]357#[derive(Clone, PartialEq, Trace)]358#[trivially_drop]359pub struct ExprLocation(pub Rc<Path>, pub usize, pub usize);360361impl Debug for ExprLocation {362	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {363		write!(f, "{:?}:{:?}-{:?}", self.0, self.1, self.2)364	}365}366367/// Holds AST expression and its location in source file368#[cfg_attr(feature = "serialize", derive(Serialize))]369#[cfg_attr(feature = "deserialize", derive(Deserialize))]370#[derive(Clone, PartialEq)]371pub struct LocExpr(pub Rc<Expr>, pub Option<ExprLocation>);372/// Safety:373/// AST is acyclic, and there should be no gc pointers374unsafe impl Trace for LocExpr {375	unsafe_empty_trace!();376}377impl Finalize for LocExpr {}378379impl Debug for LocExpr {380	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {381		if f.alternate() {382			write!(f, "{:#?}", self.0)?;383		} else {384			write!(f, "{:?}", self.0)?;385		}386		if let Some(loc) = &self.1 {387			write!(f, " from {:?}", loc)?;388		}389		Ok(())390	}391}392393/// Creates LocExpr from Expr and ExprLocation components394#[macro_export]395macro_rules! loc_expr {396	($expr:expr, $need_loc:expr,($name:expr, $start:expr, $end:expr)) => {397		LocExpr(398			std::rc::Rc::new($expr),399			if $need_loc {400				Some(ExprLocation($name, $start, $end))401			} else {402				None403			},404		)405	};406}407408/// Creates LocExpr without location info409#[macro_export]410macro_rules! loc_expr_todo {411	($expr:expr) => {412		LocExpr(Rc::new($expr), None)413	};414}
modifiedcrates/jrsonnet-parser/src/lib.rsdiffbeforeafterboth
--- a/crates/jrsonnet-parser/src/lib.rs
+++ b/crates/jrsonnet-parser/src/lib.rs
@@ -217,38 +217,37 @@
 		rule unaryop(x: rule<()>) -> ()
 			= quiet!{ x() } / expected!("<unary op>")
 
+
+		use BinaryOpType::*;
 		rule expr(s: &ParserSettings) -> LocExpr
 			= start:position!() a:precedence! {
-				a:(@) _ binop(<"||">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Or, b))}
+				a:(@) _ binop(<"||">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, Or, b))}
 				--
-				a:(@) _ binop(<"&&">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::And, b))}
+				a:(@) _ binop(<"&&">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, And, b))}
 				--
-				a:(@) _ binop(<"|">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::BitOr, b))}
+				a:(@) _ binop(<"|">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BitOr, b))}
 				--
-				a:@ _ binop(<"^">) _ b:(@) {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::BitXor, b))}
+				a:@ _ binop(<"^">) _ b:(@) {loc_expr_todo!(Expr::BinaryOp(a, BitXor, b))}
 				--
-				a:(@) _ binop(<"&">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::BitAnd, b))}
+				a:(@) _ binop(<"&">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BitAnd, b))}
 				--
-				a:(@) _ binop(<"==">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Eq, b))}
-				a:(@) _ binop(<"!=">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Neq, b))}
+				a:(@) _ binop(<"==">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, Eq, b))}
+				a:(@) _ binop(<"!=">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, Neq, b))}
 				--
-				a:(@) _ binop(<"<">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Lt, b))}
-				a:(@) _ binop(<">">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Gt, b))}
-				a:(@) _ binop(<"<=">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Lte, b))}
-				a:(@) _ binop(<">=">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Gte, b))}
-				a:(@) _ binop(<keyword("in")>) _ b:@ {loc_expr_todo!(Expr::Apply(
-					el!(Expr::Intrinsic("objectHasEx".into())), ArgsDesc(vec![Arg(None, b), Arg(None, a), Arg(None, el!(Expr::Literal(LiteralType::True)))]),
-					true
-				))}
+				a:(@) _ binop(<"<">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, Lt, b))}
+				a:(@) _ binop(<">">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, Gt, b))}
+				a:(@) _ binop(<"<=">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, Lte, b))}
+				a:(@) _ binop(<">=">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, Gte, b))}
+				a:(@) _ binop(<keyword("in")>) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, In, b))}
 				--
-				a:(@) _ binop(<"<<">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Lhs, b))}
-				a:(@) _ binop(<">>">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Rhs, b))}
+				a:(@) _ binop(<"<<">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, Lhs, b))}
+				a:(@) _ binop(<">>">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, Rhs, b))}
 				--
-				a:(@) _ binop(<"+">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Add, b))}
-				a:(@) _ binop(<"-">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Sub, b))}
+				a:(@) _ binop(<"+">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, Add, b))}
+				a:(@) _ binop(<"-">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, Sub, b))}
 				--
-				a:(@) _ binop(<"*">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Mul, b))}
-				a:(@) _ binop(<"/">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Div, b))}
+				a:(@) _ binop(<"*">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, Mul, b))}
+				a:(@) _ binop(<"/">) _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, Div, b))}
 				a:(@) _ binop(<"%">) _ b:@ {loc_expr_todo!(Expr::Apply(
 					el!(Expr::Intrinsic("mod".into())), ArgsDesc(vec![Arg(None, a), Arg(None, b)]),
 					false
@@ -306,6 +305,7 @@
 	use super::{expr::*, parse};
 	use crate::ParserSettings;
 	use std::path::PathBuf;
+	use BinaryOpType::*;
 
 	macro_rules! parse {
 		($s:expr) => {
@@ -326,10 +326,10 @@
 		pub fn basic_math() -> LocExpr {
 			el!(Expr::BinaryOp(
 				el!(Expr::Num(2.0)),
-				BinaryOpType::Add,
+				Add,
 				el!(Expr::BinaryOp(
 					el!(Expr::Num(2.0)),
-					BinaryOpType::Mul,
+					Mul,
 					el!(Expr::Num(2.0)),
 				)),
 			))
@@ -417,10 +417,10 @@
 			parse!("2+2*2"),
 			el!(Expr::BinaryOp(
 				el!(Expr::Num(2.0)),
-				BinaryOpType::Add,
+				Add,
 				el!(Expr::BinaryOp(
 					el!(Expr::Num(2.0)),
-					BinaryOpType::Mul,
+					Mul,
 					el!(Expr::Num(2.0))
 				))
 			))
@@ -438,7 +438,7 @@
 			parse!("2+(2+2*2)"),
 			el!(Expr::BinaryOp(
 				el!(Expr::Num(2.0)),
-				BinaryOpType::Add,
+				Add,
 				el!(Expr::Parened(expressions::basic_math())),
 			))
 		);
@@ -451,10 +451,10 @@
 			parse!("2//comment\n+//comment\n3/*test*/*/*test*/4"),
 			el!(Expr::BinaryOp(
 				el!(Expr::Num(2.0)),
-				BinaryOpType::Add,
+				Add,
 				el!(Expr::BinaryOp(
 					el!(Expr::Num(3.0)),
-					BinaryOpType::Mul,
+					Mul,
 					el!(Expr::Num(4.0))
 				))
 			))
@@ -468,7 +468,7 @@
 			parse!("2/*\\*/+*/ - 22"),
 			el!(Expr::BinaryOp(
 				el!(Expr::Num(2.0)),
-				BinaryOpType::Sub,
+				Sub,
 				el!(Expr::Num(22.0))
 			))
 		);
@@ -520,7 +520,7 @@
 			parse!("!a && !b"),
 			el!(BinaryOp(
 				el!(UnaryOp(UnaryOpType::Not, el!(Var("a".into())))),
-				BinaryOpType::And,
+				And,
 				el!(UnaryOp(UnaryOpType::Not, el!(Var("b".into()))))
 			))
 		);
@@ -533,7 +533,7 @@
 			parse!("!a / !b"),
 			el!(BinaryOp(
 				el!(UnaryOp(UnaryOpType::Not, el!(Var("a".into())))),
-				BinaryOpType::Div,
+				Div,
 				el!(UnaryOp(UnaryOpType::Not, el!(Var("b".into()))))
 			))
 		);