difftreelog
feat support legacy std.thisFile
in: master
5 files changed
crates/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>),
crates/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)?
crates/jrsonnet-parser/src/expr.rsdiffbeforeafterboth1use 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}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}crates/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)
crates/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),