git.delta.rocks / jrsonnet / refs/commits / c93dcb40871d

difftreelog

fix use push_stack_frame in public macroses

Yaroslav Bolyukin2021-01-25parent: #21e57ff.patch.diff
in: master

2 files changed

modifiedcrates/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)
modifiedcrates/jrsonnet-evaluator/src/typed.rsdiffbeforeafterboth
before · crates/jrsonnet-evaluator/src/typed.rs
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, 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}
after · crates/jrsonnet-evaluator/src/typed.rs
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}