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 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}