difftreelog
Add location info to all sub-expressions
in: master
2 files changed
crates/jrsonnet-parser/src/expr.rsdiffbeforeafterboth1use 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 ArgsDesc {198 pub unnamed: Vec<LocExpr>,199 pub named: Vec<(IStr, LocExpr)>,200}201impl ArgsDesc {202 pub fn new(unnamed: Vec<LocExpr>, named: Vec<(IStr, LocExpr)>) -> Self {203 Self { unnamed, named }204 }205}206207#[cfg_attr(feature = "serialize", derive(Serialize))]208#[cfg_attr(feature = "deserialize", derive(Deserialize))]209#[derive(Debug, Clone, PartialEq, Trace)]210#[trivially_drop]211pub struct BindSpec {212 pub name: IStr,213 pub params: Option<ParamsDesc>,214 pub value: LocExpr,215}216217#[cfg_attr(feature = "serialize", derive(Serialize))]218#[cfg_attr(feature = "deserialize", derive(Deserialize))]219#[derive(Debug, PartialEq, Trace)]220#[trivially_drop]221pub struct IfSpecData(pub LocExpr);222223#[cfg_attr(feature = "serialize", derive(Serialize))]224#[cfg_attr(feature = "deserialize", derive(Deserialize))]225#[derive(Debug, PartialEq, Trace)]226#[trivially_drop]227pub struct ForSpecData(pub IStr, pub LocExpr);228229#[cfg_attr(feature = "serialize", derive(Serialize))]230#[cfg_attr(feature = "deserialize", derive(Deserialize))]231#[derive(Debug, PartialEq, Trace)]232#[trivially_drop]233pub enum CompSpec {234 IfSpec(IfSpecData),235 ForSpec(ForSpecData),236}237238#[cfg_attr(feature = "serialize", derive(Serialize))]239#[cfg_attr(feature = "deserialize", derive(Deserialize))]240#[derive(Debug, PartialEq, Trace)]241#[trivially_drop]242pub struct ObjComp {243 pub pre_locals: Vec<BindSpec>,244 pub key: LocExpr,245 pub plus: bool,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#[cfg_attr(feature = "serialize", derive(Serialize))]274#[cfg_attr(feature = "deserialize", derive(Deserialize))]275#[derive(Debug, PartialEq, Trace)]276#[trivially_drop]277pub struct SliceDesc {278 pub start: Option<LocExpr>,279 pub end: Option<LocExpr>,280 pub step: Option<LocExpr>,281}282283/// Syntax base284#[cfg_attr(feature = "serialize", derive(Serialize))]285#[cfg_attr(feature = "deserialize", derive(Deserialize))]286#[derive(Debug, PartialEq, Trace)]287#[trivially_drop]288pub enum Expr {289 Literal(LiteralType),290291 /// String value: "hello"292 Str(IStr),293 /// Number: 1, 2.0, 2e+20294 Num(f64),295 /// Variable name: test296 Var(IStr),297298 /// Array of expressions: [1, 2, "Hello"]299 Arr(Vec<LocExpr>),300 /// Array comprehension:301 /// ```jsonnet302 /// ingredients: [303 /// { kind: kind, qty: 4 / 3 }304 /// for kind in [305 /// 'Honey Syrup',306 /// 'Lemon Juice',307 /// 'Farmers Gin',308 /// ]309 /// ],310 /// ```311 ArrComp(LocExpr, Vec<CompSpec>),312313 /// Object: {a: 2}314 Obj(ObjBody),315 /// Object extension: var1 {b: 2}316 ObjExtend(LocExpr, ObjBody),317318 /// (obj)319 Parened(LocExpr),320321 /// -2322 UnaryOp(UnaryOpType, LocExpr),323 /// 2 - 2324 BinaryOp(LocExpr, BinaryOpType, LocExpr),325 /// assert 2 == 2 : "Math is broken"326 AssertExpr(AssertStmt, LocExpr),327 /// local a = 2; { b: a }328 LocalExpr(Vec<BindSpec>, LocExpr),329330 /// import "hello"331 Import(PathBuf),332 /// importStr "file.txt"333 ImportStr(PathBuf),334 /// error "I'm broken"335 ErrorStmt(LocExpr),336 /// a(b, c)337 Apply(LocExpr, ArgsDesc, bool),338 /// a[b]339 Index(LocExpr, LocExpr),340 /// function(x) x341 Function(ParamsDesc, LocExpr),342 /// std.primitiveEquals343 Intrinsic(IStr),344 /// if true == false then 1 else 2345 IfElse {346 cond: IfSpecData,347 cond_then: LocExpr,348 cond_else: Option<LocExpr>,349 },350 Slice(LocExpr, SliceDesc),351}352353/// file, begin offset, end offset354#[cfg_attr(feature = "serialize", derive(Serialize))]355#[cfg_attr(feature = "deserialize", derive(Deserialize))]356#[derive(Clone, PartialEq, Trace)]357#[trivially_drop]358pub struct ExprLocation(pub Rc<Path>, pub usize, pub usize);359360impl Debug for ExprLocation {361 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {362 write!(f, "{:?}:{:?}-{:?}", self.0, self.1, self.2)363 }364}365366/// Holds AST expression and its location in source file367#[cfg_attr(feature = "serialize", derive(Serialize))]368#[cfg_attr(feature = "deserialize", derive(Deserialize))]369#[derive(Clone, PartialEq)]370pub struct LocExpr(pub Rc<Expr>, pub Option<ExprLocation>);371/// Safety:372/// AST is acyclic, and there should be no gc pointers373unsafe impl Trace for LocExpr {374 unsafe_empty_trace!();375}376impl Finalize for LocExpr {}377378impl Debug for LocExpr {379 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {380 if f.alternate() {381 write!(f, "{:#?}", self.0)?;382 } else {383 write!(f, "{:?}", self.0)?;384 }385 if let Some(loc) = &self.1 {386 write!(f, " from {:?}", loc)?;387 }388 Ok(())389 }390}391392/// Creates LocExpr from Expr and ExprLocation components393#[macro_export]394macro_rules! loc_expr {395 ($expr:expr, $need_loc:expr,($name:expr, $start:expr, $end:expr)) => {396 LocExpr(397 std::rc::Rc::new($expr),398 if $need_loc {399 Some(ExprLocation($name, $start, $end))400 } else {401 None402 },403 )404 };405}406407/// Creates LocExpr without location info408#[macro_export]409macro_rules! loc_expr_todo {410 ($expr:expr) => {411 LocExpr(Rc::new($expr), None)412 };413}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 ArgsDesc {198 pub unnamed: Vec<LocExpr>,199 pub named: Vec<(IStr, LocExpr)>,200}201impl ArgsDesc {202 pub fn new(unnamed: Vec<LocExpr>, named: Vec<(IStr, LocExpr)>) -> Self {203 Self { unnamed, named }204 }205}206207#[cfg_attr(feature = "serialize", derive(Serialize))]208#[cfg_attr(feature = "deserialize", derive(Deserialize))]209#[derive(Debug, Clone, PartialEq, Trace)]210#[trivially_drop]211pub struct BindSpec {212 pub name: IStr,213 pub params: Option<ParamsDesc>,214 pub value: LocExpr,215}216217#[cfg_attr(feature = "serialize", derive(Serialize))]218#[cfg_attr(feature = "deserialize", derive(Deserialize))]219#[derive(Debug, PartialEq, Trace)]220#[trivially_drop]221pub struct IfSpecData(pub LocExpr);222223#[cfg_attr(feature = "serialize", derive(Serialize))]224#[cfg_attr(feature = "deserialize", derive(Deserialize))]225#[derive(Debug, PartialEq, Trace)]226#[trivially_drop]227pub struct ForSpecData(pub IStr, pub LocExpr);228229#[cfg_attr(feature = "serialize", derive(Serialize))]230#[cfg_attr(feature = "deserialize", derive(Deserialize))]231#[derive(Debug, PartialEq, Trace)]232#[trivially_drop]233pub enum CompSpec {234 IfSpec(IfSpecData),235 ForSpec(ForSpecData),236}237238#[cfg_attr(feature = "serialize", derive(Serialize))]239#[cfg_attr(feature = "deserialize", derive(Deserialize))]240#[derive(Debug, PartialEq, Trace)]241#[trivially_drop]242pub struct ObjComp {243 pub pre_locals: Vec<BindSpec>,244 pub key: LocExpr,245 pub plus: bool,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#[cfg_attr(feature = "serialize", derive(Serialize))]274#[cfg_attr(feature = "deserialize", derive(Deserialize))]275#[derive(Debug, PartialEq, Trace)]276#[trivially_drop]277pub struct SliceDesc {278 pub start: Option<LocExpr>,279 pub end: Option<LocExpr>,280 pub step: Option<LocExpr>,281}282283/// Syntax base284#[cfg_attr(feature = "serialize", derive(Serialize))]285#[cfg_attr(feature = "deserialize", derive(Deserialize))]286#[derive(Debug, PartialEq, Trace)]287#[trivially_drop]288pub enum Expr {289 Literal(LiteralType),290291 /// String value: "hello"292 Str(IStr),293 /// Number: 1, 2.0, 2e+20294 Num(f64),295 /// Variable name: test296 Var(IStr),297298 /// Array of expressions: [1, 2, "Hello"]299 Arr(Vec<LocExpr>),300 /// Array comprehension:301 /// ```jsonnet302 /// ingredients: [303 /// { kind: kind, qty: 4 / 3 }304 /// for kind in [305 /// 'Honey Syrup',306 /// 'Lemon Juice',307 /// 'Farmers Gin',308 /// ]309 /// ],310 /// ```311 ArrComp(LocExpr, Vec<CompSpec>),312313 /// Object: {a: 2}314 Obj(ObjBody),315 /// Object extension: var1 {b: 2}316 ObjExtend(LocExpr, ObjBody),317318 /// (obj)319 Parened(LocExpr),320321 /// -2322 UnaryOp(UnaryOpType, LocExpr),323 /// 2 - 2324 BinaryOp(LocExpr, BinaryOpType, LocExpr),325 /// assert 2 == 2 : "Math is broken"326 AssertExpr(AssertStmt, LocExpr),327 /// local a = 2; { b: a }328 LocalExpr(Vec<BindSpec>, LocExpr),329330 /// import "hello"331 Import(PathBuf),332 /// importStr "file.txt"333 ImportStr(PathBuf),334 /// error "I'm broken"335 ErrorStmt(LocExpr),336 /// a(b, c)337 Apply(LocExpr, ArgsDesc, bool),338 /// a[b]339 Index(LocExpr, LocExpr),340 /// function(x) x341 Function(ParamsDesc, LocExpr),342 /// std.primitiveEquals343 Intrinsic(IStr),344 /// if true == false then 1 else 2345 IfElse {346 cond: IfSpecData,347 cond_then: LocExpr,348 cond_else: Option<LocExpr>,349 },350 Slice(LocExpr, SliceDesc),351}352353/// file, begin offset, end offset354#[cfg_attr(feature = "serialize", derive(Serialize))]355#[cfg_attr(feature = "deserialize", derive(Deserialize))]356#[derive(Clone, PartialEq, Trace)]357#[trivially_drop]358pub struct ExprLocation(pub Rc<Path>, pub usize, pub usize);359360impl Debug for ExprLocation {361 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {362 write!(f, "{:?}:{:?}-{:?}", self.0, self.1, self.2)363 }364}365366/// Holds AST expression and its location in source file367#[cfg_attr(feature = "serialize", derive(Serialize))]368#[cfg_attr(feature = "deserialize", derive(Deserialize))]369#[derive(Clone, PartialEq)]370pub struct LocExpr(pub Rc<Expr>, pub Option<ExprLocation>);371/// Safety:372/// AST is acyclic, and there should be no gc pointers373unsafe impl Trace for LocExpr {374 unsafe_empty_trace!();375}376impl Finalize for LocExpr {}377378impl Debug for LocExpr {379 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {380 if f.alternate() {381 write!(f, "{:#?}", self.0)?;382 } else {383 write!(f, "{:?}", self.0)?;384 }385 if let Some(loc) = &self.1 {386 write!(f, " from {:?}", loc)?;387 }388 Ok(())389 }390}391392/// Creates LocExpr from Expr and ExprLocation components393#[macro_export]394macro_rules! loc_expr {395 ($expr:expr, $need_loc:expr,($name:expr, $start:expr, $end:expr)) => {396 LocExpr(397 std::rc::Rc::new($expr),398 if $need_loc {399 Some(ExprLocation($name, $start, $end))400 } else {401 None402 },403 )404 };405}crates/jrsonnet-parser/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-parser/src/lib.rs
+++ b/crates/jrsonnet-parser/src/lib.rs
@@ -17,12 +17,12 @@
macro_rules! expr_bin {
($a:ident $op:ident $b:ident) => {
- loc_expr_todo!(Expr::BinaryOp($a, $op, $b))
+ Expr::BinaryOp($a, $op, $b)
};
}
macro_rules! expr_un {
($op:ident $a:ident) => {
- loc_expr_todo!(Expr::UnaryOp($op, $a))
+ Expr::UnaryOp($op, $a)
};
}
@@ -55,9 +55,6 @@
rule keyword(id: &'static str) -> ()
= ##parse_string_literal(id) end_of_ident()
- // Adds location data information to existing expression
- rule l(s: &ParserSettings, x: rule<Expr>) -> LocExpr
- = start:position!() v:x() end:position!() {loc_expr!(v, s.loc_data, (s.file_name.clone(), start, end))}
pub rule param(s: &ParserSettings) -> expr::Param = name:$(id()) expr:(_ "=" _ expr:expr(s){expr})? { expr::Param(name.into(), expr) }
pub rule params(s: &ParserSettings) -> expr::ParamsDesc
@@ -166,45 +163,45 @@
= keyword("for") _ id:$(id()) _ keyword("in") _ cond:expr(s) {ForSpecData(id.into(), cond)}
pub rule compspec(s: &ParserSettings) -> Vec<expr::CompSpec>
= s:(i:ifspec(s) { expr::CompSpec::IfSpec(i) } / f:forspec(s) {expr::CompSpec::ForSpec(f)} ) ** _ {s}
- pub rule local_expr(s: &ParserSettings) -> LocExpr
- = l(s,<keyword("local") _ binds:bind(s) ** comma() _ ";" _ expr:expr(s) { Expr::LocalExpr(binds, expr) }>)
- pub rule string_expr(s: &ParserSettings) -> LocExpr
- = l(s, <s:string() {Expr::Str(s.into())}>)
- pub rule obj_expr(s: &ParserSettings) -> LocExpr
- = l(s,<"{" _ body:objinside(s) _ "}" {Expr::Obj(body)}>)
- pub rule array_expr(s: &ParserSettings) -> LocExpr
- = l(s,<"[" _ elems:(expr(s) ** comma()) _ comma()? "]" {Expr::Arr(elems)}>)
- pub rule array_comp_expr(s: &ParserSettings) -> LocExpr
- = l(s,<"[" _ expr:expr(s) _ comma()? _ forspec:forspec(s) _ others:(others: compspec(s) _ {others})? "]" {
+ pub rule local_expr(s: &ParserSettings) -> Expr
+ = keyword("local") _ binds:bind(s) ** comma() _ ";" _ expr:expr(s) { Expr::LocalExpr(binds, expr) }
+ pub rule string_expr(s: &ParserSettings) -> Expr
+ = s:string() {Expr::Str(s.into())}
+ pub rule obj_expr(s: &ParserSettings) -> Expr
+ = "{" _ body:objinside(s) _ "}" {Expr::Obj(body)}
+ pub rule array_expr(s: &ParserSettings) -> Expr
+ = "[" _ elems:(expr(s) ** comma()) _ comma()? "]" {Expr::Arr(elems)}
+ pub rule array_comp_expr(s: &ParserSettings) -> Expr
+ = "[" _ expr:expr(s) _ comma()? _ forspec:forspec(s) _ others:(others: compspec(s) _ {others})? "]" {
let mut specs = vec![CompSpec::ForSpec(forspec)];
specs.extend(others.unwrap_or_default());
Expr::ArrComp(expr, specs)
- }>)
- pub rule number_expr(s: &ParserSettings) -> LocExpr
- = l(s,<n:number() { expr::Expr::Num(n) }>)
- pub rule var_expr(s: &ParserSettings) -> LocExpr
- = l(s,<n:$(id()) { expr::Expr::Var(n.into()) }>)
- pub rule if_then_else_expr(s: &ParserSettings) -> LocExpr
- = l(s,<cond:ifspec(s) _ keyword("then") _ cond_then:expr(s) cond_else:(_ keyword("else") _ e:expr(s) {e})? {Expr::IfElse{
+ }
+ pub rule number_expr(s: &ParserSettings) -> Expr
+ = n:number() { expr::Expr::Num(n) }
+ pub rule var_expr(s: &ParserSettings) -> Expr
+ = n:$(id()) { expr::Expr::Var(n.into()) }
+ pub rule if_then_else_expr(s: &ParserSettings) -> Expr
+ = cond:ifspec(s) _ keyword("then") _ cond_then:expr(s) cond_else:(_ keyword("else") _ e:expr(s) {e})? {Expr::IfElse{
cond,
cond_then,
cond_else,
- }}>)
+ }}
- pub rule literal(s: &ParserSettings) -> LocExpr
- = l(s,<v:(
+ pub rule literal(s: &ParserSettings) -> Expr
+ = v:(
keyword("null") {LiteralType::Null}
/ keyword("true") {LiteralType::True}
/ keyword("false") {LiteralType::False}
/ keyword("self") {LiteralType::This}
/ keyword("$") {LiteralType::Dollar}
/ keyword("super") {LiteralType::Super}
- ) {Expr::Literal(v)}>)
+ ) {Expr::Literal(v)}
- pub rule expr_basic(s: &ParserSettings) -> LocExpr
+ pub rule expr_basic(s: &ParserSettings) -> Expr
= literal(s)
- / quiet!{l(s,<"$intrinsic(" name:$(id()) ")" {Expr::Intrinsic(name.into())}>)}
+ / quiet!{"$intrinsic(" name:$(id()) ")" {Expr::Intrinsic(name.into())}}
/ string_expr(s) / number_expr(s)
/ array_expr(s)
@@ -212,17 +209,17 @@
/ array_expr(s)
/ array_comp_expr(s)
- / l(s,<keyword("importstr") _ path:string() {Expr::ImportStr(PathBuf::from(path))}>)
- / l(s,<keyword("import") _ path:string() {Expr::Import(PathBuf::from(path))}>)
+ / keyword("importstr") _ path:string() {Expr::ImportStr(PathBuf::from(path))}
+ / keyword("import") _ path:string() {Expr::Import(PathBuf::from(path))}
/ var_expr(s)
/ local_expr(s)
/ if_then_else_expr(s)
- / l(s,<keyword("function") _ "(" _ params:params(s) _ ")" _ expr:expr(s) {Expr::Function(params, expr)}>)
- / l(s,<assertion:assertion(s) _ ";" _ expr:expr(s) { Expr::AssertExpr(assertion, expr) }>)
+ / keyword("function") _ "(" _ params:params(s) _ ")" _ expr:expr(s) {Expr::Function(params, expr)}
+ / assertion:assertion(s) _ ";" _ expr:expr(s) { Expr::AssertExpr(assertion, expr) }
- / l(s,<keyword("error") _ expr:expr(s) { Expr::ErrorStmt(expr) }>)
+ / keyword("error") _ expr:expr(s) { Expr::ErrorStmt(expr) }
rule slice_part(s: &ParserSettings) -> Option<LocExpr>
= e:(_ e:expr(s) _{e})? {e}
@@ -246,7 +243,9 @@
use BinaryOpType::*;
use UnaryOpType::*;
rule expr(s: &ParserSettings) -> LocExpr
- = start:position!() a:precedence! {
+ = precedence! {
+ start:position!() v:@ end:position!() { loc_expr!(v, s.loc_data, (s.file_name.clone(), start, end)) }
+ --
a:(@) _ binop(<"||">) _ b:@ {expr_bin!(a Or b)}
--
a:(@) _ binop(<"&&">) _ b:@ {expr_bin!(a And b)}
@@ -280,23 +279,15 @@
unaryop(<"!">) _ b:@ {expr_un!(Not b)}
unaryop(<"~">) _ b:@ {expr_un!(BitNot b)}
--
- a:(@) _ "[" _ s:slice_desc(s) _ "]" {loc_expr_todo!(Expr::Slice(a, s))}
- a:(@) _ "." _ s:$(id()) {loc_expr_todo!(Expr::Index(a, el!(Expr::Str(s.into()))))}
- a:(@) _ "[" _ s:expr(s) _ "]" {loc_expr_todo!(Expr::Index(a, s))}
- a:(@) _ "(" _ args:args(s) _ ")" ts:(_ keyword("tailstrict"))? {loc_expr_todo!(Expr::Apply(a, args, ts.is_some()))}
- a:(@) _ "{" _ body:objinside(s) _ "}" {loc_expr_todo!(Expr::ObjExtend(a, body))}
+ a:(@) _ "[" _ e:slice_desc(s) _ "]" {Expr::Slice(a, e)}
+ a:(@) _ "." _ e:$(id()) {Expr::Index(a, el!(Expr::Str(e.into())))}
+ a:(@) _ "[" _ e:expr(s) _ "]" {Expr::Index(a, e)}
+ a:(@) _ "(" _ args:args(s) _ ")" ts:(_ keyword("tailstrict"))? {Expr::Apply(a, args, ts.is_some())}
+ a:(@) _ "{" _ body:objinside(s) _ "}" {Expr::ObjExtend(a, body)}
--
e:expr_basic(s) {e}
- "(" _ e:expr(s) _ ")" {loc_expr_todo!(Expr::Parened(e))}
- } end:position!() {
- let LocExpr(e, _) = a;
- LocExpr(e, if s.loc_data {
- Some(ExprLocation(s.file_name.clone(), start, end))
- } else {
- None
- })
+ "(" _ e:expr(s) _ ")" {Expr::Parened(e)}
}
- / e:expr_basic(s) {e}
pub rule jsonnet(s: &ParserSettings) -> LocExpr = _ e:expr(s) _ {e}
}
@@ -334,6 +325,12 @@
};
}
+ macro_rules! el_loc {
+ ($expr:expr, $loc:expr$(,)?) => {
+ LocExpr(std::rc::Rc::new($expr), Some($loc))
+ };
+ }
+
mod expressions {
use super::*;
@@ -576,6 +573,62 @@
parse!(jrsonnet_stdlib::STDLIB_STR);
}
+ #[test]
+ fn add_location_info_to_all_sub_expressions() {
+ use Expr::*;
+
+ let file_name: std::rc::Rc<std::path::Path> = PathBuf::from("/test.jsonnet").into();
+ let expr = parse(
+ "{} { local x = 1, x: x } + {}",
+ &ParserSettings {
+ loc_data: true,
+ file_name: file_name.clone(),
+ },
+ )
+ .unwrap();
+ assert_eq!(
+ expr,
+ el_loc!(
+ BinaryOp(
+ el_loc!(
+ ObjExtend(
+ el_loc!(
+ Obj(ObjBody::MemberList(vec![])),
+ ExprLocation(file_name.clone(), 0, 2)
+ ),
+ ObjBody::MemberList(vec![
+ Member::BindStmt(BindSpec {
+ name: "x".into(),
+ params: None,
+ value: el_loc!(
+ Num(1.0),
+ ExprLocation(file_name.clone(), 15, 16)
+ )
+ }),
+ Member::Field(FieldMember {
+ name: FieldName::Fixed("x".into()),
+ plus: false,
+ params: None,
+ visibility: Visibility::Normal,
+ value: el_loc!(
+ Var("x".into()),
+ ExprLocation(file_name.clone(), 21, 22)
+ ),
+ })
+ ])
+ ),
+ ExprLocation(file_name.clone(), 0, 24)
+ ),
+ BinaryOpType::Add,
+ el_loc!(
+ Obj(ObjBody::MemberList(vec![])),
+ ExprLocation(file_name.clone(), 27, 29)
+ ),
+ ),
+ ExprLocation(file_name.clone(), 0, 29),
+ ),
+ );
+ }
// From source code
/*
#[bench]