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
before · crates/jrsonnet-types/src/lib.rs
1#![allow(clippy::redundant_closure_call)]23use std::fmt::Display;45#[macro_export]6macro_rules! ty {7	((Array<number>)) => {{8		$crate::ComplexValType::ArrayRef(&$crate::ComplexValType::Simple($crate::ValType::Num))9	}};10	(array) => {11		$crate::ComplexValType::Simple($crate::ValType::Arr)12	};13	(boolean) => {14		$crate::ComplexValType::Simple($crate::ValType::Bool)15	};16	(null) => {17		$crate::ComplexValType::Simple($crate::ValType::Null)18	};19	(string) => {20		$crate::ComplexValType::Simple($crate::ValType::Str)21	};22	(char) => {23		$crate::ComplexValType::Char24	};25	(number) => {26		$crate::ComplexValType::Simple($crate::ValType::Num)27	};28	(BoundedNumber<($min:expr), ($max:expr)>) => {{29		$crate::ComplexValType::BoundedNumber($min, $max)30	}};31	(object) => {32		$crate::ComplexValType::Simple($crate::ValType::Obj)33	};34	(any) => {35		$crate::ComplexValType::Any36	};37	(function) => {38		$crate::ComplexValType::Simple($crate::ValType::Func)39	};40	(($($a:tt) |+)) => {{41		static CONTENTS: &'static [$crate::ComplexValType] = &[42			$(ty!($a)),+43		];44		$crate::ComplexValType::UnionRef(CONTENTS)45	}};46	(($($a:tt) &+)) => {{47		static CONTENTS: &'static [$crate::ComplexValType] = &[48			$(ty!($a)),+49		];50		$crate::ComplexValType::SumRef(CONTENTS)51	}};52}5354#[test]55fn test() {56	assert_eq!(57		ty!((Array<number>)),58		ComplexValType::ArrayRef(&ComplexValType::Simple(ValType::Num))59	);60	assert_eq!(ty!(array), ComplexValType::Simple(ValType::Arr));61	assert_eq!(ty!(any), ComplexValType::Any);62	assert_eq!(63		ty!((string | number)),64		ComplexValType::UnionRef(&[65			ComplexValType::Simple(ValType::Str),66			ComplexValType::Simple(ValType::Num)67		])68	);69	assert_eq!(70		format!("{}", ty!(((string & number) | (object & null)))),71		"string & number | object & null"72	);73	assert_eq!(format!("{}", ty!((string | array))), "string | array");74	assert_eq!(75		format!("{}", ty!(((string & number) | array))),76		"string & number | array"77	);78}7980#[derive(Debug, Clone, Copy, PartialEq, Eq)]81pub enum ValType {82	Bool,83	Null,84	Str,85	Num,86	Arr,87	Obj,88	Func,89}9091impl ValType {92	pub const fn name(&self) -> &'static str {93		use ValType::*;94		match self {95			Bool => "boolean",96			Null => "null",97			Str => "string",98			Num => "number",99			Arr => "array",100			Obj => "object",101			Func => "function",102		}103	}104}105106impl Display for ValType {107	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {108		write!(f, "{}", self.name())109	}110}111112#[derive(Debug, Clone, PartialEq)]113pub enum ComplexValType {114	Any,115	Char,116	Simple(ValType),117	BoundedNumber(Option<f64>, Option<f64>),118	Array(Box<ComplexValType>),119	ArrayRef(&'static ComplexValType),120	ObjectRef(&'static [(&'static str, ComplexValType)]),121	Union(Vec<ComplexValType>),122	UnionRef(&'static [ComplexValType]),123	Sum(Vec<ComplexValType>),124	SumRef(&'static [ComplexValType]),125}126impl From<ValType> for ComplexValType {127	fn from(s: ValType) -> Self {128		Self::Simple(s)129	}130}131132fn write_union(133	f: &mut std::fmt::Formatter<'_>,134	is_union: bool,135	union: &[ComplexValType],136) -> std::fmt::Result {137	for (i, v) in union.iter().enumerate() {138		let should_add_braces =139			matches!(v, ComplexValType::UnionRef(_) | ComplexValType::Union(_) if !is_union);140		if i != 0 {141			write!(f, " {} ", if is_union { '|' } else { '&' })?;142		}143		if should_add_braces {144			write!(f, "(")?;145		}146		write!(f, "{}", v)?;147		if should_add_braces {148			write!(f, ")")?;149		}150	}151	Ok(())152}153154fn print_array(a: &ComplexValType, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {155	if *a == ComplexValType::Any {156		write!(f, "array")?157	} else {158		write!(f, "Array<{}>", a)?159	}160	Ok(())161}162163impl Display for ComplexValType {164	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {165		match self {166			ComplexValType::Any => write!(f, "any")?,167			ComplexValType::Simple(s) => write!(f, "{}", s)?,168			ComplexValType::Char => write!(f, "char")?,169			ComplexValType::BoundedNumber(a, b) => write!(170				f,171				"BoundedNumber<{}, {}>",172				a.map(|e| e.to_string()).unwrap_or_else(|| "".into()),173				b.map(|e| e.to_string()).unwrap_or_else(|| "".into())174			)?,175			ComplexValType::ArrayRef(a) => print_array(a, f)?,176			ComplexValType::Array(a) => print_array(a, f)?,177			ComplexValType::ObjectRef(fields) => {178				write!(f, "{{")?;179				for (i, (k, v)) in fields.iter().enumerate() {180					if i != 0 {181						write!(f, ", ")?;182					}183					write!(f, "{}: {}", k, v)?;184				}185				write!(f, "}}")?;186			}187			ComplexValType::Union(v) => write_union(f, true, v)?,188			ComplexValType::UnionRef(v) => write_union(f, true, v)?,189			ComplexValType::Sum(v) => write_union(f, false, v)?,190			ComplexValType::SumRef(v) => write_union(f, false, v)?,191		};192		Ok(())193	}194}195196peg::parser! {197pub grammar parser() for str {198	rule number() -> f64199		= n:$(['0'..='9']+) { n.parse().unwrap() }200201	rule any_ty() -> ComplexValType = "any" { ComplexValType::Any }202	rule char_ty() -> ComplexValType = "character" { ComplexValType::Char }203	rule bool_ty() -> ComplexValType = "boolean" { ComplexValType::Simple(ValType::Bool) }204	rule null_ty() -> ComplexValType = "null" { ComplexValType::Simple(ValType::Null) }205	rule str_ty() -> ComplexValType = "string" { ComplexValType::Simple(ValType::Str) }206	rule num_ty() -> ComplexValType = "number" { ComplexValType::Simple(ValType::Num) }207	rule simple_array_ty() -> ComplexValType = "array" { ComplexValType::Simple(ValType::Arr) }208	rule simple_object_ty() -> ComplexValType = "object" { ComplexValType::Simple(ValType::Obj) }209	rule simple_function_ty() -> ComplexValType = "function" { ComplexValType::Simple(ValType::Func) }210211	rule array_ty() -> ComplexValType212		= "Array<" t:ty() ">" { ComplexValType::Array(Box::new(t)) }213214	rule bounded_number_ty() -> ComplexValType215		= "BoundedNumber<" a:number() ", " b:number() ">" { ComplexValType::BoundedNumber(Some(a), Some(b)) }216217	rule ty_basic() -> ComplexValType218		= any_ty()219		/ char_ty()220		/ bool_ty()221		/ null_ty()222		/ str_ty()223		/ num_ty()224		/ simple_array_ty()225		/ simple_object_ty()226		/ simple_function_ty()227		/ array_ty()228		/ bounded_number_ty()229230	pub rule ty() -> ComplexValType231		= precedence! {232			a:(@) " | " b:@ {233				match a {234					ComplexValType::Union(mut a) => {235						a.push(b);236						ComplexValType::Union(a)237					}238					_ => ComplexValType::Union(vec![a, b]),239				}240			}241			--242			a:(@) " & " b:@ {243				match a {244					ComplexValType::Sum(mut a) => {245						a.push(b);246						ComplexValType::Sum(a)247					}248					_ => ComplexValType::Sum(vec![a, b]),249				}250			}251			--252			"(" t:ty() ")" { t }253			t:ty_basic() { t }254		}255}256}257258#[cfg(test)]259pub mod tests {260	use super::parser;261262	#[test]263	fn precedence() {264		assert_eq!(265			parser::ty("(any & any) | (any | any) & any")266				.unwrap()267				.to_string(),268			"any & any | (any | any) & any"269		);270	}271272	#[test]273	fn array() {274		assert_eq!(parser::ty("Array<any>").unwrap().to_string(), "array");275		assert_eq!(276			parser::ty("Array<number>").unwrap().to_string(),277			"Array<number>"278		);279	}280	#[test]281	fn bounded_number() {282		assert_eq!(283			parser::ty("BoundedNumber<1, 2>").unwrap().to_string(),284			"BoundedNumber<1, 2>"285		);286	}287}
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}