difftreelog
refactor unify throw & throw_runtime
in: master
13 files changed
crates/jrsonnet-evaluator/src/error.rsdiffbeforeafterboth265pub type Result<V, E = LocError> = std::result::Result<V, E>;265pub type Result<V, E = LocError> = std::result::Result<V, E>;266266267#[macro_export]267#[macro_export]268macro_rules! throw {268macro_rules! throw {269 ($e: expr) => {269 ($w:ident$(::$i:ident)*$(($($tt:tt)*))?) => {270 return Err($e.into())270 return Err($w$(::$i)*$(($($tt)*))?.into())271 };271 };272}272 ($l:literal) => {273273 return Err($crate::error::Error::RuntimeError($l.into()).into())274#[macro_export]274 };275macro_rules! throw_runtime {276 ($($tt:tt)*) => {275 ($l:literal, $($tt:tt)*) => {277 return Err($crate::error::Error::RuntimeError(format!($($tt)*).into()).into())276 return Err($crate::error::Error::RuntimeError(format!($l, $($tt)*).into()).into())278 };277 };279}278}280279crates/jrsonnet-evaluator/src/evaluate/destructure.rsdiffbeforeafterboth32 Destruct::Array { start, rest, end } => {32 Destruct::Array { start, rest, end } => {33 use jrsonnet_parser::DestructRest;33 use jrsonnet_parser::DestructRest;343435 use crate::{throw_runtime, val::ArrValue};35 use crate::{throw, val::ArrValue};363637 #[derive(Trace)]37 #[derive(Trace)]38 struct DataThunk {38 struct DataThunk {47 let v = self.parent.evaluate(s)?;47 let v = self.parent.evaluate(s)?;48 let arr = match v {48 let arr = match v {49 Val::Arr(a) => a,49 Val::Arr(a) => a,50 _ => throw_runtime!("expected array"),50 _ => throw!("expected array"),51 };51 };52 if !self.has_rest {52 if !self.has_rest {53 if arr.len() != self.min_len {53 if arr.len() != self.min_len {54 throw_runtime!("expected {} elements, got {}", self.min_len, arr.len())54 throw!("expected {} elements, got {}", self.min_len, arr.len())55 }55 }56 } else if arr.len() < self.min_len {56 } else if arr.len() < self.min_len {57 throw_runtime!(57 throw!(58 "expected at least {} elements, but array was only {}",58 "expected at least {} elements, but array was only {}",59 self.min_len,59 self.min_len,60 arr.len()60 arr.len()163 }163 }164 #[cfg(feature = "exp-destruct")]164 #[cfg(feature = "exp-destruct")]165 Destruct::Object { fields, rest } => {165 Destruct::Object { fields, rest } => {166 use crate::{obj::ObjValue, throw_runtime};166 use crate::{obj::ObjValue, throw};167167168 #[derive(Trace)]168 #[derive(Trace)]169 struct DataThunk {169 struct DataThunk {178 let v = self.parent.evaluate(s)?;178 let v = self.parent.evaluate(s)?;179 let obj = match v {179 let obj = match v {180 Val::Obj(o) => o,180 Val::Obj(o) => o,181 _ => throw_runtime!("expected object"),181 _ => throw!("expected object"),182 };182 };183 for field in &self.field_names {183 for field in &self.field_names {184 if !obj.has_field_ex(field.clone(), true) {184 if !obj.has_field_ex(field.clone(), true) {185 throw_runtime!("missing field: {}", field);185 throw!("missing field: {}", field);186 }186 }187 }187 }188 if !self.has_rest {188 if !self.has_rest {189 let len = obj.len();189 let len = obj.len();190 if len != self.field_names.len() {190 if len != self.field_names.len() {191 throw_runtime!("too many fields, and rest not found");191 throw!("too many fields, and rest not found");192 }192 }193 }193 }194 Ok(obj)194 Ok(obj)crates/jrsonnet-evaluator/src/evaluate/operator.rsdiffbeforeafterboth150 (Num(v1), BitXor, Num(v2)) => Num(f64::from((*v1 as i32) ^ (*v2 as i32))),150 (Num(v1), BitXor, Num(v2)) => Num(f64::from((*v1 as i32) ^ (*v2 as i32))),151 (Num(v1), Lhs, Num(v2)) => {151 (Num(v1), Lhs, Num(v2)) => {152 if *v2 < 0.0 {152 if *v2 < 0.0 {153 throw!(RuntimeError("shift by negative exponent".into()))153 throw!("shift by negative exponent")154 }154 }155 Num(f64::from((*v1 as i32) << (*v2 as i32)))155 Num(f64::from((*v1 as i32) << (*v2 as i32)))156 }156 }157 (Num(v1), Rhs, Num(v2)) => {157 (Num(v1), Rhs, Num(v2)) => {158 if *v2 < 0.0 {158 if *v2 < 0.0 {159 throw!(RuntimeError("shift by negative exponent".into()))159 throw!("shift by negative exponent")160 }160 }161 Num(f64::from((*v1 as i32) >> (*v2 as i32)))161 Num(f64::from((*v1 as i32) >> (*v2 as i32)))162 }162 }crates/jrsonnet-evaluator/src/integrations/serde.rsdiffbeforeafterboth72 }72 }73 Self::Object(out)73 Self::Object(out)74 }74 }75 Val::Func(_) => throw!(RuntimeError("tried to manifest function".into())),75 Val::Func(_) => throw!("tried to manifest function"),76 })76 })77 }77 }78}78}crates/jrsonnet-evaluator/src/stdlib/format.rsdiffbeforeafterboth591 ),591 ),592 Val::Str(s) => {592 Val::Str(s) => {593 if s.chars().count() != 1 {593 if s.chars().count() != 1 {594 throw!(RuntimeError(594 throw!("%c expected 1 char string, got {}", s.chars().count(),);595 format!("%c expected 1 char string, got {}", s.chars().count()).into(),596 ));597 }595 }598 tmp_out.push_str(&s);596 tmp_out.push_str(&s);599 }597 }crates/jrsonnet-evaluator/src/stdlib/manifest.rsdiffbeforeafterboth341 }341 }342 }342 }343 }343 }344 Val::Func(_) => throw!(RuntimeError("tried to manifest function".into())),344 Val::Func(_) => throw!("tried to manifest function"),345 }345 }346 Ok(())346 Ok(())347}347}crates/jrsonnet-evaluator/src/typed/conversions.rsdiffbeforeafterboth6use jrsonnet_types::{ComplexValType, ValType};6use jrsonnet_types::{ComplexValType, ValType};778use crate::{8use crate::{9 error::{Error::*, Result},9 error::Result,10 function::{FuncDesc, FuncVal},10 function::{FuncDesc, FuncVal},11 throw,11 throw,12 typed::CheckType,12 typed::CheckType,41 Val::Num(n) => {41 Val::Num(n) => {42 #[allow(clippy::float_cmp)]42 #[allow(clippy::float_cmp)]43 if n.trunc() != n {43 if n.trunc() != n {44 throw!(RuntimeError(44 throw!(45 format!(46 "cannot convert number with fractional part to {}",45 "cannot convert number with fractional part to {}",47 stringify!($ty)46 stringify!($ty)48 )49 .into()50 ))47 )51 }48 }52 Ok(n as Self)49 Ok(n as Self)53 }50 }99 Val::Num(n) => {96 Val::Num(n) => {100 #[allow(clippy::float_cmp)]97 #[allow(clippy::float_cmp)]101 if n.trunc() != n {98 if n.trunc() != n {102 throw!(RuntimeError(99 throw!(103 format!(104 "cannot convert number with fractional part to {}",100 "cannot convert number with fractional part to {}",105 stringify!($ty)101 stringify!($ty)106 )107 .into()108 ))102 )109 }103 }110 Ok(Self(n as $ty))104 Ok(Self(n as $ty))111 }105 }167161168 fn into_untyped(value: Self, _: State) -> Result<Val> {162 fn into_untyped(value: Self, _: State) -> Result<Val> {169 if value > u32::MAX as Self {163 if value > u32::MAX as Self {170 throw!(RuntimeError("number is too large".into()))164 throw!("number is too large")171 }165 }172 Ok(Val::Num(value as f64))166 Ok(Val::Num(value as f64))173 }167 }178 Val::Num(n) => {172 Val::Num(n) => {179 #[allow(clippy::float_cmp)]173 #[allow(clippy::float_cmp)]180 if n.trunc() != n {174 if n.trunc() != n {181 throw!(RuntimeError(175 throw!("cannot convert number with fractional part to usize")182 "cannot convert number with fractional part to usize".into()183 ))184 }176 }185 Ok(n as Self)177 Ok(n as Self)186 }178 }440 <Self as Typed>::TYPE.check(s, &value)?;432 <Self as Typed>::TYPE.check(s, &value)?;441 match value {433 match value {442 Val::Func(FuncVal::Normal(desc)) => Ok(desc),434 Val::Func(FuncVal::Normal(desc)) => Ok(desc),443 Val::Func(_) => throw!(RuntimeError("expected normal function, not builtin".into())),435 Val::Func(_) => throw!("expected normal function, not builtin"),444 _ => unreachable!(),436 _ => unreachable!(),445 }437 }446 }438 }crates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth629 if num.is_finite() {629 if num.is_finite() {630 Ok(Self::Num(num))630 Ok(Self::Num(num))631 } else {631 } else {632 throw!(RuntimeError("overflow".into()))632 throw!("overflow")633 }633 }634 }634 }635635843 (Val::Null, Val::Null) => true,843 (Val::Null, Val::Null) => true,844 (Val::Str(a), Val::Str(b)) => a == b,844 (Val::Str(a), Val::Str(b)) => a == b,845 (Val::Num(a), Val::Num(b)) => (a - b).abs() <= f64::EPSILON,845 (Val::Num(a), Val::Num(b)) => (a - b).abs() <= f64::EPSILON,846 (Val::Arr(_), Val::Arr(_)) => throw!(RuntimeError(846 (Val::Arr(_), Val::Arr(_)) => {847 "primitiveEquals operates on primitive types, got array".into(),847 throw!("primitiveEquals operates on primitive types, got array")848 )),848 }849 (Val::Obj(_), Val::Obj(_)) => throw!(RuntimeError(849 (Val::Obj(_), Val::Obj(_)) => {850 "primitiveEquals operates on primitive types, got object".into(),850 throw!("primitiveEquals operates on primitive types, got object")851 )),851 }852 (a, b) if is_function_like(a) && is_function_like(b) => {852 (a, b) if is_function_like(a) && is_function_like(b) => {853 throw!(RuntimeError("cannot test equality of functions".into()))853 throw!("cannot test equality of functions")854 }854 }855 (_, _) => false,855 (_, _) => false,856 })856 })crates/jrsonnet-stdlib/src/arrays.rsdiffbeforeafterboth1use jrsonnet_evaluator::{1use jrsonnet_evaluator::{2 error::Result,2 error::Result,3 function::{builtin, FuncVal},3 function::{builtin, FuncVal},4 throw_runtime,4 throw,5 typed::{Any, BoundedUsize, Typed, VecVal},5 typed::{Any, BoundedUsize, Typed, VecVal},6 val::{equals, ArrValue, IndexableVal},6 val::{equals, ArrValue, IndexableVal},7 IStr, State, Val,7 IStr, State, Val,43 match func.evaluate_simple(s.clone(), &(c.to_string(),))? {43 match func.evaluate_simple(s.clone(), &(c.to_string(),))? {44 Val::Str(o) => out.push_str(&o),44 Val::Str(o) => out.push_str(&o),45 Val::Null => continue,45 Val::Null => continue,46 _ => throw_runtime!("in std.join all items should be strings"),46 _ => throw!("in std.join all items should be strings"),47 };47 };48 }48 }49 Ok(IndexableVal::Str(out.into()))49 Ok(IndexableVal::Str(out.into()))59 }59 }60 }60 }61 Val::Null => continue,61 Val::Null => continue,62 _ => throw_runtime!("in std.join all items should be arrays"),62 _ => throw!("in std.join all items should be arrays"),63 };63 };64 }64 }65 Ok(IndexableVal::Arr(out.into()))65 Ok(IndexableVal::Arr(out.into()))128 } else if matches!(item, Val::Null) {128 } else if matches!(item, Val::Null) {129 continue;129 continue;130 } else {130 } else {131 throw_runtime!("in std.join all items should be arrays");131 throw!("in std.join all items should be arrays");132 }132 }133 }133 }134134149 } else if matches!(item, Val::Null) {149 } else if matches!(item, Val::Null) {150 continue;150 continue;151 } else {151 } else {152 throw_runtime!("in std.join all items should be strings");152 throw!("in std.join all items should be strings");153 }153 }154 }154 }155155crates/jrsonnet-stdlib/src/lib.rsdiffbeforeafterboth8 error::{Error::*, Result},8 error::{Error::*, Result},9 function::{builtin::Builtin, ArgLike, CallLocation, FuncVal, TlaArg},9 function::{builtin::Builtin, ArgLike, CallLocation, FuncVal, TlaArg},10 gc::{GcHashMap, TraceBox},10 gc::{GcHashMap, TraceBox},11 tb, throw_runtime,11 tb, throw,12 trace::PathResolver,12 trace::PathResolver,13 typed::{Any, Either, Either2, Either4, VecVal, M1},13 typed::{Any, Either, Either2, Either4, VecVal, M1},14 val::{equals, ArrValue},14 val::{equals, ArrValue},500 true500 true501 }501 }502 }502 }503 _ => throw_runtime!("both arguments should be of the same type"),503 _ => throw!("both arguments should be of the same type"),504 })504 })505}505}506506534 true534 true535 }535 }536 }536 }537 _ => throw_runtime!("both arguments should be of the same type"),537 _ => throw!("both arguments should be of the same type"),538 })538 })539}539}540540crates/jrsonnet-stdlib/src/sort.rsdiffbeforeafterboth1use jrsonnet_evaluator::{1use jrsonnet_evaluator::{2 error::Result,2 error::Result,3 function::{builtin, FuncVal},3 function::{builtin, FuncVal},4 throw_runtime,4 throw,5 typed::Any,5 typed::Any,6 val::ArrValue,6 val::ArrValue,7 State, Val,7 State, Val,41 (Val::Num(_), SortKeyType::Unknown) => sort_type = SortKeyType::Number,41 (Val::Num(_), SortKeyType::Unknown) => sort_type = SortKeyType::Number,42 (Val::Str(_), SortKeyType::String) | (Val::Num(_), SortKeyType::Number) => {}42 (Val::Str(_), SortKeyType::String) | (Val::Num(_), SortKeyType::Number) => {}43 (Val::Str(_) | Val::Num(_), _) => {43 (Val::Str(_) | Val::Num(_), _) => {44 throw_runtime!("sort elements should have the same types")44 throw!("sort elements should have the same types")45 }45 }46 _ => throw_runtime!("sort key should either be a string or a number"),46 _ => throw!("sort key should either be a string or a number"),47 }47 }48 }48 }49 Ok(sort_type)49 Ok(sort_type)tests/tests/common.rsdiffbeforeafterboth1use jrsonnet_evaluator::{1use jrsonnet_evaluator::{2 error::Result,2 error::Result,3 function::{builtin, FuncVal},3 function::{builtin, FuncVal},4 throw_runtime, ObjValueBuilder, State, Thunk, Val,4 throw, ObjValueBuilder, State, Thunk, Val,5};5};6use jrsonnet_stdlib::StateExt;6use jrsonnet_stdlib::StateExt;7711 let a = &$a;11 let a = &$a;12 let b = &$b;12 let b = &$b;13 if a != b {13 if a != b {14 ::jrsonnet_evaluator::throw_runtime!("assertion failed: a != b\na={:#?}\nb={:#?}", a, b)14 ::jrsonnet_evaluator::throw!("assertion failed: a != b\na={:#?}\nb={:#?}", a, b)15 }15 }16 }};16 }};17}17}20macro_rules! ensure {20macro_rules! ensure {21 ($v:expr $(,)?) => {21 ($v:expr $(,)?) => {22 if !$v {22 if !$v {23 ::jrsonnet_evaluator::throw_runtime!("assertion failed: {}", stringify!($v))23 ::jrsonnet_evaluator::throw!("assertion failed: {}", stringify!($v))24 }24 }25 };25 };26}26}29macro_rules! ensure_val_eq {29macro_rules! ensure_val_eq {30 ($s:expr, $a:expr, $b:expr) => {{30 ($s:expr, $a:expr, $b:expr) => {{31 if !::jrsonnet_evaluator::val::equals($s.clone(), &$a.clone(), &$b.clone())? {31 if !::jrsonnet_evaluator::val::equals($s.clone(), &$a.clone(), &$b.clone())? {32 ::jrsonnet_evaluator::throw_runtime!(32 ::jrsonnet_evaluator::throw!(33 "assertion failed: a != b\na={:#?}\nb={:#?}",33 "assertion failed: a != b\na={:#?}\nb={:#?}",34 $a.to_json(34 $a.to_json(35 $s.clone(),35 $s.clone(),52fn assert_throw(s: State, lazy: Thunk<Val>, message: String) -> Result<bool> {52fn assert_throw(s: State, lazy: Thunk<Val>, message: String) -> Result<bool> {53 match lazy.evaluate(s) {53 match lazy.evaluate(s) {54 Ok(_) => {54 Ok(_) => {55 throw_runtime!("expected argument to throw on evaluation, but it returned instead")55 throw!("expected argument to throw on evaluation, but it returned instead")56 }56 }57 Err(e) => {57 Err(e) => {58 let error = format!("{}", e.error());58 let error = format!("{}", e.error());tests/tests/sanity.rsdiffbeforeafterboth1use jrsonnet_evaluator::{error::Result, throw_runtime, State, Val};1use jrsonnet_evaluator::{error::Result, throw, State, Val};2use jrsonnet_stdlib::StateExt;2use jrsonnet_stdlib::StateExt;334mod common;4mod common;232324 {24 {25 let e = match s.evaluate_snippet("snip".to_owned(), "assert 1 == 2: 'fail'; null") {25 let e = match s.evaluate_snippet("snip".to_owned(), "assert 1 == 2: 'fail'; null") {26 Ok(_) => throw_runtime!("assertion should fail"),26 Ok(_) => throw!("assertion should fail"),27 Err(e) => e,27 Err(e) => e,28 };28 };29 let e = s.stringify_err(&e);29 let e = s.stringify_err(&e);30 ensure!(e.starts_with("assert failed: fail\n"));30 ensure!(e.starts_with("assert failed: fail\n"));31 }31 }32 {32 {33 let e = match s.evaluate_snippet("snip".to_owned(), "std.assertEqual(1, 2)") {33 let e = match s.evaluate_snippet("snip".to_owned(), "std.assertEqual(1, 2)") {34 Ok(_) => throw_runtime!("assertion should fail"),34 Ok(_) => throw!("assertion should fail"),35 Err(e) => e,35 Err(e) => e,36 };36 };37 let e = s.stringify_err(&e);37 let e = s.stringify_err(&e);