difftreelog
feat(jrsonnet-types) implement gc
in: master
It is currently not possible to implement recursive type, so all tracing is noop here
2 files changed
crates/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"] }
crates/jrsonnet-types/src/lib.rsdiffbeforeafterboth1#![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}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}