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

difftreelog

feat peg parsing for types

Yaroslav Bolyukin2021-01-12parent: #fe95a60.patch.diff
in: master

3 files changed

modifiedcrates/jrsonnet-evaluator/src/typed.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/typed.rs
+++ b/crates/jrsonnet-evaluator/src/typed.rs
@@ -158,6 +158,20 @@
 					Err(TypeError::ExpectedGot(self.clone(), value.value_type()).into())
 				}
 			}
+			ComplexValType::Array(elem_type) => match value {
+				Val::Arr(a) => {
+					for (i, item) in a.iter().enumerate() {
+						push_type(
+							&None,
+							|| format!("array index {}", i),
+							|| ValuePathItem::Index(i as u64),
+							|| Ok(elem_type.check(&item.clone()?)?),
+						)?;
+					}
+					Ok(())
+				}
+				v => return Err(TypeError::ExpectedGot(self.clone(), v.value_type()).into()),
+			},
 			ComplexValType::ArrayRef(elem_type) => match value {
 				Val::Arr(a) => {
 					for (i, item) in a.iter().enumerate() {
@@ -192,6 +206,21 @@
 				}
 				v => return Err(TypeError::ExpectedGot(self.clone(), v.value_type()).into()),
 			},
+			ComplexValType::Union(types) => {
+				let mut errors = Vec::new();
+				for ty in types.iter() {
+					match ty.check(value) {
+						Ok(()) => {
+							return Ok(());
+						}
+						Err(e) => match e.error() {
+							Error::TypeError(e) => errors.push(e.clone()),
+							_ => return Err(e),
+						},
+					}
+				}
+				return Err(TypeError::UnionFailed(self.clone(), TypeLocErrorList(errors)).into());
+			}
 			ComplexValType::UnionRef(types) => {
 				let mut errors = Vec::new();
 				for ty in types.iter() {
@@ -207,6 +236,12 @@
 				}
 				return Err(TypeError::UnionFailed(self.clone(), TypeLocErrorList(errors)).into());
 			}
+			ComplexValType::Sum(types) => {
+				for ty in types.iter() {
+					ty.check(value)?
+				}
+				Ok(())
+			}
 			ComplexValType::SumRef(types) => {
 				for ty in types.iter() {
 					ty.check(value)?
modifiedcrates/jrsonnet-types/Cargo.tomldiffbeforeafterboth
--- a/crates/jrsonnet-types/Cargo.toml
+++ b/crates/jrsonnet-types/Cargo.toml
@@ -5,3 +5,4 @@
 edition = "2018"
 
 [dependencies]
+peg = "0.6.3"
\ No newline at end of file
modifiedcrates/jrsonnet-types/src/lib.rsdiffbeforeafterboth
before · crates/jrsonnet-types/src/lib.rs
1use std::fmt::Display;23#[macro_export]4macro_rules! ty {5	((Array<number>)) => {{6		$crate::ComplexValType::ArrayRef(&$crate::ComplexValType::Simple($crate::ValType::Num))7	}};8	(array) => {9		$crate::ComplexValType::Simple($crate::ValType::Arr)10	};11	(boolean) => {12		$crate::ComplexValType::Simple($crate::ValType::Bool)13	};14	(null) => {15		$crate::ComplexValType::Simple($crate::ValType::Null)16	};17	(string) => {18		$crate::ComplexValType::Simple($crate::ValType::Str)19	};20	(char) => {21		$crate::ComplexValType::Char22	};23	(number) => {24		$crate::ComplexValType::Simple($crate::ValType::Num)25	};26	(BoundedNumber<($min:expr), ($max:expr)>) => {{27		$crate::ComplexValType::BoundedNumber($min, $max)28	}};29	(object) => {30		$crate::ComplexValType::Simple($crate::ValType::Obj)31	};32	(any) => {33		$crate::ComplexValType::Any34	};35	(function) => {36		$crate::ComplexValType::Simple($crate::ValType::Func)37	};38	(($($a:tt) |+)) => {{39		static CONTENTS: &'static [$crate::ComplexValType] = &[40			$(ty!($a)),+41		];42		$crate::ComplexValType::UnionRef(CONTENTS)43	}};44	(($($a:tt) &+)) => {{45		static CONTENTS: &'static [$crate::ComplexValType] = &[46			$(ty!($a)),+47		];48		$crate::ComplexValType::SumRef(CONTENTS)49	}};50}5152#[test]53fn test() {54	assert_eq!(55		ty!((Array<number>)),56		ComplexValType::ArrayRef(&ComplexValType::Simple(ValType::Num))57	);58	assert_eq!(ty!(array), ComplexValType::Simple(ValType::Arr));59	assert_eq!(ty!(any), ComplexValType::Any);60	assert_eq!(61		ty!((string | number)),62		ComplexValType::UnionRef(&[63			ComplexValType::Simple(ValType::Str),64			ComplexValType::Simple(ValType::Num)65		])66	);67	assert_eq!(68		format!("{}", ty!(((string & number) | (object & null)))),69		"string & number | object & null"70	);71	assert_eq!(format!("{}", ty!((string | array))), "string | array");72	assert_eq!(format!("{}", ty!(((string & number) | array))), "string & number | array");73}7475#[derive(Debug, Clone, Copy, PartialEq, Eq)]76pub enum ValType {77	Bool,78	Null,79	Str,80	Num,81	Arr,82	Obj,83	Func,84}8586impl ValType {87	pub const fn name(&self) -> &'static str {88		use ValType::*;89		match self {90			Bool => "boolean",91			Null => "null",92			Str => "string",93			Num => "number",94			Arr => "array",95			Obj => "object",96			Func => "function",97		}98	}99}100101impl Display for ValType {102	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {103		write!(f, "{}", self.name())104	}105}106107#[derive(Debug, Clone, PartialEq)]108pub enum ComplexValType {109	Any,110	Char,111	Simple(ValType),112	BoundedNumber(Option<f64>, Option<f64>),113	ArrayRef(&'static ComplexValType),114	ObjectRef(&'static [(&'static str, ComplexValType)]),115	UnionRef(&'static [ComplexValType]),116	SumRef(&'static [ComplexValType]),117}118impl From<ValType> for ComplexValType {119	fn from(s: ValType) -> Self {120		Self::Simple(s)121	}122}123124fn write_union(125	f: &mut std::fmt::Formatter<'_>,126	is_union: bool,127	union: &[ComplexValType],128) -> std::fmt::Result {129	for (i, v) in union.iter().enumerate() {130		let should_add_braces = match v {131			ComplexValType::UnionRef(_) if !is_union => true,132			_ => false,133		};134		if i != 0 {135			write!(f, " {} ", if is_union { '|' } else { '&' })?;136		}137		if should_add_braces {138			write!(f, "(")?;139		}140		write!(f, "{}", v)?;141		if should_add_braces {142			write!(f, ")")?;143		}144	}145	Ok(())146}147148impl Display for ComplexValType {149	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {150		match self {151			ComplexValType::Any => write!(f, "any")?,152			ComplexValType::Simple(s) => write!(f, "{}", s)?,153			ComplexValType::Char => write!(f, "char")?,154			ComplexValType::BoundedNumber(a, b) => write!(155				f,156				"BoundedNumber<{}, {}>",157				a.map(|e| e.to_string()).unwrap_or_else(|| "".into()),158				b.map(|e| e.to_string()).unwrap_or_else(|| "".into())159			)?,160			ComplexValType::ArrayRef(a) => {161				if **a == ComplexValType::Any {162					write!(f, "array")?163				} else {164					write!(f, "Array<{}>", a)?165				}166			}167			ComplexValType::ObjectRef(fields) => {168				write!(f, "{{")?;169				for (i, (k, v)) in fields.iter().enumerate() {170					if i != 0 {171						write!(f, ", ")?;172					}173					write!(f, "{}: {}", k, v)?;174				}175				write!(f, "}}")?;176			}177			ComplexValType::UnionRef(v) => write_union(f, true, v)?,178			ComplexValType::SumRef(v) => write_union(f, false, v)?,179		};180		Ok(())181	}182}
after · crates/jrsonnet-types/src/lib.rs
1use std::fmt::Display;23#[macro_export]4macro_rules! ty {5	((Array<number>)) => {{6		$crate::ComplexValType::ArrayRef(&$crate::ComplexValType::Simple($crate::ValType::Num))7	}};8	(array) => {9		$crate::ComplexValType::Simple($crate::ValType::Arr)10	};11	(boolean) => {12		$crate::ComplexValType::Simple($crate::ValType::Bool)13	};14	(null) => {15		$crate::ComplexValType::Simple($crate::ValType::Null)16	};17	(string) => {18		$crate::ComplexValType::Simple($crate::ValType::Str)19	};20	(char) => {21		$crate::ComplexValType::Char22	};23	(number) => {24		$crate::ComplexValType::Simple($crate::ValType::Num)25	};26	(BoundedNumber<($min:expr), ($max:expr)>) => {{27		$crate::ComplexValType::BoundedNumber($min, $max)28	}};29	(object) => {30		$crate::ComplexValType::Simple($crate::ValType::Obj)31	};32	(any) => {33		$crate::ComplexValType::Any34	};35	(function) => {36		$crate::ComplexValType::Simple($crate::ValType::Func)37	};38	(($($a:tt) |+)) => {{39		static CONTENTS: &'static [$crate::ComplexValType] = &[40			$(ty!($a)),+41		];42		$crate::ComplexValType::UnionRef(CONTENTS)43	}};44	(($($a:tt) &+)) => {{45		static CONTENTS: &'static [$crate::ComplexValType] = &[46			$(ty!($a)),+47		];48		$crate::ComplexValType::SumRef(CONTENTS)49	}};50}5152#[test]53fn test() {54	assert_eq!(55		ty!((Array<number>)),56		ComplexValType::ArrayRef(&ComplexValType::Simple(ValType::Num))57	);58	assert_eq!(ty!(array), ComplexValType::Simple(ValType::Arr));59	assert_eq!(ty!(any), ComplexValType::Any);60	assert_eq!(61		ty!((string | number)),62		ComplexValType::UnionRef(&[63			ComplexValType::Simple(ValType::Str),64			ComplexValType::Simple(ValType::Num)65		])66	);67	assert_eq!(68		format!("{}", ty!(((string & number) | (object & null)))),69		"string & number | object & null"70	);71	assert_eq!(format!("{}", ty!((string | array))), "string | array");72	assert_eq!(format!("{}", ty!(((string & number) | array))), "string & number | array");73}7475#[derive(Debug, Clone, Copy, PartialEq, Eq)]76pub enum ValType {77	Bool,78	Null,79	Str,80	Num,81	Arr,82	Obj,83	Func,84}8586impl ValType {87	pub const fn name(&self) -> &'static str {88		use ValType::*;89		match self {90			Bool => "boolean",91			Null => "null",92			Str => "string",93			Num => "number",94			Arr => "array",95			Obj => "object",96			Func => "function",97		}98	}99}100101impl Display for ValType {102	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {103		write!(f, "{}", self.name())104	}105}106107#[derive(Debug, Clone, PartialEq)]108pub enum ComplexValType {109	Any,110	Char,111	Simple(ValType),112	BoundedNumber(Option<f64>, Option<f64>),113	Array(Box<ComplexValType>),114	ArrayRef(&'static ComplexValType),115	ObjectRef(&'static [(&'static str, ComplexValType)]),116	Union(Vec<ComplexValType>),117	UnionRef(&'static [ComplexValType]),118	Sum(Vec<ComplexValType>),119	SumRef(&'static [ComplexValType]),120}121impl From<ValType> for ComplexValType {122	fn from(s: ValType) -> Self {123		Self::Simple(s)124	}125}126127fn write_union(128	f: &mut std::fmt::Formatter<'_>,129	is_union: bool,130	union: &[ComplexValType],131) -> std::fmt::Result {132	for (i, v) in union.iter().enumerate() {133		let should_add_braces = match v {134			ComplexValType::UnionRef(_) | ComplexValType::Union(_) if !is_union => true,135			_ => false,136		};137		if i != 0 {138			write!(f, " {} ", if is_union { '|' } else { '&' })?;139		}140		if should_add_braces {141			write!(f, "(")?;142		}143		write!(f, "{}", v)?;144		if should_add_braces {145			write!(f, ")")?;146		}147	}148	Ok(())149}150151fn print_array(a: &ComplexValType, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {152	if *a == ComplexValType::Any {153		write!(f, "array")?154	} else {155		write!(f, "Array<{}>", a)?156	}157	Ok(())158}159160impl Display for ComplexValType {161	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {162		match self {163			ComplexValType::Any => write!(f, "any")?,164			ComplexValType::Simple(s) => write!(f, "{}", s)?,165			ComplexValType::Char => write!(f, "char")?,166			ComplexValType::BoundedNumber(a, b) => write!(167				f,168				"BoundedNumber<{}, {}>",169				a.map(|e| e.to_string()).unwrap_or_else(|| "".into()),170				b.map(|e| e.to_string()).unwrap_or_else(|| "".into())171			)?,172			ComplexValType::ArrayRef(a) => print_array(a, f)?,173			ComplexValType::Array(a) => print_array(a, f)?,174			ComplexValType::ObjectRef(fields) => {175				write!(f, "{{")?;176				for (i, (k, v)) in fields.iter().enumerate() {177					if i != 0 {178						write!(f, ", ")?;179					}180					write!(f, "{}: {}", k, v)?;181				}182				write!(f, "}}")?;183			}184			ComplexValType::Union(v) => write_union(f, true, v)?,185			ComplexValType::UnionRef(v) => write_union(f, true, v)?,186			ComplexValType::Sum(v) => write_union(f, false, v)?,187			ComplexValType::SumRef(v) => write_union(f, false, v)?,188		};189		Ok(())190	}191}192193peg::parser!{194pub grammar parser() for str {195	rule number() -> f64196		= n:$(['0'..='9']+) { n.parse().unwrap() }197198	rule any_ty() -> ComplexValType = "any" { ComplexValType::Any }199	rule char_ty() -> ComplexValType = "character" { ComplexValType::Char }200	rule bool_ty() -> ComplexValType = "boolean" { ComplexValType::Simple(ValType::Bool) }201	rule null_ty() -> ComplexValType = "null" { ComplexValType::Simple(ValType::Null) }202	rule str_ty() -> ComplexValType = "string" { ComplexValType::Simple(ValType::Str) }203	rule num_ty() -> ComplexValType = "number" { ComplexValType::Simple(ValType::Num) }204	rule simple_array_ty() -> ComplexValType = "array" { ComplexValType::Simple(ValType::Arr) }205	rule simple_object_ty() -> ComplexValType = "object" { ComplexValType::Simple(ValType::Obj) }206	rule simple_function_ty() -> ComplexValType = "function" { ComplexValType::Simple(ValType::Func) }207	208	rule array_ty() -> ComplexValType209		= "Array<" t:ty() ">" { ComplexValType::Array(Box::new(t)) }210211	rule bounded_number_ty() -> ComplexValType212		= "BoundedNumber<" a:number() ", " b:number() ">" { ComplexValType::BoundedNumber(Some(a), Some(b)) }213214	rule ty_basic() -> ComplexValType215		= any_ty()216		/ char_ty()217		/ bool_ty()218		/ null_ty()219		/ str_ty()220		/ num_ty()221		/ simple_array_ty()222		/ simple_object_ty()223		/ simple_function_ty()224		/ array_ty()225		/ bounded_number_ty()226227	pub rule ty() -> ComplexValType228		= precedence! {229			a:(@) " | " b:@ {230				match a {231					ComplexValType::Union(mut a) => {232						a.push(b);233						ComplexValType::Union(a)234					}235					_ => ComplexValType::Union(vec![a, b]),236				}237			}238			--239			a:(@) " & " b:@ {240				match a {241					ComplexValType::Sum(mut a) => {242						a.push(b);243						ComplexValType::Sum(a)244					}245					_ => ComplexValType::Sum(vec![a, b]),246				}247			}248			--249			"(" t:ty() ")" { t }250			t:ty_basic() { t }251		}252}253}254255#[cfg(test)]256pub mod tests {257	use super::parser;258259	#[test]260	fn precedence() {261		assert_eq!(parser::ty("(any & any) | (any | any) & any").unwrap().to_string(), "any & any | (any | any) & any");262	}263264	#[test]265	fn array() {266		assert_eq!(parser::ty("Array<any>").unwrap().to_string(), "array");267		assert_eq!(parser::ty("Array<number>").unwrap().to_string(), "Array<number>");268	}269	#[test]270	fn bounded_number() {271		assert_eq!(parser::ty("BoundedNumber<1, 2>").unwrap().to_string(), "BoundedNumber<1, 2>");272	}273}