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

difftreelog

feat support legacy std.thisFile

Yaroslav Bolyukin2022-04-22parent: #e082575.patch.diff
in: master

5 files changed

modifiedcrates/jrsonnet-evaluator/src/error.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/error.rs
+++ b/crates/jrsonnet-evaluator/src/error.rs
@@ -140,6 +140,11 @@
 	#[error("sort error: {0}")]
 	Sort(#[from] SortError),
 
+	/// Thrown as error, as this is legacy feature, and error here
+	/// is acceptable for defeating object field cache
+	#[error("should not reach outside: std.thisFile")]
+	MagicThisFileUsed,
+
 	#[cfg(feature = "anyhow-error")]
 	#[error(transparent)]
 	Other(Rc<anyhow::Error>),
modifiedcrates/jrsonnet-evaluator/src/evaluate/mod.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/evaluate/mod.rs
+++ b/crates/jrsonnet-evaluator/src/evaluate/mod.rs
@@ -568,12 +568,13 @@
 				(Val::Obj(v), Val::Str(key)) => s.push(
 					CallLocation::new(loc),
 					|| format!("field <{}> access", key),
-					|| {
-						if let Some(v) = v.get(s.clone(), key.clone())? {
-							Ok(v)
-						} else {
-							throw!(NoSuchField(key.clone()))
+					|| match v.get(s.clone(), key.clone()) {
+						Ok(Some(v)) => Ok(v),
+						Ok(None) => throw!(NoSuchField(key.clone())),
+						Err(e) if matches!(e.error(), MagicThisFileUsed) => {
+							Ok(Val::Str(loc.0.to_string_lossy().into()))
 						}
+						Err(e) => Err(e),
 					},
 				)?,
 				(Val::Obj(_), n) => throw!(ValueIndexMustBeTypeGot(
@@ -674,6 +675,7 @@
 				.with(|b| b.get(name).copied())
 				.ok_or_else(|| IntrinsicNotFound(name.clone()))?,
 		)),
+		IntrinsicThisFile => return Err(MagicThisFileUsed.into()),
 		AssertExpr(assert, returned) => {
 			evaluate_assert(s.clone(), ctx.clone(), assert)?;
 			evaluate(s, ctx, returned)?
modifiedcrates/jrsonnet-parser/src/expr.rsdiffbeforeafterboth
before · crates/jrsonnet-parser/src/expr.rs
1use std::{2	fmt::{Debug, Display},3	ops::Deref,4	path::{Path, PathBuf},5	rc::Rc,6};78use gcmodule::Trace;9use jrsonnet_interner::IStr;10#[cfg(feature = "serde")]11use serde::{Deserialize, Serialize};1213#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]14#[derive(Debug, PartialEq, Trace)]15pub enum FieldName {16	/// {fixed: 2}17	Fixed(IStr),18	/// {["dyn"+"amic"]: 3}19	Dyn(LocExpr),20}2122#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]23#[derive(Debug, Clone, Copy, PartialEq, Trace)]24pub enum Visibility {25	/// :26	Normal,27	/// ::28	Hidden,29	/// :::30	Unhide,31}3233impl Visibility {34	pub fn is_visible(&self) -> bool {35		matches!(self, Self::Normal | Self::Unhide)36	}37}3839#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]40#[derive(Clone, Debug, PartialEq, Trace)]41pub struct AssertStmt(pub LocExpr, pub Option<LocExpr>);4243#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]44#[derive(Debug, PartialEq, Trace)]45pub struct FieldMember {46	pub name: FieldName,47	pub plus: bool,48	pub params: Option<ParamsDesc>,49	pub visibility: Visibility,50	pub value: LocExpr,51}5253#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]54#[derive(Debug, PartialEq, Trace)]55pub enum Member {56	Field(FieldMember),57	BindStmt(BindSpec),58	AssertStmt(AssertStmt),59}6061#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]62#[derive(Debug, Clone, Copy, PartialEq, Trace)]63pub enum UnaryOpType {64	Plus,65	Minus,66	BitNot,67	Not,68}6970impl Display for UnaryOpType {71	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {72		use UnaryOpType::*;73		write!(74			f,75			"{}",76			match self {77				Plus => "+",78				Minus => "-",79				BitNot => "~",80				Not => "!",81			}82		)83	}84}8586#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]87#[derive(Debug, Clone, Copy, PartialEq, Trace)]88pub enum BinaryOpType {89	Mul,90	Div,9192	/// Implemented as intrinsic, put here for completeness93	Mod,9495	Add,96	Sub,9798	Lhs,99	Rhs,100101	Lt,102	Gt,103	Lte,104	Gte,105106	BitAnd,107	BitOr,108	BitXor,109110	Eq,111	Neq,112113	And,114	Or,115116	// Equialent to std.objectHasEx(a, b, true)117	In,118}119120impl Display for BinaryOpType {121	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {122		use BinaryOpType::*;123		write!(124			f,125			"{}",126			match self {127				Mul => "*",128				Div => "/",129				Mod => "%",130				Add => "+",131				Sub => "-",132				Lhs => "<<",133				Rhs => ">>",134				Lt => "<",135				Gt => ">",136				Lte => "<=",137				Gte => ">=",138				BitAnd => "&",139				BitOr => "|",140				BitXor => "^",141				Eq => "==",142				Neq => "!=",143				And => "&&",144				Or => "||",145				In => "in",146			}147		)148	}149}150151/// name, default value152#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]153#[derive(Debug, PartialEq, Trace)]154pub struct Param(pub IStr, pub Option<LocExpr>);155156/// Defined function parameters157#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]158#[derive(Debug, Clone, PartialEq, Trace)]159pub struct ParamsDesc(pub Rc<Vec<Param>>);160161impl Deref for ParamsDesc {162	type Target = Vec<Param>;163	fn deref(&self) -> &Self::Target {164		&self.0165	}166}167168#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]169#[derive(Debug, PartialEq, Trace)]170pub struct ArgsDesc {171	pub unnamed: Vec<LocExpr>,172	pub named: Vec<(IStr, LocExpr)>,173}174impl ArgsDesc {175	pub fn new(unnamed: Vec<LocExpr>, named: Vec<(IStr, LocExpr)>) -> Self {176		Self { unnamed, named }177	}178}179180#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]181#[derive(Debug, Clone, PartialEq, Trace)]182pub struct BindSpec {183	pub name: IStr,184	pub params: Option<ParamsDesc>,185	pub value: LocExpr,186}187188#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]189#[derive(Debug, PartialEq, Trace)]190pub struct IfSpecData(pub LocExpr);191192#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]193#[derive(Debug, PartialEq, Trace)]194pub struct ForSpecData(pub IStr, pub LocExpr);195196#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]197#[derive(Debug, PartialEq, Trace)]198pub enum CompSpec {199	IfSpec(IfSpecData),200	ForSpec(ForSpecData),201}202203#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]204#[derive(Debug, PartialEq, Trace)]205pub struct ObjComp {206	pub pre_locals: Vec<BindSpec>,207	pub key: LocExpr,208	pub plus: bool,209	pub value: LocExpr,210	pub post_locals: Vec<BindSpec>,211	pub compspecs: Vec<CompSpec>,212}213214#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]215#[derive(Debug, PartialEq, Trace)]216pub enum ObjBody {217	MemberList(Vec<Member>),218	ObjComp(ObjComp),219}220221#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]222#[derive(Debug, PartialEq, Clone, Copy, Trace)]223pub enum LiteralType {224	This,225	Super,226	Dollar,227	Null,228	True,229	False,230}231232#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]233#[derive(Debug, PartialEq, Trace)]234pub struct SliceDesc {235	pub start: Option<LocExpr>,236	pub end: Option<LocExpr>,237	pub step: Option<LocExpr>,238}239240/// Syntax base241#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]242#[derive(Debug, PartialEq, Trace)]243pub enum Expr {244	Literal(LiteralType),245246	/// String value: "hello"247	Str(IStr),248	/// Number: 1, 2.0, 2e+20249	Num(f64),250	/// Variable name: test251	Var(IStr),252253	/// Array of expressions: [1, 2, "Hello"]254	Arr(Vec<LocExpr>),255	/// Array comprehension:256	/// ```jsonnet257	///  ingredients: [258	///    { kind: kind, qty: 4 / 3 }259	///    for kind in [260	///      'Honey Syrup',261	///      'Lemon Juice',262	///      'Farmers Gin',263	///    ]264	///  ],265	/// ```266	ArrComp(LocExpr, Vec<CompSpec>),267268	/// Object: {a: 2}269	Obj(ObjBody),270	/// Object extension: var1 {b: 2}271	ObjExtend(LocExpr, ObjBody),272273	/// (obj)274	Parened(LocExpr),275276	/// -2277	UnaryOp(UnaryOpType, LocExpr),278	/// 2 - 2279	BinaryOp(LocExpr, BinaryOpType, LocExpr),280	/// assert 2 == 2 : "Math is broken"281	AssertExpr(AssertStmt, LocExpr),282	/// local a = 2; { b: a }283	LocalExpr(Vec<BindSpec>, LocExpr),284285	/// import "hello"286	Import(PathBuf),287	/// importStr "file.txt"288	ImportStr(PathBuf),289	/// importBin "file.txt"290	ImportBin(PathBuf),291	/// error "I'm broken"292	ErrorStmt(LocExpr),293	/// a(b, c)294	Apply(LocExpr, ArgsDesc, bool),295	/// a[b]296	Index(LocExpr, LocExpr),297	/// function(x) x298	Function(ParamsDesc, LocExpr),299	/// std.primitiveEquals300	Intrinsic(IStr),301	/// if true == false then 1 else 2302	IfElse {303		cond: IfSpecData,304		cond_then: LocExpr,305		cond_else: Option<LocExpr>,306	},307	Slice(LocExpr, SliceDesc),308}309310/// file, begin offset, end offset311#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]312#[derive(Clone, PartialEq, Trace)]313#[skip_trace]314pub struct ExprLocation(pub Rc<Path>, pub usize, pub usize);315impl ExprLocation {316	pub fn belongs_to(&self, other: &ExprLocation) -> bool {317		other.0 == self.0 && other.1 <= self.1 && other.2 >= self.2318	}319}320321impl Debug for ExprLocation {322	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {323		write!(f, "{:?}:{:?}-{:?}", self.0, self.1, self.2)324	}325}326327/// Holds AST expression and its location in source file328#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]329#[derive(Clone, PartialEq, Trace)]330pub struct LocExpr(pub Rc<Expr>, pub ExprLocation);331332impl Debug for LocExpr {333	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {334		if f.alternate() {335			write!(f, "{:#?}", self.0)?;336		} else {337			write!(f, "{:?}", self.0)?;338		}339		write!(f, " from {:?}", self.1)?;340		Ok(())341	}342}
after · crates/jrsonnet-parser/src/expr.rs
1use std::{2	fmt::{Debug, Display},3	ops::Deref,4	path::{Path, PathBuf},5	rc::Rc,6};78use gcmodule::Trace;9use jrsonnet_interner::IStr;10#[cfg(feature = "serde")]11use serde::{Deserialize, Serialize};1213#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]14#[derive(Debug, PartialEq, Trace)]15pub enum FieldName {16	/// {fixed: 2}17	Fixed(IStr),18	/// {["dyn"+"amic"]: 3}19	Dyn(LocExpr),20}2122#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]23#[derive(Debug, Clone, Copy, PartialEq, Trace)]24pub enum Visibility {25	/// :26	Normal,27	/// ::28	Hidden,29	/// :::30	Unhide,31}3233impl Visibility {34	pub fn is_visible(&self) -> bool {35		matches!(self, Self::Normal | Self::Unhide)36	}37}3839#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]40#[derive(Clone, Debug, PartialEq, Trace)]41pub struct AssertStmt(pub LocExpr, pub Option<LocExpr>);4243#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]44#[derive(Debug, PartialEq, Trace)]45pub struct FieldMember {46	pub name: FieldName,47	pub plus: bool,48	pub params: Option<ParamsDesc>,49	pub visibility: Visibility,50	pub value: LocExpr,51}5253#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]54#[derive(Debug, PartialEq, Trace)]55pub enum Member {56	Field(FieldMember),57	BindStmt(BindSpec),58	AssertStmt(AssertStmt),59}6061#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]62#[derive(Debug, Clone, Copy, PartialEq, Trace)]63pub enum UnaryOpType {64	Plus,65	Minus,66	BitNot,67	Not,68}6970impl Display for UnaryOpType {71	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {72		use UnaryOpType::*;73		write!(74			f,75			"{}",76			match self {77				Plus => "+",78				Minus => "-",79				BitNot => "~",80				Not => "!",81			}82		)83	}84}8586#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]87#[derive(Debug, Clone, Copy, PartialEq, Trace)]88pub enum BinaryOpType {89	Mul,90	Div,9192	/// Implemented as intrinsic, put here for completeness93	Mod,9495	Add,96	Sub,9798	Lhs,99	Rhs,100101	Lt,102	Gt,103	Lte,104	Gte,105106	BitAnd,107	BitOr,108	BitXor,109110	Eq,111	Neq,112113	And,114	Or,115116	// Equialent to std.objectHasEx(a, b, true)117	In,118}119120impl Display for BinaryOpType {121	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {122		use BinaryOpType::*;123		write!(124			f,125			"{}",126			match self {127				Mul => "*",128				Div => "/",129				Mod => "%",130				Add => "+",131				Sub => "-",132				Lhs => "<<",133				Rhs => ">>",134				Lt => "<",135				Gt => ">",136				Lte => "<=",137				Gte => ">=",138				BitAnd => "&",139				BitOr => "|",140				BitXor => "^",141				Eq => "==",142				Neq => "!=",143				And => "&&",144				Or => "||",145				In => "in",146			}147		)148	}149}150151/// name, default value152#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]153#[derive(Debug, PartialEq, Trace)]154pub struct Param(pub IStr, pub Option<LocExpr>);155156/// Defined function parameters157#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]158#[derive(Debug, Clone, PartialEq, Trace)]159pub struct ParamsDesc(pub Rc<Vec<Param>>);160161impl Deref for ParamsDesc {162	type Target = Vec<Param>;163	fn deref(&self) -> &Self::Target {164		&self.0165	}166}167168#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]169#[derive(Debug, PartialEq, Trace)]170pub struct ArgsDesc {171	pub unnamed: Vec<LocExpr>,172	pub named: Vec<(IStr, LocExpr)>,173}174impl ArgsDesc {175	pub fn new(unnamed: Vec<LocExpr>, named: Vec<(IStr, LocExpr)>) -> Self {176		Self { unnamed, named }177	}178}179180#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]181#[derive(Debug, Clone, PartialEq, Trace)]182pub struct BindSpec {183	pub name: IStr,184	pub params: Option<ParamsDesc>,185	pub value: LocExpr,186}187188#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]189#[derive(Debug, PartialEq, Trace)]190pub struct IfSpecData(pub LocExpr);191192#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]193#[derive(Debug, PartialEq, Trace)]194pub struct ForSpecData(pub IStr, pub LocExpr);195196#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]197#[derive(Debug, PartialEq, Trace)]198pub enum CompSpec {199	IfSpec(IfSpecData),200	ForSpec(ForSpecData),201}202203#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]204#[derive(Debug, PartialEq, Trace)]205pub struct ObjComp {206	pub pre_locals: Vec<BindSpec>,207	pub key: LocExpr,208	pub plus: bool,209	pub value: LocExpr,210	pub post_locals: Vec<BindSpec>,211	pub compspecs: Vec<CompSpec>,212}213214#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]215#[derive(Debug, PartialEq, Trace)]216pub enum ObjBody {217	MemberList(Vec<Member>),218	ObjComp(ObjComp),219}220221#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]222#[derive(Debug, PartialEq, Clone, Copy, Trace)]223pub enum LiteralType {224	This,225	Super,226	Dollar,227	Null,228	True,229	False,230}231232#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]233#[derive(Debug, PartialEq, Trace)]234pub struct SliceDesc {235	pub start: Option<LocExpr>,236	pub end: Option<LocExpr>,237	pub step: Option<LocExpr>,238}239240/// Syntax base241#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]242#[derive(Debug, PartialEq, Trace)]243pub enum Expr {244	Literal(LiteralType),245246	/// String value: "hello"247	Str(IStr),248	/// Number: 1, 2.0, 2e+20249	Num(f64),250	/// Variable name: test251	Var(IStr),252253	/// Array of expressions: [1, 2, "Hello"]254	Arr(Vec<LocExpr>),255	/// Array comprehension:256	/// ```jsonnet257	///  ingredients: [258	///    { kind: kind, qty: 4 / 3 }259	///    for kind in [260	///      'Honey Syrup',261	///      'Lemon Juice',262	///      'Farmers Gin',263	///    ]264	///  ],265	/// ```266	ArrComp(LocExpr, Vec<CompSpec>),267268	/// Object: {a: 2}269	Obj(ObjBody),270	/// Object extension: var1 {b: 2}271	ObjExtend(LocExpr, ObjBody),272273	/// (obj)274	Parened(LocExpr),275276	/// -2277	UnaryOp(UnaryOpType, LocExpr),278	/// 2 - 2279	BinaryOp(LocExpr, BinaryOpType, LocExpr),280	/// assert 2 == 2 : "Math is broken"281	AssertExpr(AssertStmt, LocExpr),282	/// local a = 2; { b: a }283	LocalExpr(Vec<BindSpec>, LocExpr),284285	/// import "hello"286	Import(PathBuf),287	/// importStr "file.txt"288	ImportStr(PathBuf),289	/// importBin "file.txt"290	ImportBin(PathBuf),291	/// error "I'm broken"292	ErrorStmt(LocExpr),293	/// a(b, c)294	Apply(LocExpr, ArgsDesc, bool),295	/// a[b]296	Index(LocExpr, LocExpr),297	/// function(x) x298	Function(ParamsDesc, LocExpr),299	/// std.thisFile300	IntrinsicThisFile,301	/// std.primitiveEquals302	Intrinsic(IStr),303	/// if true == false then 1 else 2304	IfElse {305		cond: IfSpecData,306		cond_then: LocExpr,307		cond_else: Option<LocExpr>,308	},309	Slice(LocExpr, SliceDesc),310}311312/// file, begin offset, end offset313#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]314#[derive(Clone, PartialEq, Trace)]315#[skip_trace]316pub struct ExprLocation(pub Rc<Path>, pub usize, pub usize);317impl ExprLocation {318	pub fn belongs_to(&self, other: &ExprLocation) -> bool {319		other.0 == self.0 && other.1 <= self.1 && other.2 >= self.2320	}321}322323impl Debug for ExprLocation {324	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {325		write!(f, "{:?}:{:?}-{:?}", self.0, self.1, self.2)326	}327}328329/// Holds AST expression and its location in source file330#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]331#[derive(Clone, PartialEq, Trace)]332pub struct LocExpr(pub Rc<Expr>, pub ExprLocation);333334impl Debug for LocExpr {335	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {336		if f.alternate() {337			write!(f, "{:#?}", self.0)?;338		} else {339			write!(f, "{:?}", self.0)?;340		}341		write!(f, " from {:?}", self.1)?;342		Ok(())343	}344}
modifiedcrates/jrsonnet-parser/src/lib.rsdiffbeforeafterboth
--- a/crates/jrsonnet-parser/src/lib.rs
+++ b/crates/jrsonnet-parser/src/lib.rs
@@ -210,6 +210,7 @@
 		pub rule expr_basic(s: &ParserSettings) -> Expr
 			= literal(s)
 
+			/ quiet!{"$intrinsicThisFile" {Expr::IntrinsicThisFile}}
 			/ quiet!{"$intrinsic(" name:$(id()) ")" {Expr::Intrinsic(name.into())}}
 
 			/ string_expr(s) / number_expr(s)
modifiedcrates/jrsonnet-stdlib/src/std.jsonnetdiffbeforeafterboth
--- a/crates/jrsonnet-stdlib/src/std.jsonnet
+++ b/crates/jrsonnet-stdlib/src/std.jsonnet
@@ -2,6 +2,9 @@
   local std = self,
   local id = std.id,
 
+  # Magic legacy field
+  thisFile:: $intrinsicThisFile,
+
   # Those functions aren't normally located in stdlib
   length:: $intrinsic(length),
   type:: $intrinsic(type),