difftreelog
refactor AssertStmt to struct
in: master
6 files changed
crates/jrsonnet-evaluator/src/evaluate/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/evaluate/mod.rs
+++ b/crates/jrsonnet-evaluator/src/evaluate/mod.rs
@@ -454,19 +454,18 @@
}
pub fn evaluate_assert(ctx: Context, assertion: &AssertStmt) -> Result<()> {
- let value = &assertion.0;
- let msg = &assertion.1;
+ let AssertStmt { assertion, message } = assertion;
let assertion_result = in_frame(
- CallLocation::new(&value.span),
+ CallLocation::new(&assertion.span),
|| "assertion condition".to_owned(),
- || bool::from_untyped(evaluate(ctx.clone(), value)?),
+ || bool::from_untyped(evaluate(ctx.clone(), assertion)?),
)?;
if !assertion_result {
in_frame(
- CallLocation::new(&value.span),
+ CallLocation::new(&assertion.span),
|| "assertion failure".to_owned(),
|| {
- if let Some(msg) = msg {
+ if let Some(msg) = message {
bail!(AssertionFailed(evaluate(ctx, msg)?.to_string()?));
}
bail!(AssertionFailed(Val::Null.to_string()?));
crates/jrsonnet-ir-parser/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-ir-parser/src/lib.rs
+++ b/crates/jrsonnet-ir-parser/src/lib.rs
@@ -237,13 +237,13 @@
fn assert_stmt(p: &mut Parser<'_>) -> Result<AssertStmt> {
p.eat(T![assert])?;
- let cond = spanned(p, expr)?;
- let msg = if p.try_eat(T![:]) {
- Some(spanned(p, expr)?)
+ let assertion = spanned(p, expr)?;
+ let message = if p.try_eat(T![:]) {
+ Some(expr(p)?)
} else {
None
};
- Ok(AssertStmt(cond, msg))
+ Ok(AssertStmt { assertion, message })
}
fn if_spec_data(p: &mut Parser<'_>) -> Result<IfSpecData> {
crates/jrsonnet-ir-parser/src/snapshots/jrsonnet_ir_parser__tests__basic_test.snapdiffbeforeafterboth--- a/crates/jrsonnet-ir-parser/src/snapshots/jrsonnet_ir_parser__tests__basic_test.snap
+++ b/crates/jrsonnet-ir-parser/src/snapshots/jrsonnet_ir_parser__tests__basic_test.snap
@@ -4,8 +4,8 @@
---
AssertExpr(
AssertExpr {
- assert: AssertStmt(
- Index {
+ assert: AssertStmt {
+ assertion: Index {
indexable: Literal(
True,
),
@@ -18,12 +18,12 @@
},
],
} from virtual:<test>:7-18,
- Some(
+ message: Some(
Literal(
False,
- ) from virtual:<test>:21-26,
+ ),
),
- ),
+ },
rest: Literal(
True,
),
crates/jrsonnet-ir/src/expr.rsdiffbeforeafterboth1use std::{2 fmt::{self, Debug, Display},3 ops::Deref,4 rc::Rc,5};67use jrsonnet_gcmodule::Acyclic;8use jrsonnet_interner::IStr;910use crate::{11 function::{FunctionSignature, ParamDefault, ParamName, ParamParse},12 source::Source,13};1415#[derive(Debug, PartialEq, Acyclic)]16pub enum FieldName {17 /// {fixed: 2}18 Fixed(IStr),19 /// {["dyn"+"amic"]: 3}20 Dyn(Expr),21}2223#[derive(Debug, Clone, Copy, PartialEq, Eq, Acyclic)]24#[repr(u8)]25pub enum Visibility {26 /// :27 Normal,28 /// ::29 Hidden,30 /// :::31 Unhide,32}3334impl Visibility {35 pub fn is_visible(&self) -> bool {36 matches!(self, Self::Normal | Self::Unhide)37 }38}3940#[derive(Debug, PartialEq, Acyclic)]41pub struct AssertStmt(pub Spanned<Expr>, pub Option<Spanned<Expr>>);4243#[derive(Debug, PartialEq, Acyclic)]44pub struct FieldMember {45 pub name: Spanned<FieldName>,46 pub plus: bool,47 pub params: Option<ExprParams>,48 pub visibility: Visibility,49 pub value: Rc<Expr>,50}5152#[derive(Debug, PartialEq, Acyclic)]53pub enum Member {54 Field(FieldMember),55 BindStmt(BindSpec),56 AssertStmt(AssertStmt),57}5859#[derive(Debug, Clone, Copy, PartialEq, Eq, Acyclic)]60pub enum UnaryOpType {61 Plus,62 Minus,63 BitNot,64 Not,65}6667impl Display for UnaryOpType {68 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {69 use UnaryOpType::*;70 write!(71 f,72 "{}",73 match self {74 Plus => "+",75 Minus => "-",76 BitNot => "~",77 Not => "!",78 }79 )80 }81}8283#[derive(Debug, Clone, Copy, PartialEq, Eq, Acyclic)]84pub enum BinaryOpType {85 Mul,86 Div,8788 /// Implemented as intrinsic, put here for completeness89 Mod,9091 Add,92 Sub,9394 Lhs,95 Rhs,9697 Lt,98 Gt,99 Lte,100 Gte,101102 BitAnd,103 BitOr,104 BitXor,105106 Eq,107 Neq,108109 And,110 Or,111 #[cfg(feature = "exp-null-coaelse")]112 NullCoaelse,113114 // Equialent to std.objectHasEx(a, b, true)115 In,116}117118impl Display for BinaryOpType {119 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {120 use BinaryOpType::*;121 write!(122 f,123 "{}",124 match self {125 Mul => "*",126 Div => "/",127 Mod => "%",128 Add => "+",129 Sub => "-",130 Lhs => "<<",131 Rhs => ">>",132 Lt => "<",133 Gt => ">",134 Lte => "<=",135 Gte => ">=",136 BitAnd => "&",137 BitOr => "|",138 BitXor => "^",139 Eq => "==",140 Neq => "!=",141 And => "&&",142 Or => "||",143 In => "in",144 #[cfg(feature = "exp-null-coaelse")]145 NullCoaelse => "??",146 }147 )148 }149}150151/// name, default value152#[derive(Debug, PartialEq, Acyclic)]153pub struct ExprParam {154 pub destruct: Destruct,155 pub default: Option<Rc<Expr>>,156}157158/// Defined function parameters159#[derive(Debug, Clone, PartialEq, Acyclic)]160pub struct ExprParams {161 pub exprs: Rc<Vec<ExprParam>>,162 pub signature: FunctionSignature,163 pub(crate) binds_len: usize,164}165impl ExprParams {166 pub fn len(&self) -> usize {167 self.exprs.len()168 }169 pub fn is_empty(&self) -> bool {170 self.exprs.is_empty()171 }172173 pub fn binds_len(&self) -> usize {174 self.binds_len175 }176 pub fn new(exprs: Vec<ExprParam>) -> Self {177 Self {178 signature: FunctionSignature::new(179 exprs180 .iter()181 .map(|p| {182 ParamParse::new(183 p.destruct.name(),184 ParamDefault::exists(p.default.is_some()),185 )186 })187 .collect(),188 ),189 binds_len: exprs.iter().map(|v| v.destruct.binds_len()).sum(),190 exprs: Rc::new(exprs),191 }192 }193}194195#[derive(Debug, PartialEq, Acyclic)]196pub struct ArgsDesc {197 pub unnamed: Vec<Rc<Expr>>,198 pub names: Vec<IStr>,199 pub values: Vec<Rc<Expr>>,200}201impl ArgsDesc {202 pub fn new(unnamed: Vec<Rc<Expr>>, names: Vec<IStr>, values: Vec<Rc<Expr>>) -> Self {203 Self {204 unnamed,205 names,206 values,207 }208 }209}210211#[derive(Debug, Clone, PartialEq, Eq, Acyclic)]212pub enum DestructRest {213 /// ...rest214 Keep(IStr),215 /// ...216 Drop,217}218219#[derive(Debug, Clone, PartialEq, Acyclic)]220pub enum Destruct {221 Full(IStr),222 #[cfg(feature = "exp-destruct")]223 Skip,224 #[cfg(feature = "exp-destruct")]225 Array {226 start: Vec<Destruct>,227 rest: Option<DestructRest>,228 end: Vec<Destruct>,229 },230 #[cfg(feature = "exp-destruct")]231 Object {232 #[allow(clippy::type_complexity)]233 fields: Vec<(IStr, Option<Destruct>, Option<Rc<Spanned<Expr>>>)>,234 rest: Option<DestructRest>,235 },236}237impl Destruct {238 /// Name of destructure, used for function parameter names239 pub fn name(&self) -> ParamName {240 match self {241 Self::Full(name) => ParamName::Named(name.clone()),242 #[cfg(feature = "exp-destruct")]243 _ => ParamName::Unnamed,244 }245 }246 pub fn binds_len(&self) -> usize {247 #[cfg(feature = "exp-destruct")]248 fn cap_rest(rest: &Option<DestructRest>) -> usize {249 match rest {250 Some(DestructRest::Keep(_)) => 1,251 Some(DestructRest::Drop) => 0,252 None => 0,253 }254 }255 match self {256 Self::Full(_) => 1,257 #[cfg(feature = "exp-destruct")]258 Self::Skip => 0,259 #[cfg(feature = "exp-destruct")]260 Self::Array { start, rest, end } => {261 start.iter().map(Destruct::binds_len).sum::<usize>()262 + end.iter().map(Destruct::binds_len).sum::<usize>()263 + cap_rest(rest)264 }265 #[cfg(feature = "exp-destruct")]266 Self::Object { fields, rest } => {267 let mut out = 0;268 for (_, into, _) in fields {269 match into {270 Some(v) => out += v.binds_len(),271 // Field is destructured to default name272 None => out += 1,273 }274 }275 out + cap_rest(rest)276 }277 }278 }279}280281#[derive(Debug, PartialEq, Acyclic)]282pub enum BindSpec {283 Field {284 into: Destruct,285 value: Rc<Expr>,286 },287 Function {288 name: IStr,289 params: ExprParams,290 value: Rc<Expr>,291 },292}293impl BindSpec {294 pub fn binds_len(&self) -> usize {295 match self {296 BindSpec::Field { into, .. } => into.binds_len(),297 BindSpec::Function { .. } => 1,298 }299 }300}301302#[derive(Debug, PartialEq, Acyclic)]303pub struct IfSpecData {304 pub span: Span,305 pub cond: Expr,306}307308#[derive(Debug, PartialEq, Acyclic)]309pub struct ForSpecData {310 pub destruct: Destruct,311 pub over: Expr,312}313314#[derive(Debug, PartialEq, Acyclic)]315pub enum CompSpec {316 IfSpec(IfSpecData),317 ForSpec(ForSpecData),318}319320#[derive(Debug, PartialEq, Acyclic)]321pub struct ObjComp {322 pub locals: Rc<Vec<BindSpec>>,323 pub field: Rc<FieldMember>,324 pub compspecs: Vec<CompSpec>,325}326327#[derive(Debug, PartialEq, Acyclic)]328pub struct ObjMembers {329 pub locals: Rc<Vec<BindSpec>>,330 pub asserts: Rc<Vec<AssertStmt>>,331 pub fields: Vec<FieldMember>,332}333334#[derive(Debug, PartialEq, Acyclic)]335pub enum ObjBody {336 MemberList(ObjMembers),337 ObjComp(ObjComp),338}339340#[derive(Debug, PartialEq, Eq, Clone, Copy, Acyclic)]341pub enum LiteralType {342 This,343 Super,344 Dollar,345 Null,346 True,347 False,348}349350#[derive(Debug, PartialEq, Acyclic)]351pub struct SliceDesc {352 pub start: Option<Spanned<Expr>>,353 pub end: Option<Spanned<Expr>>,354 pub step: Option<Spanned<Expr>>,355}356357#[derive(Debug, PartialEq, Acyclic)]358pub struct AssertExpr {359 pub assert: AssertStmt,360 pub rest: Expr,361}362363#[derive(Debug, PartialEq, Acyclic)]364pub struct BinaryOp {365 pub lhs: Expr,366 pub op: BinaryOpType,367 pub rhs: Expr,368}369370#[derive(Debug, PartialEq, Acyclic)]371pub enum ImportKind {372 Normal,373 Str,374 Bin,375}376377#[derive(Debug, PartialEq, Acyclic)]378pub struct IfElse {379 pub cond: IfSpecData,380 pub cond_then: Expr,381 pub cond_else: Option<Expr>,382}383384#[derive(Debug, PartialEq, Acyclic)]385pub struct Slice {386 pub value: Expr,387 pub slice: SliceDesc,388}389390/// Syntax base391#[derive(Debug, PartialEq, Acyclic)]392pub enum Expr {393 Literal(LiteralType),394395 /// String value: "hello"396 Str(IStr),397 /// Number: 1, 2.0, 2e+20398 Num(f64),399 /// Variable name: test400 Var(Spanned<IStr>),401402 /// Array of expressions: [1, 2, "Hello"]403 Arr(Rc<Vec<Expr>>),404 /// Array comprehension:405 /// ```jsonnet406 /// ingredients: [407 /// { kind: kind, qty: 4 / 3 }408 /// for kind in [409 /// 'Honey Syrup',410 /// 'Lemon Juice',411 /// 'Farmers Gin',412 /// ]413 /// ],414 /// ```415 ArrComp(Rc<Expr>, Vec<CompSpec>),416417 /// Object: {a: 2}418 Obj(ObjBody),419 /// Object extension: var1 {b: 2}420 ObjExtend(Rc<Expr>, ObjBody),421422 /// -2423 UnaryOp(UnaryOpType, Box<Expr>),424 /// 2 - 2425 BinaryOp(Box<BinaryOp>),426 /// assert 2 == 2 : "Math is broken"427 AssertExpr(Rc<AssertExpr>),428 /// local a = 2; { b: a }429 LocalExpr(Vec<BindSpec>, Box<Expr>),430431 /// import* "hello"432 Import(Spanned<ImportKind>, Box<Expr>),433 /// error "I'm broken"434 ErrorStmt(Span, Box<Expr>),435 /// a(b, c)436 Apply(Box<Expr>, Spanned<ArgsDesc>, bool),437 /// a[b], a.b, a?.b438 Index {439 indexable: Box<Expr>,440 parts: Vec<IndexPart>,441 },442 /// function(x) x443 Function(ExprParams, Rc<Expr>),444 /// if true == false then 1 else 2445 IfElse(Box<IfElse>),446 Slice(Box<Slice>),447}448449#[derive(Debug, PartialEq, Acyclic)]450pub struct IndexPart {451 pub span: Span,452 pub value: Expr,453 #[cfg(feature = "exp-null-coaelse")]454 pub null_coaelse: bool,455}456457/// file, begin offset, end offset458#[derive(Clone, PartialEq, Eq, Acyclic)]459#[repr(C)]460pub struct Span(pub Source, pub u32, pub u32);461impl Span {462 pub fn belongs_to(&self, other: &Span) -> bool {463 other.0 == self.0 && other.1 <= self.1 && other.2 >= self.2464 }465}466467#[cfg(target_pointer_width = "64")]468static_assertions::assert_eq_size!(Span, (usize, usize));469470impl Debug for Span {471 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {472 write!(f, "{:?}:{:?}-{:?}", self.0, self.1, self.2)473 }474}475476#[derive(Clone, PartialEq, Acyclic)]477pub struct Spanned<T: Acyclic> {478 pub value: T,479 pub span: Span,480}481impl<T: Acyclic> Deref for Spanned<T> {482 type Target = T;483 fn deref(&self) -> &Self::Target {484 &self.value485 }486}487impl<T: Acyclic> Spanned<T> {488 #[inline]489 pub fn new(value: T, span: Span) -> Self {490 Self { value, span }491 }492}493494impl<T: Debug + Acyclic> Debug for Spanned<T> {495 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {496 let expr = &**self;497 if f.alternate() {498 write!(f, "{:#?}", expr)?;499 } else {500 write!(f, "{:?}", expr)?;501 }502 write!(f, " from {:?}", self.span)?;503 Ok(())504 }505}1use std::{2 fmt::{self, Debug, Display},3 ops::Deref,4 rc::Rc,5};67use jrsonnet_gcmodule::Acyclic;8use jrsonnet_interner::IStr;910use crate::{11 function::{FunctionSignature, ParamDefault, ParamName, ParamParse},12 source::Source,13};1415#[derive(Debug, PartialEq, Acyclic)]16pub enum FieldName {17 /// {fixed: 2}18 Fixed(IStr),19 /// {["dyn"+"amic"]: 3}20 Dyn(Expr),21}2223#[derive(Debug, Clone, Copy, PartialEq, Eq, Acyclic)]24#[repr(u8)]25pub enum Visibility {26 /// :27 Normal,28 /// ::29 Hidden,30 /// :::31 Unhide,32}3334impl Visibility {35 pub fn is_visible(&self) -> bool {36 matches!(self, Self::Normal | Self::Unhide)37 }38}3940#[derive(Debug, PartialEq, Acyclic)]41pub struct AssertStmt {42 pub assertion: Spanned<Expr>,43 pub message: Option<Expr>,44}4546#[derive(Debug, PartialEq, Acyclic)]47pub struct FieldMember {48 pub name: Spanned<FieldName>,49 pub plus: bool,50 pub params: Option<ExprParams>,51 pub visibility: Visibility,52 pub value: Rc<Expr>,53}5455#[derive(Debug, PartialEq, Acyclic)]56pub enum Member {57 Field(FieldMember),58 BindStmt(BindSpec),59 AssertStmt(AssertStmt),60}6162#[derive(Debug, Clone, Copy, PartialEq, Eq, Acyclic)]63pub enum UnaryOpType {64 Plus,65 Minus,66 BitNot,67 Not,68}6970impl Display for UnaryOpType {71 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> 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#[derive(Debug, Clone, Copy, PartialEq, Eq, Acyclic)]87pub enum BinaryOpType {88 Mul,89 Div,9091 /// Implemented as intrinsic, put here for completeness92 Mod,9394 Add,95 Sub,9697 Lhs,98 Rhs,99100 Lt,101 Gt,102 Lte,103 Gte,104105 BitAnd,106 BitOr,107 BitXor,108109 Eq,110 Neq,111112 And,113 Or,114 #[cfg(feature = "exp-null-coaelse")]115 NullCoaelse,116117 // Equialent to std.objectHasEx(a, b, true)118 In,119}120121impl Display for BinaryOpType {122 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {123 use BinaryOpType::*;124 write!(125 f,126 "{}",127 match self {128 Mul => "*",129 Div => "/",130 Mod => "%",131 Add => "+",132 Sub => "-",133 Lhs => "<<",134 Rhs => ">>",135 Lt => "<",136 Gt => ">",137 Lte => "<=",138 Gte => ">=",139 BitAnd => "&",140 BitOr => "|",141 BitXor => "^",142 Eq => "==",143 Neq => "!=",144 And => "&&",145 Or => "||",146 In => "in",147 #[cfg(feature = "exp-null-coaelse")]148 NullCoaelse => "??",149 }150 )151 }152}153154/// name, default value155#[derive(Debug, PartialEq, Acyclic)]156pub struct ExprParam {157 pub destruct: Destruct,158 pub default: Option<Rc<Expr>>,159}160161/// Defined function parameters162#[derive(Debug, Clone, PartialEq, Acyclic)]163pub struct ExprParams {164 pub exprs: Rc<Vec<ExprParam>>,165 pub signature: FunctionSignature,166 pub(crate) binds_len: usize,167}168impl ExprParams {169 pub fn len(&self) -> usize {170 self.exprs.len()171 }172 pub fn is_empty(&self) -> bool {173 self.exprs.is_empty()174 }175176 pub fn binds_len(&self) -> usize {177 self.binds_len178 }179 pub fn new(exprs: Vec<ExprParam>) -> Self {180 Self {181 signature: FunctionSignature::new(182 exprs183 .iter()184 .map(|p| {185 ParamParse::new(186 p.destruct.name(),187 ParamDefault::exists(p.default.is_some()),188 )189 })190 .collect(),191 ),192 binds_len: exprs.iter().map(|v| v.destruct.binds_len()).sum(),193 exprs: Rc::new(exprs),194 }195 }196}197198#[derive(Debug, PartialEq, Acyclic)]199pub struct ArgsDesc {200 pub unnamed: Vec<Rc<Expr>>,201 pub names: Vec<IStr>,202 pub values: Vec<Rc<Expr>>,203}204impl ArgsDesc {205 pub fn new(unnamed: Vec<Rc<Expr>>, names: Vec<IStr>, values: Vec<Rc<Expr>>) -> Self {206 Self {207 unnamed,208 names,209 values,210 }211 }212}213214#[derive(Debug, Clone, PartialEq, Eq, Acyclic)]215pub enum DestructRest {216 /// ...rest217 Keep(IStr),218 /// ...219 Drop,220}221222#[derive(Debug, Clone, PartialEq, Acyclic)]223pub enum Destruct {224 Full(IStr),225 #[cfg(feature = "exp-destruct")]226 Skip,227 #[cfg(feature = "exp-destruct")]228 Array {229 start: Vec<Destruct>,230 rest: Option<DestructRest>,231 end: Vec<Destruct>,232 },233 #[cfg(feature = "exp-destruct")]234 Object {235 #[allow(clippy::type_complexity)]236 fields: Vec<(IStr, Option<Destruct>, Option<Rc<Spanned<Expr>>>)>,237 rest: Option<DestructRest>,238 },239}240impl Destruct {241 /// Name of destructure, used for function parameter names242 pub fn name(&self) -> ParamName {243 match self {244 Self::Full(name) => ParamName::Named(name.clone()),245 #[cfg(feature = "exp-destruct")]246 _ => ParamName::Unnamed,247 }248 }249 pub fn binds_len(&self) -> usize {250 #[cfg(feature = "exp-destruct")]251 fn cap_rest(rest: &Option<DestructRest>) -> usize {252 match rest {253 Some(DestructRest::Keep(_)) => 1,254 Some(DestructRest::Drop) => 0,255 None => 0,256 }257 }258 match self {259 Self::Full(_) => 1,260 #[cfg(feature = "exp-destruct")]261 Self::Skip => 0,262 #[cfg(feature = "exp-destruct")]263 Self::Array { start, rest, end } => {264 start.iter().map(Destruct::binds_len).sum::<usize>()265 + end.iter().map(Destruct::binds_len).sum::<usize>()266 + cap_rest(rest)267 }268 #[cfg(feature = "exp-destruct")]269 Self::Object { fields, rest } => {270 let mut out = 0;271 for (_, into, _) in fields {272 match into {273 Some(v) => out += v.binds_len(),274 // Field is destructured to default name275 None => out += 1,276 }277 }278 out + cap_rest(rest)279 }280 }281 }282}283284#[derive(Debug, PartialEq, Acyclic)]285pub enum BindSpec {286 Field {287 into: Destruct,288 value: Rc<Expr>,289 },290 Function {291 name: IStr,292 params: ExprParams,293 value: Rc<Expr>,294 },295}296impl BindSpec {297 pub fn binds_len(&self) -> usize {298 match self {299 BindSpec::Field { into, .. } => into.binds_len(),300 BindSpec::Function { .. } => 1,301 }302 }303}304305#[derive(Debug, PartialEq, Acyclic)]306pub struct IfSpecData {307 pub span: Span,308 pub cond: Expr,309}310311#[derive(Debug, PartialEq, Acyclic)]312pub struct ForSpecData {313 pub destruct: Destruct,314 pub over: Expr,315}316317#[derive(Debug, PartialEq, Acyclic)]318pub enum CompSpec {319 IfSpec(IfSpecData),320 ForSpec(ForSpecData),321}322323#[derive(Debug, PartialEq, Acyclic)]324pub struct ObjComp {325 pub locals: Rc<Vec<BindSpec>>,326 pub field: Rc<FieldMember>,327 pub compspecs: Vec<CompSpec>,328}329330#[derive(Debug, PartialEq, Acyclic)]331pub struct ObjMembers {332 pub locals: Rc<Vec<BindSpec>>,333 pub asserts: Rc<Vec<AssertStmt>>,334 pub fields: Vec<FieldMember>,335}336337#[derive(Debug, PartialEq, Acyclic)]338pub enum ObjBody {339 MemberList(ObjMembers),340 ObjComp(ObjComp),341}342343#[derive(Debug, PartialEq, Eq, Clone, Copy, Acyclic)]344pub enum LiteralType {345 This,346 Super,347 Dollar,348 Null,349 True,350 False,351}352353#[derive(Debug, PartialEq, Acyclic)]354pub struct SliceDesc {355 pub start: Option<Spanned<Expr>>,356 pub end: Option<Spanned<Expr>>,357 pub step: Option<Spanned<Expr>>,358}359360#[derive(Debug, PartialEq, Acyclic)]361pub struct AssertExpr {362 pub assert: AssertStmt,363 pub rest: Expr,364}365366#[derive(Debug, PartialEq, Acyclic)]367pub struct BinaryOp {368 pub lhs: Expr,369 pub op: BinaryOpType,370 pub rhs: Expr,371}372373#[derive(Debug, PartialEq, Acyclic)]374pub enum ImportKind {375 Normal,376 Str,377 Bin,378}379380#[derive(Debug, PartialEq, Acyclic)]381pub struct IfElse {382 pub cond: IfSpecData,383 pub cond_then: Expr,384 pub cond_else: Option<Expr>,385}386387#[derive(Debug, PartialEq, Acyclic)]388pub struct Slice {389 pub value: Expr,390 pub slice: SliceDesc,391}392393/// Syntax base394#[derive(Debug, PartialEq, Acyclic)]395pub enum Expr {396 Literal(LiteralType),397398 /// String value: "hello"399 Str(IStr),400 /// Number: 1, 2.0, 2e+20401 Num(f64),402 /// Variable name: test403 Var(Spanned<IStr>),404405 /// Array of expressions: [1, 2, "Hello"]406 Arr(Rc<Vec<Expr>>),407 /// Array comprehension:408 /// ```jsonnet409 /// ingredients: [410 /// { kind: kind, qty: 4 / 3 }411 /// for kind in [412 /// 'Honey Syrup',413 /// 'Lemon Juice',414 /// 'Farmers Gin',415 /// ]416 /// ],417 /// ```418 ArrComp(Rc<Expr>, Vec<CompSpec>),419420 /// Object: {a: 2}421 Obj(ObjBody),422 /// Object extension: var1 {b: 2}423 ObjExtend(Rc<Expr>, ObjBody),424425 /// -2426 UnaryOp(UnaryOpType, Box<Expr>),427 /// 2 - 2428 BinaryOp(Box<BinaryOp>),429 /// assert 2 == 2 : "Math is broken"430 AssertExpr(Rc<AssertExpr>),431 /// local a = 2; { b: a }432 LocalExpr(Vec<BindSpec>, Box<Expr>),433434 /// import* "hello"435 Import(Spanned<ImportKind>, Box<Expr>),436 /// error "I'm broken"437 ErrorStmt(Span, Box<Expr>),438 /// a(b, c)439 Apply(Box<Expr>, Spanned<ArgsDesc>, bool),440 /// a[b], a.b, a?.b441 Index {442 indexable: Box<Expr>,443 parts: Vec<IndexPart>,444 },445 /// function(x) x446 Function(ExprParams, Rc<Expr>),447 /// if true == false then 1 else 2448 IfElse(Box<IfElse>),449 Slice(Box<Slice>),450}451452#[derive(Debug, PartialEq, Acyclic)]453pub struct IndexPart {454 pub span: Span,455 pub value: Expr,456 #[cfg(feature = "exp-null-coaelse")]457 pub null_coaelse: bool,458}459460/// file, begin offset, end offset461#[derive(Clone, PartialEq, Eq, Acyclic)]462#[repr(C)]463pub struct Span(pub Source, pub u32, pub u32);464impl Span {465 pub fn belongs_to(&self, other: &Span) -> bool {466 other.0 == self.0 && other.1 <= self.1 && other.2 >= self.2467 }468}469470#[cfg(target_pointer_width = "64")]471static_assertions::assert_eq_size!(Span, (usize, usize));472473impl Debug for Span {474 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {475 write!(f, "{:?}:{:?}-{:?}", self.0, self.1, self.2)476 }477}478479#[derive(Clone, PartialEq, Acyclic)]480pub struct Spanned<T: Acyclic> {481 pub value: T,482 pub span: Span,483}484impl<T: Acyclic> Deref for Spanned<T> {485 type Target = T;486 fn deref(&self) -> &Self::Target {487 &self.value488 }489}490impl<T: Acyclic> Spanned<T> {491 #[inline]492 pub fn new(value: T, span: Span) -> Self {493 Self { value, span }494 }495}496497impl<T: Debug + Acyclic> Debug for Spanned<T> {498 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {499 let expr = &**self;500 if f.alternate() {501 write!(f, "{:#?}", expr)?;502 } else {503 write!(f, "{:?}", expr)?;504 }505 write!(f, " from {:?}", self.span)?;506 Ok(())507 }508}crates/jrsonnet-ir/src/visit.rsdiffbeforeafterboth--- a/crates/jrsonnet-ir/src/visit.rs
+++ b/crates/jrsonnet-ir/src/visit.rs
@@ -157,10 +157,10 @@
}
pub fn visit_assert_stmt<V: Visitor>(v: &mut V, ass: &AssertStmt) {
- let AssertStmt(cond, msg) = ass;
- v.visit_expr(cond);
- if let Some(msg) = msg {
- v.visit_expr(msg);
+ let AssertStmt { assertion, message } = ass;
+ v.visit_expr(assertion);
+ if let Some(message) = message {
+ v.visit_expr(message);
}
}
pub fn visit_expr<V: Visitor>(v: &mut V, e: &Expr) {
crates/jrsonnet-peg-parser/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-peg-parser/src/lib.rs
+++ b/crates/jrsonnet-peg-parser/src/lib.rs
@@ -138,7 +138,7 @@
/ name:id() _ "(" _ params:params(s) _ ")" _ "=" _ value:expr(s) {BindSpec::Function{name, params, value: Rc::new(value)}}
pub rule assertion(s: &ParserSettings) -> AssertStmt
- = keyword("assert") _ cond:spanned(<expr(s)>, s) msg:(_ ":" _ e:spanned(<expr(s)>, s) {e})? { AssertStmt(cond, msg) }
+ = keyword("assert") _ assertion:spanned(<expr(s)>, s) message:(_ ":" _ e:expr(s) {e})? { AssertStmt{assertion, message} }
pub rule whole_line() -> &'input str
= str:$((!['\n'][_])* "\n") {str}