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}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}