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