1use std::fmt;
2
3use crate::atomic::Atomic;
4use crate::union::Union;
5
6impl fmt::Display for Union {
7 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8 if self.types.is_empty() {
9 return write!(f, "never");
10 }
11 let strs: Vec<String> = self.types.iter().map(|a| format!("{}", a)).collect();
12 write!(f, "{}", strs.join("|"))
13 }
14}
15
16impl fmt::Display for Atomic {
17 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
18 match self {
19 Atomic::TString => write!(f, "string"),
20 Atomic::TLiteralString(s) => write!(f, "\"{}\"", s),
21 Atomic::TClassString(None) => write!(f, "class-string"),
22 Atomic::TClassString(Some(cls)) => write!(f, "class-string<{}>", cls),
23 Atomic::TNonEmptyString => write!(f, "non-empty-string"),
24 Atomic::TNumericString => write!(f, "numeric-string"),
25
26 Atomic::TInt => write!(f, "int"),
27 Atomic::TLiteralInt(n) => write!(f, "{}", n),
28 Atomic::TIntRange { min, max } => {
29 let lo = min
30 .map(|n| n.to_string())
31 .unwrap_or_else(|| "min".to_string());
32 let hi = max
33 .map(|n| n.to_string())
34 .unwrap_or_else(|| "max".to_string());
35 write!(f, "int<{}, {}>", lo, hi)
36 }
37 Atomic::TPositiveInt => write!(f, "positive-int"),
38 Atomic::TNegativeInt => write!(f, "negative-int"),
39 Atomic::TNonNegativeInt => write!(f, "non-negative-int"),
40
41 Atomic::TFloat => write!(f, "float"),
42 Atomic::TLiteralFloat(i, frac) => write!(f, "{}.{}", i, frac),
43
44 Atomic::TBool => write!(f, "bool"),
45 Atomic::TTrue => write!(f, "true"),
46 Atomic::TFalse => write!(f, "false"),
47
48 Atomic::TNull => write!(f, "null"),
49 Atomic::TVoid => write!(f, "void"),
50 Atomic::TNever => write!(f, "never"),
51 Atomic::TMixed => write!(f, "mixed"),
52 Atomic::TScalar => write!(f, "scalar"),
53 Atomic::TNumeric => write!(f, "numeric"),
54
55 Atomic::TObject => write!(f, "object"),
56 Atomic::TNamedObject { fqcn, type_params } => {
57 if type_params.is_empty() {
58 write!(f, "{}", fqcn)
59 } else {
60 let params: Vec<String> =
61 type_params.iter().map(|p| format!("{}", p)).collect();
62 write!(f, "{}<{}>", fqcn, params.join(", "))
63 }
64 }
65 Atomic::TStaticObject { fqcn } => write!(f, "static({})", fqcn),
66 Atomic::TSelf { fqcn } => write!(f, "self({})", fqcn),
67 Atomic::TParent { fqcn } => write!(f, "parent({})", fqcn),
68
69 Atomic::TCallable {
70 params: None,
71 return_type: None,
72 } => write!(f, "callable"),
73 Atomic::TCallable {
74 params: Some(params),
75 return_type,
76 } => {
77 let ps: Vec<String> = params
78 .iter()
79 .map(|p| {
80 if let Some(ty) = &p.ty {
81 format!("{}", ty)
82 } else {
83 "mixed".to_string()
84 }
85 })
86 .collect();
87 let ret = return_type
88 .as_ref()
89 .map(|r| format!("{}", r))
90 .unwrap_or_else(|| "mixed".to_string());
91 write!(f, "callable({}): {}", ps.join(", "), ret)
92 }
93 Atomic::TCallable {
94 params: None,
95 return_type: Some(ret),
96 } => {
97 write!(f, "callable(): {}", ret)
98 }
99 Atomic::TClosure {
100 params,
101 return_type,
102 ..
103 } => {
104 let ps: Vec<String> = params
105 .iter()
106 .map(|p| {
107 if let Some(ty) = &p.ty {
108 format!("{}", ty)
109 } else {
110 "mixed".to_string()
111 }
112 })
113 .collect();
114 write!(f, "Closure({}): {}", ps.join(", "), return_type)
115 }
116
117 Atomic::TArray { key, value } => {
118 write!(f, "array<{}, {}>", key, value)
119 }
120 Atomic::TList { value } => write!(f, "list<{}>", value),
121 Atomic::TNonEmptyArray { key, value } => {
122 write!(f, "non-empty-array<{}, {}>", key, value)
123 }
124 Atomic::TNonEmptyList { value } => write!(f, "non-empty-list<{}>", value),
125 Atomic::TKeyedArray { properties, .. } => {
126 let entries: Vec<String> = properties
127 .iter()
128 .map(|(k, v)| {
129 let key_str = match k {
130 crate::atomic::ArrayKey::String(s) => format!("'{}'", s),
131 crate::atomic::ArrayKey::Int(n) => n.to_string(),
132 };
133 let opt = if v.optional { "?" } else { "" };
134 format!("{}{}: {}", key_str, opt, v.ty)
135 })
136 .collect();
137 write!(f, "array{{{}}}", entries.join(", "))
138 }
139
140 Atomic::TTemplateParam { name, .. } => write!(f, "{}", name),
141 Atomic::TConditional {
142 subject,
143 if_true,
144 if_false,
145 } => {
146 write!(f, "({} is ? {} : {})", subject, if_true, if_false)
147 }
148
149 Atomic::TInterfaceString => write!(f, "interface-string"),
150 Atomic::TEnumString => write!(f, "enum-string"),
151 Atomic::TTraitString => write!(f, "trait-string"),
152 }
153 }
154}