1use super::*;
2use crate::fmt::FmtAdapter;
3use std::{fmt::Display, format_args as fmt};
4
5impl<T: Display + Annotation, A: AstTypes> Display for At<T, A> {
6 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
7 write!(f, "{}", self.0)
8 }
9}
10
11impl<T: Annotation, A: AstTypes> std::fmt::Debug for At<T, A> {
12 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
13 <A::Annotation as std::fmt::Debug>::fmt(&self.1, f)?;
14 f.write_str(" ")?;
15 <T as std::fmt::Debug>::fmt(&self.0, f)
16 }
17}
18
19impl<A: AstTypes> Display for Expr<A> {
20 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21 match self {
22 Self::Omitted => "/* omitted */".fmt(f),
23 Self::Id(id) => id.fmt(f),
24 Self::MetId(id) => write!(f, "`{id}"),
25 Self::Lit(literal) => literal.fmt(f),
26 Self::Use(v) => write!(f, "use {v}"),
27 Self::Bind(v) => v.fmt(f),
28 Self::Make(v) => v.fmt(f),
29 Self::Match(v) => v.fmt(f),
30
31 Self::Op(op @ Op::Continue, exprs) => f.delimit(op, "").list(exprs, "!?,"),
32 Self::Op(op @ (Op::If | Op::While), exprs) => match exprs.as_slice() {
33 [cond, pass, At(Expr::Op(Op::Tuple, e), _)] if e.is_empty() => {
34 write!(f, "{op}{cond} {pass}")
35 }
36 [cond, pass, fail] => write!(f, "{op}{cond} {pass} else {fail}"),
37 other => f.delimit(fmt!("({op}, "), ")").list(other, ", "),
38 },
39 Self::Op(Op::Array, exprs) => f.delimit("[", "]").list(exprs, ", "),
40 Self::Op(Op::ArRep, exprs) => f.delimit("[", "]").list(exprs, "; "),
41 Self::Op(Op::Block, exprs) => f
42 .delimit_indented("{", "}")
43 .list_wrap("\n", exprs, "\n", "\n"),
44 Self::Op(Op::Tuple, exprs) => f.delimit("(", ")").list(exprs, ", "),
45 Self::Op(Op::Group, exprs) => f.list(exprs, ", "),
46 Self::Op(Op::MetaInner, exprs) => match exprs.as_slice() {
47 [meta, expr @ ..] => f.delimit(fmt!("#![{meta}]\n"), "").list(expr, ","),
48 [] => write!(f, "#![]"),
49 },
50 Self::Op(Op::MetaOuter, exprs) => match exprs.as_slice() {
51 [meta, expr @ ..] => f.delimit(fmt!("#[{meta}]\n"), "").list(expr, ","),
52 [] => write!(f, "#[]"),
53 },
54
55 Self::Op(op @ Op::Call, exprs) => match exprs.as_slice() {
56 [callee, At(Expr::Op(Op::Tuple, args), _)] => {
57 f.delimit(fmt!("{callee}("), ")").list(args, ", ")
58 }
59 [callee, args @ ..] => f.delimit(fmt!("{callee}(?"), "?)").list(args, ", "),
60 [] => write!(f, "{op}"),
61 },
62 Self::Op(op @ Op::Index, exprs) => match exprs.as_slice() {
63 [callee, args @ ..] => f.delimit(fmt!("{callee}["), "]").list(args, ", "),
64 [] => write!(f, "{op}"),
65 },
66
67 Self::Op(op @ Op::Do, exprs) => f.list(exprs, op),
68 Self::Op(op @ Op::Macro, exprs) => f.delimit(op, "").list(exprs, " => "),
69 Self::Op(op @ Op::Try, exprs) => f.delimit("(", fmt!("){op}")).list(exprs, ", "),
70 Self::Op(op, exprs) => match exprs.as_slice() {
71 [one] => write!(f, "{op}{one}"),
72 many => f.delimit("(", ")").list(many, op),
73 },
74 }
75 }
76}
77
78impl Display for Op {
79 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
80 f.write_str(match self {
81 Op::Do => ";\n",
82 Op::As => " as ",
83 Op::Macro => "macro ",
84 Op::Block => "{}",
85 Op::Array => "[]",
86 Op::ArRep => "; ",
87 Op::Group => "()",
88 Op::Tuple => "()",
89 Op::MetaInner => "#![]",
90 Op::MetaOuter => "#[]",
91 Op::Try => "?",
92 Op::Index => "",
93 Op::Call => "",
94 Op::Pub => "pub ",
95 Op::Const => "const ",
96 Op::Static => "static ",
97 Op::Loop => "loop ",
98 Op::If => "if ",
99 Op::While => "while ",
100 Op::Break => "break ",
101 Op::Return => "return ",
102 Op::Continue => "continue",
103 Op::Dot => ".",
104 Op::RangeEx => "..",
105 Op::RangeIn => "..=",
106 Op::Neg => "-",
107 Op::Not => "!",
108 Op::Identity => "!!",
109 Op::Refer => "&",
110 Op::Deref => "*",
111 Op::Mul => " * ",
112 Op::Div => " / ",
113 Op::Rem => " % ",
114 Op::Add => " + ",
115 Op::Sub => " - ",
116 Op::Shl => " << ",
117 Op::Shr => " >> ",
118 Op::And => " & ",
119 Op::Xor => " ^ ",
120 Op::Or => " | ",
121 Op::Lt => " < ",
122 Op::Leq => " <= ",
123 Op::Eq => " == ",
124 Op::Neq => " != ",
125 Op::Geq => " >= ",
126 Op::Gt => " > ",
127 Op::LogAnd => " && ",
128 Op::LogXor => " ^^ ",
129 Op::LogOr => " || ",
130 Op::Set => " = ",
131 Op::MulSet => " *= ",
132 Op::DivSet => " /= ",
133 Op::RemSet => " %= ",
134 Op::AddSet => " += ",
135 Op::SubSet => " -= ",
136 Op::ShlSet => " <<= ",
137 Op::ShrSet => " >>= ",
138 Op::AndSet => " &= ",
139 Op::XorSet => " ^= ",
140 Op::OrSet => " |= ",
141 })
142 }
143}
144
145impl<A: AstTypes> Display for Use<A> {
146 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
147 match self {
148 Self::Glob => "*".fmt(f),
149 Self::Name(name) => name.fmt(f),
150 Self::Alias(name, alias) => write!(f, "{name} as {alias}"),
151 Self::Path(segment, rest) => write!(f, "{segment}::{rest}"),
152 Self::Tree(items) => match items.len() {
153 0 => "{}".fmt(f),
154 1..=3 => f.delimit("{ ", " }").list(items, ", "),
155 _ => f
156 .delimit_indented("{", "}")
157 .list_wrap("\n", items, ",\n", ",\n"),
158 },
159 }
160 }
161}
162
163impl<A: AstTypes> Display for Bind<A> {
164 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
165 let Self(op, gens, pat, exprs) = self;
166 op.fmt(f)?;
167 if !gens.is_empty() {
168 f.delimit("<", "> ").list(gens, ", ")?;
169 }
170
171 match (op, exprs.as_slice()) {
172 (_, [At(Expr::Omitted, _)]) => write!(f, "{pat}"),
173 (BindOp::Fn | BindOp::Mod | BindOp::Impl, [At(Expr::Op(Op::Block, _), _)]) => {
174 f.delimit(fmt!("{pat} "), "").list(exprs, ",!? ")
175 }
176 (BindOp::Fn, _) => f.delimit(fmt!("{pat} = "), "").list(exprs, ""),
177 (BindOp::Mod | BindOp::Impl, _) => f.delimit(fmt!("{pat} "), "").list(exprs, "!?;"),
178 (BindOp::Struct | BindOp::Enum, _) => match pat {
179 Pat::Op(PatOp::TypePrefixed, bind) => match bind.as_slice() {
180 [name, Pat::Op(PatOp::Record, parts)] => f
181 .delimit_indented(fmt!("{name} {{"), "}")
182 .list_wrap("\n", parts, ",\n", ",\n"),
183 [name, Pat::Op(PatOp::Tuple, parts)] => {
184 f.delimit(fmt!("{name}("), ")").list(parts, ", ")
185 }
186 _ => pat.fmt(f),
187 },
188 _ => pat.fmt(f),
189 },
190 (BindOp::For, [iter, pass, At(Expr::Op(Op::Tuple, e), _)]) if e.is_empty() => {
191 write!(f, "{pat} in {iter} {pass}")
192 }
193 (BindOp::For, [iter, pass, fail]) => write!(f, "{pat} in {iter} {pass} else {fail}"),
194 (BindOp::For, other) => f.delimit(fmt!("{pat} in [["), "]]!?").list(other, ", "),
195 (_, []) => write!(f, "{pat}"),
196 (_, [value]) => write!(f, "{pat} = {value}"),
197 (_, [value, fail]) => write!(f, "{pat} = {value} else {fail}"),
198
199 (_, other) => f.delimit(fmt!("{pat} ("), ")").list(other, ", "),
200 }
201 }
202}
203
204impl Display for BindOp {
205 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
206 f.write_str(match self {
207 Self::Let => "let ",
208 Self::Type => "type ",
209 Self::Struct => "struct ",
210 Self::Enum => "enum ",
211 Self::Fn => "fn ",
212 Self::Mod => "mod ",
213 Self::Impl => "impl ",
214 Self::For => "for ",
215 })
216 }
217}
218
219impl<A: AstTypes> Display for Make<A> {
220 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
221 let Self(expr, make_arms) = self;
222 f.delimit(fmt!("({expr} {{"), "})").list(make_arms, ", ")
223 }
224}
225
226impl<A: AstTypes> Display for MakeArm<A> {
227 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
228 match self {
229 Self(name, Some(body)) => write!(f, "{name}: {body}"),
230 Self(name, None) => write!(f, "{name}"),
231 }
232 }
233}
234
235impl<A: AstTypes> Display for Match<A> {
236 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
237 let Self(scrutinee, arms) = self;
238 f.delimit_indented(fmt!("match {scrutinee} {{"), "}")
239 .list_wrap("\n", arms, ",\n", ",\n")
240 }
241}
242
243impl<A: AstTypes> Display for MatchArm<A> {
244 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
245 let Self(pat, expr) = self;
246 write!(f, "{pat} => {expr}")
247 }
248}
249
250impl<A: AstTypes> Display for Pat<A> {
251 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
252 match self {
253 Self::Ignore => "_".fmt(f),
254 Self::Never => "!".fmt(f),
255 Self::Value(literal) => literal.fmt(f),
256 Self::MetId(name) => write!(f, "`{name}"),
257 Self::Name(name) => name.fmt(f),
258 Self::Op(PatOp::Record, pats) => f.delimit("{ ", " }").list(pats, ", "),
259 Self::Op(PatOp::Tuple, pats) => f.delimit("(", ")").list(pats, ", "),
260 Self::Op(PatOp::Slice, pats) => f.delimit("[", "]").list(pats, ", "),
261 Self::Op(op @ PatOp::ArRep, pats) => f.delimit("[", "]").list(pats, op),
262 Self::Op(op @ (PatOp::Typed | PatOp::Fn), pats) => match pats.as_slice() {
263 [fun] => write!(f, "fn {fun}"), pats => f.list(pats, op),
265 },
266 Self::Op(op @ PatOp::Alt, pats) => f.list(pats, op),
267 Self::Op(op @ PatOp::Generic, pats) => match pats.as_slice() {
268 [] => op.fmt(f),
269 [first, rest @ ..] => f.delimit(fmt!("{first}<"), ">").list(rest, ", "),
270 },
271 Self::Op(op @ PatOp::TypePrefixed, pats) => match pats.as_slice() {
272 [] => op.fmt(f),
273 [first, rest @ ..] => f.delimit(fmt!("{first} "), "").list(rest, ",? "),
274 },
275 Self::Op(op, pats) => match pats.as_slice() {
276 [] => op.fmt(f),
277 [rest] => write!(f, "{op}{rest}"),
278 _ => f.delimit("(", ")").list(pats, op),
279 },
280 }
281 }
282}
283
284impl Display for PatOp {
285 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
286 f.write_str(match self {
287 Self::Pub => "pub ",
288 Self::Mut => "mut ",
289 Self::Ref => "&",
290 Self::Ptr => "*",
291 Self::Rest => "..",
292 Self::RangeEx => "..",
293 Self::RangeIn => "..=",
294 Self::Record => ", ",
295 Self::Tuple => ", ",
296 Self::Slice => ", ",
297 Self::ArRep => "; ",
298 Self::Typed => ": ",
299 Self::Generic => "T<>",
300 Self::TypePrefixed => "T()",
301 Self::Fn => " -> ",
302 Self::Alt => " | ",
303 })
304 }
305}