difftreelog
feat describe jrsonnet type system
in: master
2 files changed
crates/jrsonnet-types/Cargo.tomldiffbeforeafterboth--- /dev/null
+++ b/crates/jrsonnet-types/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "jrsonnet-types"
+version = "0.3.2"
+authors = ["Yaroslav Bolyukin <iam@lach.pw>"]
+edition = "2018"
+
+[dependencies]
crates/jrsonnet-types/src/lib.rsdiffbeforeafterboth1use std::fmt::Display;23#[macro_export]4macro_rules! ty {5 ([$inner:tt]) => {{6 static VAL: &'static ComplexValType = &ty!($inner);7 match VAL {8 ComplexValType::Any => ComplexValType::Simple(ValType::Arr),9 _ => ComplexValType::ArrayRef(&VAL),10 }11 }};12 (bool) => {13 ComplexValType::Simple(ValType::Bool)14 };15 (null) => {16 ComplexValType::Simple(ValType::Null)17 };18 (str) => {19 ComplexValType::Simple(ValType::Str)20 };21 (char) => {22 ComplexValType::Char23 };24 (num) => {25 ComplexValType::Simple(ValType::Num)26 };27 (number(($min:expr)..($max:expr))) => {{28 ComplexValType::BoundedNumber($min, $max)29 }};30 (obj) => {31 ComplexValType::Simple(ValType::Obj)32 };33 (any) => {34 ComplexValType::Any35 };36 (fn.any) => {37 ComplexValType::Simple(ValType::Func)38 };39 (($($a:tt) |+)) => {{40 static CONTENTS: &'static [ComplexValType] = &[41 $(ty!($a)),+42 ];43 ComplexValType::UnionRef(CONTENTS)44 }};45 (($($a:tt) &+)) => {{46 static CONTENTS: &'static [ComplexValType] = &[47 $(ty!($a)),+48 ];49 ComplexValType::SumRef(CONTENTS)50 }};51}5253#[test]54fn test() {55 assert_eq!(56 ty!([num]),57 ComplexValType::ArrayRef(&ComplexValType::Simple(ValType::Num))58 );59 assert_eq!(ty!([any]), ComplexValType::Simple(ValType::Arr));60 assert_eq!(ty!(any), ComplexValType::Any);61 assert_eq!(62 ty!((str | num)),63 ComplexValType::UnionRef(&[64 ComplexValType::Simple(ValType::Str),65 ComplexValType::Simple(ValType::Num)66 ])67 );68 assert_eq!(69 format!("{}", ty!(((str & num) | (obj & null)))),70 "((str & num) | (obj & null))"71 );72 assert_eq!(format!("{}", ty!((str | [any]))), "(str | [any])");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 => "bool",91 Null => "null",92 Str => "str",93 Num => "num",94 Arr => "[any]",95 Obj => "obj",96 Func => "fn.any",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}123124impl ComplexValType {125 fn needs_brackets(&self) -> bool {126 matches!(self, ComplexValType::UnionRef(_) | ComplexValType::SumRef(_))127 }128}129130fn write_union(131 f: &mut std::fmt::Formatter<'_>,132 ch: char,133 union: &[ComplexValType],134) -> std::fmt::Result {135 write!(f, "(")?;136 for (i, v) in union.iter().enumerate() {137 if i != 0 {138 write!(f, " {} ", ch)?;139 }140 write!(f, "{}", v)?;141 }142 write!(f, ")")?;143 Ok(())144}145146impl Display for ComplexValType {147 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {148 match self {149 ComplexValType::Any => write!(f, "any")?,150 ComplexValType::Simple(s) => write!(f, "{}", s)?,151 ComplexValType::Char => write!(f, "char")?,152 ComplexValType::BoundedNumber(a, b) => write!(153 f,154 "number({}..{})",155 a.map(|e| e.to_string()).unwrap_or_else(|| "".into()),156 b.map(|e| e.to_string()).unwrap_or_else(|| "".into())157 )?,158 ComplexValType::ArrayRef(a) => {159 if a.needs_brackets() {160 write!(f, "(")?;161 }162 write!(f, "{}", a)?;163 if a.needs_brackets() {164 write!(f, ")")?;165 }166 write!(f, "[]")?;167 }168 ComplexValType::ObjectRef(fields) => {169 write!(f, "{{")?;170 for (i, (k, v)) in fields.iter().enumerate() {171 if i != 0 {172 write!(f, ", ")?;173 }174 write!(f, "{}: {}", k, v)?;175 }176 write!(f, "}}")?;177 }178 ComplexValType::UnionRef(v) => write_union(f, '|', v)?,179 ComplexValType::SumRef(v) => write_union(f, '&', v)?,180 };181 Ok(())182 }183}