difftreelog
fix use push_stack_frame in public macroses
in: master
2 files changed
crates/jrsonnet-evaluator/src/function.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/function.rs
+++ b/crates/jrsonnet-evaluator/src/function.rs
@@ -146,7 +146,7 @@
($ctx: expr, $fn_name: expr, $args: expr, $total_args: expr, [
$($id: expr, $name: ident: $ty: expr $(=>$match: path)?);+ $(;)?
], $handler:block) => {{
- use $crate::{error::Error::*, throw, evaluate, push, typed::CheckType};
+ use $crate::{error::Error::*, throw, evaluate, push_stack_frame, typed::CheckType};
let args = $args;
if args.len() > $total_args {
@@ -162,7 +162,7 @@
throw!(IntrinsicArgumentReorderingIsNotSupportedYet);
}
}
- let $name = push(None, || format!("evaluating argument"), || {
+ let $name = push_stack_frame(None, || format!("evaluating argument"), || {
let value = evaluate($ctx.clone(), &$name.1)?;
$ty.check(&value)?;
Ok(value)
crates/jrsonnet-evaluator/src/typed.rsdiffbeforeafterboth1use std::{fmt::Display, rc::Rc};23use crate::{4 error::{Error, LocError, Result},5 push, Val,6};7use jrsonnet_parser::ExprLocation;8use jrsonnet_types::{ComplexValType, ValType};9use thiserror::Error;1011#[macro_export]12macro_rules! unwrap_type {13 ($desc: expr, $value: expr, $typ: expr => $match: path) => {{14 use $crate::{push, typed::CheckType};15 push(None, $desc, || Ok($typ.check(&$value)?))?;16 match $value {17 $match(v) => v,18 _ => unreachable!(),19 }20 }};21}2223#[derive(Debug, Error, Clone)]24pub enum TypeError {25 #[error("expected {0}, got {1}")]26 ExpectedGot(ComplexValType, ValType),27 #[error("missing property {0} from {1:?}")]28 MissingProperty(Rc<str>, ComplexValType),29 #[error("every failed from {0}:\n{1}")]30 UnionFailed(ComplexValType, TypeLocErrorList),31 #[error("number out of bounds: {0} not in {1:?}..{2:?}")]32 BoundsFailed(f64, Option<f64>, Option<f64>),33}34impl From<TypeError> for LocError {35 fn from(e: TypeError) -> Self {36 Error::TypeError(e.into()).into()37 }38}3940#[derive(Debug, Clone)]41pub struct TypeLocError(Box<TypeError>, ValuePathStack);42impl From<TypeError> for TypeLocError {43 fn from(e: TypeError) -> Self {44 Self(Box::new(e), ValuePathStack(Vec::new()))45 }46}47impl From<TypeLocError> for LocError {48 fn from(e: TypeLocError) -> Self {49 Error::TypeError(e).into()50 }51}52impl Display for TypeLocError {53 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {54 write!(f, "{}", self.0)?;55 if !(self.1).0.is_empty() {56 write!(f, "at {}", self.1)?;57 }58 Ok(())59 }60}6162#[derive(Debug, Clone)]63pub struct TypeLocErrorList(Vec<TypeLocError>);64impl Display for TypeLocErrorList {65 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {66 use std::fmt::Write;67 let mut out = String::new();68 for (i, err) in self.0.iter().enumerate() {69 if i != 0 {70 writeln!(f)?;71 }72 out.clear();73 write!(out, "{}", err)?;7475 for (i, line) in out.lines().enumerate() {76 if line.trim().is_empty() {77 continue;78 }79 if i != 0 {80 writeln!(f)?;81 write!(f, " ")?;82 } else {83 write!(f, " - ")?;84 }85 write!(f, "{}", line)?;86 }87 }88 Ok(())89 }90}9192fn push_type(93 location: Option<&ExprLocation>,94 error_reason: impl Fn() -> String,95 path: impl Fn() -> ValuePathItem,96 item: impl Fn() -> Result<()>,97) -> Result<()> {98 push(location, error_reason, || match item() {99 Ok(_) => Ok(()),100 Err(mut e) => {101 if let Error::TypeError(e) = &mut e.error_mut() {102 (e.1).0.push(path())103 }104 Err(e)105 }106 })107}108109// TODO: check_fast for fast path of union type checking110pub trait CheckType {111 fn check(&self, value: &Val) -> Result<()>;112}113114impl CheckType for ValType {115 fn check(&self, value: &Val) -> Result<()> {116 let got = value.value_type();117 if got != *self {118 let loc_error: TypeLocError = TypeError::ExpectedGot((*self).into(), got).into();119 return Err(loc_error.into());120 }121 Ok(())122 }123}124125#[derive(Clone, Debug)]126enum ValuePathItem {127 Field(Rc<str>),128 Index(u64),129}130impl Display for ValuePathItem {131 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {132 match self {133 Self::Field(name) => write!(f, ".{}", name)?,134 Self::Index(idx) => write!(f, "[{}]", idx)?,135 }136 Ok(())137 }138}139140#[derive(Clone, Debug)]141struct ValuePathStack(Vec<ValuePathItem>);142impl Display for ValuePathStack {143 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {144 write!(f, "self")?;145 for elem in self.0.iter().rev() {146 write!(f, "{}", elem)?;147 }148 Ok(())149 }150}151152impl CheckType for ComplexValType {153 fn check(&self, value: &Val) -> Result<()> {154 match self {155 Self::Any => Ok(()),156 Self::Simple(s) => s.check(value),157 Self::Char => match value {158 Val::Str(s) if s.len() == 1 || s.chars().count() == 1 => Ok(()),159 v => Err(TypeError::ExpectedGot(self.clone(), v.value_type()).into()),160 },161 Self::BoundedNumber(from, to) => {162 if let Val::Num(n) = value {163 if from.map(|from| from > *n).unwrap_or(false)164 || to.map(|to| to <= *n).unwrap_or(false)165 {166 return Err(TypeError::BoundsFailed(*n, *from, *to).into());167 }168 Ok(())169 } else {170 Err(TypeError::ExpectedGot(self.clone(), value.value_type()).into())171 }172 }173 Self::Array(elem_type) => match value {174 Val::Arr(a) => {175 for (i, item) in a.iter().enumerate() {176 push_type(177 None,178 || format!("array index {}", i),179 || ValuePathItem::Index(i as u64),180 || Ok(elem_type.check(&item.clone()?)?),181 )?;182 }183 Ok(())184 }185 v => Err(TypeError::ExpectedGot(self.clone(), v.value_type()).into()),186 },187 Self::ArrayRef(elem_type) => match value {188 Val::Arr(a) => {189 for (i, item) in a.iter().enumerate() {190 push_type(191 None,192 || format!("array index {}", i),193 || ValuePathItem::Index(i as u64),194 || Ok(elem_type.check(&item.clone()?)?),195 )?;196 }197 Ok(())198 }199 v => Err(TypeError::ExpectedGot(self.clone(), v.value_type()).into()),200 },201 Self::ObjectRef(elems) => match value {202 Val::Obj(obj) => {203 for (k, v) in elems.iter() {204 if let Some(got_v) = obj.get((*k).into())? {205 push_type(206 None,207 || format!("property {}", k),208 || ValuePathItem::Field((*k).into()),209 || v.check(&got_v),210 )?211 } else {212 return Err(213 TypeError::MissingProperty((*k).into(), self.clone()).into()214 );215 }216 }217 Ok(())218 }219 v => Err(TypeError::ExpectedGot(self.clone(), v.value_type()).into()),220 },221 Self::Union(types) => {222 let mut errors = Vec::new();223 for ty in types.iter() {224 match ty.check(value) {225 Ok(()) => {226 return Ok(());227 }228 Err(e) => match e.error() {229 Error::TypeError(e) => errors.push(e.clone()),230 _ => return Err(e),231 },232 }233 }234 Err(TypeError::UnionFailed(self.clone(), TypeLocErrorList(errors)).into())235 }236 Self::UnionRef(types) => {237 let mut errors = Vec::new();238 for ty in types.iter() {239 match ty.check(value) {240 Ok(()) => {241 return Ok(());242 }243 Err(e) => match e.error() {244 Error::TypeError(e) => errors.push(e.clone()),245 _ => return Err(e),246 },247 }248 }249 Err(TypeError::UnionFailed(self.clone(), TypeLocErrorList(errors)).into())250 }251 Self::Sum(types) => {252 for ty in types.iter() {253 ty.check(value)?254 }255 Ok(())256 }257 Self::SumRef(types) => {258 for ty in types.iter() {259 ty.check(value)?260 }261 Ok(())262 }263 }264 }265}1use std::{fmt::Display, rc::Rc};23use crate::{4 error::{Error, LocError, Result},5 push, Val,6};7use jrsonnet_parser::ExprLocation;8use jrsonnet_types::{ComplexValType, ValType};9use thiserror::Error;1011#[macro_export]12macro_rules! unwrap_type {13 ($desc: expr, $value: expr, $typ: expr => $match: path) => {{14 use $crate::{push_stack_frame, typed::CheckType};15 push_stack_frame(None, $desc, || Ok($typ.check(&$value)?))?;16 match $value {17 $match(v) => v,18 _ => unreachable!(),19 }20 }};21}2223#[derive(Debug, Error, Clone)]24pub enum TypeError {25 #[error("expected {0}, got {1}")]26 ExpectedGot(ComplexValType, ValType),27 #[error("missing property {0} from {1:?}")]28 MissingProperty(Rc<str>, ComplexValType),29 #[error("every failed from {0}:\n{1}")]30 UnionFailed(ComplexValType, TypeLocErrorList),31 #[error("number out of bounds: {0} not in {1:?}..{2:?}")]32 BoundsFailed(f64, Option<f64>, Option<f64>),33}34impl From<TypeError> for LocError {35 fn from(e: TypeError) -> Self {36 Error::TypeError(e.into()).into()37 }38}3940#[derive(Debug, Clone)]41pub struct TypeLocError(Box<TypeError>, ValuePathStack);42impl From<TypeError> for TypeLocError {43 fn from(e: TypeError) -> Self {44 Self(Box::new(e), ValuePathStack(Vec::new()))45 }46}47impl From<TypeLocError> for LocError {48 fn from(e: TypeLocError) -> Self {49 Error::TypeError(e).into()50 }51}52impl Display for TypeLocError {53 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {54 write!(f, "{}", self.0)?;55 if !(self.1).0.is_empty() {56 write!(f, "at {}", self.1)?;57 }58 Ok(())59 }60}6162#[derive(Debug, Clone)]63pub struct TypeLocErrorList(Vec<TypeLocError>);64impl Display for TypeLocErrorList {65 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {66 use std::fmt::Write;67 let mut out = String::new();68 for (i, err) in self.0.iter().enumerate() {69 if i != 0 {70 writeln!(f)?;71 }72 out.clear();73 write!(out, "{}", err)?;7475 for (i, line) in out.lines().enumerate() {76 if line.trim().is_empty() {77 continue;78 }79 if i != 0 {80 writeln!(f)?;81 write!(f, " ")?;82 } else {83 write!(f, " - ")?;84 }85 write!(f, "{}", line)?;86 }87 }88 Ok(())89 }90}9192fn push_type(93 location: Option<&ExprLocation>,94 error_reason: impl Fn() -> String,95 path: impl Fn() -> ValuePathItem,96 item: impl Fn() -> Result<()>,97) -> Result<()> {98 push(location, error_reason, || match item() {99 Ok(_) => Ok(()),100 Err(mut e) => {101 if let Error::TypeError(e) = &mut e.error_mut() {102 (e.1).0.push(path())103 }104 Err(e)105 }106 })107}108109// TODO: check_fast for fast path of union type checking110pub trait CheckType {111 fn check(&self, value: &Val) -> Result<()>;112}113114impl CheckType for ValType {115 fn check(&self, value: &Val) -> Result<()> {116 let got = value.value_type();117 if got != *self {118 let loc_error: TypeLocError = TypeError::ExpectedGot((*self).into(), got).into();119 return Err(loc_error.into());120 }121 Ok(())122 }123}124125#[derive(Clone, Debug)]126enum ValuePathItem {127 Field(Rc<str>),128 Index(u64),129}130impl Display for ValuePathItem {131 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {132 match self {133 Self::Field(name) => write!(f, ".{}", name)?,134 Self::Index(idx) => write!(f, "[{}]", idx)?,135 }136 Ok(())137 }138}139140#[derive(Clone, Debug)]141struct ValuePathStack(Vec<ValuePathItem>);142impl Display for ValuePathStack {143 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {144 write!(f, "self")?;145 for elem in self.0.iter().rev() {146 write!(f, "{}", elem)?;147 }148 Ok(())149 }150}151152impl CheckType for ComplexValType {153 fn check(&self, value: &Val) -> Result<()> {154 match self {155 Self::Any => Ok(()),156 Self::Simple(s) => s.check(value),157 Self::Char => match value {158 Val::Str(s) if s.len() == 1 || s.chars().count() == 1 => Ok(()),159 v => Err(TypeError::ExpectedGot(self.clone(), v.value_type()).into()),160 },161 Self::BoundedNumber(from, to) => {162 if let Val::Num(n) = value {163 if from.map(|from| from > *n).unwrap_or(false)164 || to.map(|to| to <= *n).unwrap_or(false)165 {166 return Err(TypeError::BoundsFailed(*n, *from, *to).into());167 }168 Ok(())169 } else {170 Err(TypeError::ExpectedGot(self.clone(), value.value_type()).into())171 }172 }173 Self::Array(elem_type) => match value {174 Val::Arr(a) => {175 for (i, item) in a.iter().enumerate() {176 push_type(177 None,178 || format!("array index {}", i),179 || ValuePathItem::Index(i as u64),180 || Ok(elem_type.check(&item.clone()?)?),181 )?;182 }183 Ok(())184 }185 v => Err(TypeError::ExpectedGot(self.clone(), v.value_type()).into()),186 },187 Self::ArrayRef(elem_type) => match value {188 Val::Arr(a) => {189 for (i, item) in a.iter().enumerate() {190 push_type(191 None,192 || format!("array index {}", i),193 || ValuePathItem::Index(i as u64),194 || Ok(elem_type.check(&item.clone()?)?),195 )?;196 }197 Ok(())198 }199 v => Err(TypeError::ExpectedGot(self.clone(), v.value_type()).into()),200 },201 Self::ObjectRef(elems) => match value {202 Val::Obj(obj) => {203 for (k, v) in elems.iter() {204 if let Some(got_v) = obj.get((*k).into())? {205 push_type(206 None,207 || format!("property {}", k),208 || ValuePathItem::Field((*k).into()),209 || v.check(&got_v),210 )?211 } else {212 return Err(213 TypeError::MissingProperty((*k).into(), self.clone()).into()214 );215 }216 }217 Ok(())218 }219 v => Err(TypeError::ExpectedGot(self.clone(), v.value_type()).into()),220 },221 Self::Union(types) => {222 let mut errors = Vec::new();223 for ty in types.iter() {224 match ty.check(value) {225 Ok(()) => {226 return Ok(());227 }228 Err(e) => match e.error() {229 Error::TypeError(e) => errors.push(e.clone()),230 _ => return Err(e),231 },232 }233 }234 Err(TypeError::UnionFailed(self.clone(), TypeLocErrorList(errors)).into())235 }236 Self::UnionRef(types) => {237 let mut errors = Vec::new();238 for ty in types.iter() {239 match ty.check(value) {240 Ok(()) => {241 return Ok(());242 }243 Err(e) => match e.error() {244 Error::TypeError(e) => errors.push(e.clone()),245 _ => return Err(e),246 },247 }248 }249 Err(TypeError::UnionFailed(self.clone(), TypeLocErrorList(errors)).into())250 }251 Self::Sum(types) => {252 for ty in types.iter() {253 ty.check(value)?254 }255 Ok(())256 }257 Self::SumRef(types) => {258 for ty in types.iter() {259 ty.check(value)?260 }261 Ok(())262 }263 }264 }265}