git.delta.rocks / jrsonnet / refs/commits / 0a2dd7a14884

difftreelog

feat(jrsonnet-types) implement gc

Yaroslav Bolyukin2021-06-05parent: #6794ed5.patch.diff
in: master
It is currently not possible to implement recursive type, so all tracing
is noop here

2 files changed

modifiedcrates/jrsonnet-types/Cargo.tomldiffbeforeafterboth
--- a/crates/jrsonnet-types/Cargo.toml
+++ b/crates/jrsonnet-types/Cargo.toml
@@ -8,3 +8,4 @@
 
 [dependencies]
 peg = "0.7.0"
+gc = { version = "0.4.1", features = ["derive"] }
modifiedcrates/jrsonnet-types/src/lib.rsdiffbeforeafterboth
after · crates/jrsonnet-types/src/lib.rs
1#![allow(clippy::redundant_closure_call)]23use gc::{unsafe_empty_trace, Finalize, Trace};4use std::fmt::Display;56#[macro_export]7macro_rules! ty {8	((Array<number>)) => {{9		$crate::ComplexValType::ArrayRef(&$crate::ComplexValType::Simple($crate::ValType::Num))10	}};11	(array) => {12		$crate::ComplexValType::Simple($crate::ValType::Arr)13	};14	(boolean) => {15		$crate::ComplexValType::Simple($crate::ValType::Bool)16	};17	(null) => {18		$crate::ComplexValType::Simple($crate::ValType::Null)19	};20	(string) => {21		$crate::ComplexValType::Simple($crate::ValType::Str)22	};23	(char) => {24		$crate::ComplexValType::Char25	};26	(number) => {27		$crate::ComplexValType::Simple($crate::ValType::Num)28	};29	(BoundedNumber<($min:expr), ($max:expr)>) => {{30		$crate::ComplexValType::BoundedNumber($min, $max)31	}};32	(object) => {33		$crate::ComplexValType::Simple($crate::ValType::Obj)34	};35	(any) => {36		$crate::ComplexValType::Any37	};38	(function) => {39		$crate::ComplexValType::Simple($crate::ValType::Func)40	};41	(($($a:tt) |+)) => {{42		static CONTENTS: &'static [$crate::ComplexValType] = &[43			$(ty!($a)),+44		];45		$crate::ComplexValType::UnionRef(CONTENTS)46	}};47	(($($a:tt) &+)) => {{48		static CONTENTS: &'static [$crate::ComplexValType] = &[49			$(ty!($a)),+50		];51		$crate::ComplexValType::SumRef(CONTENTS)52	}};53}5455#[test]56fn test() {57	assert_eq!(58		ty!((Array<number>)),59		ComplexValType::ArrayRef(&ComplexValType::Simple(ValType::Num))60	);61	assert_eq!(ty!(array), ComplexValType::Simple(ValType::Arr));62	assert_eq!(ty!(any), ComplexValType::Any);63	assert_eq!(64		ty!((string | number)),65		ComplexValType::UnionRef(&[66			ComplexValType::Simple(ValType::Str),67			ComplexValType::Simple(ValType::Num)68		])69	);70	assert_eq!(71		format!("{}", ty!(((string & number) | (object & null)))),72		"string & number | object & null"73	);74	assert_eq!(format!("{}", ty!((string | array))), "string | array");75	assert_eq!(76		format!("{}", ty!(((string & number) | array))),77		"string & number | array"78	);79}8081#[derive(Debug, Clone, Copy, PartialEq, Eq)]82pub enum ValType {83	Bool,84	Null,85	Str,86	Num,87	Arr,88	Obj,89	Func,90}91impl Finalize for ValType {}92unsafe impl Trace for ValType {93	unsafe_empty_trace!();94}9596impl ValType {97	pub const fn name(&self) -> &'static str {98		use ValType::*;99		match self {100			Bool => "boolean",101			Null => "null",102			Str => "string",103			Num => "number",104			Arr => "array",105			Obj => "object",106			Func => "function",107		}108	}109}110111impl Display for ValType {112	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {113		write!(f, "{}", self.name())114	}115}116117#[derive(Debug, Clone, PartialEq)]118pub enum ComplexValType {119	Any,120	Char,121	Simple(ValType),122	BoundedNumber(Option<f64>, Option<f64>),123	Array(Box<ComplexValType>),124	ArrayRef(&'static ComplexValType),125	ObjectRef(&'static [(&'static str, ComplexValType)]),126	Union(Vec<ComplexValType>),127	UnionRef(&'static [ComplexValType]),128	Sum(Vec<ComplexValType>),129	SumRef(&'static [ComplexValType]),130}131impl Finalize for ComplexValType {}132unsafe impl Trace for ComplexValType {133	unsafe_empty_trace!();134}135136impl From<ValType> for ComplexValType {137	fn from(s: ValType) -> Self {138		Self::Simple(s)139	}140}141142fn write_union(143	f: &mut std::fmt::Formatter<'_>,144	is_union: bool,145	union: &[ComplexValType],146) -> std::fmt::Result {147	for (i, v) in union.iter().enumerate() {148		let should_add_braces =149			matches!(v, ComplexValType::UnionRef(_) | ComplexValType::Union(_) if !is_union);150		if i != 0 {151			write!(f, " {} ", if is_union { '|' } else { '&' })?;152		}153		if should_add_braces {154			write!(f, "(")?;155		}156		write!(f, "{}", v)?;157		if should_add_braces {158			write!(f, ")")?;159		}160	}161	Ok(())162}163164fn print_array(a: &ComplexValType, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {165	if *a == ComplexValType::Any {166		write!(f, "array")?167	} else {168		write!(f, "Array<{}>", a)?169	}170	Ok(())171}172173impl Display for ComplexValType {174	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {175		match self {176			ComplexValType::Any => write!(f, "any")?,177			ComplexValType::Simple(s) => write!(f, "{}", s)?,178			ComplexValType::Char => write!(f, "char")?,179			ComplexValType::BoundedNumber(a, b) => write!(180				f,181				"BoundedNumber<{}, {}>",182				a.map(|e| e.to_string()).unwrap_or_else(|| "".into()),183				b.map(|e| e.to_string()).unwrap_or_else(|| "".into())184			)?,185			ComplexValType::ArrayRef(a) => print_array(a, f)?,186			ComplexValType::Array(a) => print_array(a, f)?,187			ComplexValType::ObjectRef(fields) => {188				write!(f, "{{")?;189				for (i, (k, v)) in fields.iter().enumerate() {190					if i != 0 {191						write!(f, ", ")?;192					}193					write!(f, "{}: {}", k, v)?;194				}195				write!(f, "}}")?;196			}197			ComplexValType::Union(v) => write_union(f, true, v)?,198			ComplexValType::UnionRef(v) => write_union(f, true, v)?,199			ComplexValType::Sum(v) => write_union(f, false, v)?,200			ComplexValType::SumRef(v) => write_union(f, false, v)?,201		};202		Ok(())203	}204}205206peg::parser! {207pub grammar parser() for str {208	rule number() -> f64209		= n:$(['0'..='9']+) { n.parse().unwrap() }210211	rule any_ty() -> ComplexValType = "any" { ComplexValType::Any }212	rule char_ty() -> ComplexValType = "character" { ComplexValType::Char }213	rule bool_ty() -> ComplexValType = "boolean" { ComplexValType::Simple(ValType::Bool) }214	rule null_ty() -> ComplexValType = "null" { ComplexValType::Simple(ValType::Null) }215	rule str_ty() -> ComplexValType = "string" { ComplexValType::Simple(ValType::Str) }216	rule num_ty() -> ComplexValType = "number" { ComplexValType::Simple(ValType::Num) }217	rule simple_array_ty() -> ComplexValType = "array" { ComplexValType::Simple(ValType::Arr) }218	rule simple_object_ty() -> ComplexValType = "object" { ComplexValType::Simple(ValType::Obj) }219	rule simple_function_ty() -> ComplexValType = "function" { ComplexValType::Simple(ValType::Func) }220221	rule array_ty() -> ComplexValType222		= "Array<" t:ty() ">" { ComplexValType::Array(Box::new(t)) }223224	rule bounded_number_ty() -> ComplexValType225		= "BoundedNumber<" a:number() ", " b:number() ">" { ComplexValType::BoundedNumber(Some(a), Some(b)) }226227	rule ty_basic() -> ComplexValType228		= any_ty()229		/ char_ty()230		/ bool_ty()231		/ null_ty()232		/ str_ty()233		/ num_ty()234		/ simple_array_ty()235		/ simple_object_ty()236		/ simple_function_ty()237		/ array_ty()238		/ bounded_number_ty()239240	pub rule ty() -> ComplexValType241		= precedence! {242			a:(@) " | " b:@ {243				match a {244					ComplexValType::Union(mut a) => {245						a.push(b);246						ComplexValType::Union(a)247					}248					_ => ComplexValType::Union(vec![a, b]),249				}250			}251			--252			a:(@) " & " b:@ {253				match a {254					ComplexValType::Sum(mut a) => {255						a.push(b);256						ComplexValType::Sum(a)257					}258					_ => ComplexValType::Sum(vec![a, b]),259				}260			}261			--262			"(" t:ty() ")" { t }263			t:ty_basic() { t }264		}265}266}267268#[cfg(test)]269pub mod tests {270	use super::parser;271272	#[test]273	fn precedence() {274		assert_eq!(275			parser::ty("(any & any) | (any | any) & any")276				.unwrap()277				.to_string(),278			"any & any | (any | any) & any"279		);280	}281282	#[test]283	fn array() {284		assert_eq!(parser::ty("Array<any>").unwrap().to_string(), "array");285		assert_eq!(286			parser::ty("Array<number>").unwrap().to_string(),287			"Array<number>"288		);289	}290	#[test]291	fn bounded_number() {292		assert_eq!(293			parser::ty("BoundedNumber<1, 2>").unwrap().to_string(),294			"BoundedNumber<1, 2>"295		);296	}297}