Skip to main content

graphix_compiler/typ/
print.rs

1use crate::{
2    expr::print::{PrettyBuf, PrettyDisplay},
3    typ::{Type, TypeRef},
4    PrintFlag, PRINT_FLAGS,
5};
6use netidx::publisher::Typ;
7use std::fmt::{self, Write};
8
9impl fmt::Display for Type {
10    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11        match self {
12            Self::Abstract { id, params } if params.is_empty() => write!(f, "abstract"),
13            Self::Abstract { id, params: _ } => write!(f, "<abstract#{}>", id.0),
14            Self::Bottom => write!(f, "_"),
15            Self::Any => write!(f, "Any"),
16            Self::Ref (TypeRef { scope: _, name, params , ..}) => {
17                write!(f, "{name}")?;
18                if !params.is_empty() {
19                    write!(f, "<")?;
20                    for (i, t) in params.iter().enumerate() {
21                        write!(f, "{t}")?;
22                        if i < params.len() - 1 {
23                            write!(f, ", ")?;
24                        }
25                    }
26                    write!(f, ">")?;
27                }
28                Ok(())
29            }
30            Self::TVar(tv) => write!(f, "{tv}"),
31            Self::Fn(t) => write!(f, "{t}"),
32            Self::Error(t) => write!(f, "Error<{t}>"),
33            Self::Array(t) => write!(f, "Array<{t}>"),
34            Self::Map { key, value } => write!(f, "Map<{key}, {value}>"),
35            Self::ByRef(t) => write!(f, "&{t}"),
36            Self::Tuple(ts) => {
37                write!(f, "(")?;
38                for (i, t) in ts.iter().enumerate() {
39                    write!(f, "{t}")?;
40                    if i < ts.len() - 1 {
41                        write!(f, ", ")?;
42                    }
43                }
44                write!(f, ")")
45            }
46            Self::Variant(tag, ts) if ts.len() == 0 => {
47                write!(f, "`{tag}")
48            }
49            Self::Variant(tag, ts) => {
50                write!(f, "`{tag}(")?;
51                for (i, t) in ts.iter().enumerate() {
52                    write!(f, "{t}")?;
53                    if i < ts.len() - 1 {
54                        write!(f, ", ")?
55                    }
56                }
57                write!(f, ")")
58            }
59            Self::Struct(ts) => {
60                write!(f, "{{")?;
61                for (i, (n, t)) in ts.iter().enumerate() {
62                    write!(f, "{n}: {t}")?;
63                    if i < ts.len() - 1 {
64                        write!(f, ", ")?
65                    }
66                }
67                write!(f, "}}")
68            }
69            Self::Set(s) => {
70                write!(f, "[")?;
71                for (i, t) in s.iter().enumerate() {
72                    write!(f, "{t}")?;
73                    if i < s.len() - 1 {
74                        write!(f, ", ")?;
75                    }
76                }
77                write!(f, "]")
78            }
79            Self::Primitive(s) => {
80                let replace = PRINT_FLAGS.get().contains(PrintFlag::ReplacePrims);
81                if replace && *s == Typ::number() {
82                    write!(f, "Number")
83                } else if replace && *s == Typ::float() {
84                    write!(f, "Float")
85                } else if replace && *s == Typ::real() {
86                    write!(f, "Real")
87                } else if replace && *s == Typ::integer() {
88                    write!(f, "Int")
89                } else if replace && *s == Typ::unsigned_integer() {
90                    write!(f, "Uint")
91                } else if replace && *s == Typ::signed_integer() {
92                    write!(f, "Sint")
93                } else if s.len() == 0 {
94                    write!(f, "[]")
95                } else if s.len() == 1 {
96                    write!(f, "{}", s.iter().next().unwrap())
97                } else {
98                    let mut s = *s;
99                    macro_rules! builtin {
100                        ($set:expr, $name:literal) => {
101                            if replace && s.contains($set) {
102                                s.remove($set);
103                                write!(f, $name)?;
104                                if !s.is_empty() {
105                                    write!(f, ", ")?
106                                }
107                            }
108                        };
109                    }
110                    write!(f, "[")?;
111                    builtin!(Typ::number(), "Number");
112                    builtin!(Typ::real(), "Real");
113                    builtin!(Typ::float(), "Float");
114                    builtin!(Typ::integer(), "Int");
115                    builtin!(Typ::unsigned_integer(), "Uint");
116                    builtin!(Typ::signed_integer(), "Sint");
117                    for (i, t) in s.iter().enumerate() {
118                        write!(f, "{t}")?;
119                        if i < s.len() - 1 {
120                            write!(f, ", ")?;
121                        }
122                    }
123                    write!(f, "]")
124                }
125            }
126        }
127    }
128}
129
130impl PrettyDisplay for Type {
131    fn fmt_pretty_inner(&self, buf: &mut PrettyBuf) -> fmt::Result {
132        match self {
133            Self::Abstract { .. } => writeln!(buf, "{self}"),
134            Self::Bottom => writeln!(buf, "_"),
135            Self::Any => writeln!(buf, "Any"),
136            Self::Ref (TypeRef { scope: _, name, params , ..}) => {
137                if params.is_empty() {
138                    writeln!(buf, "{name}")
139                } else {
140                    writeln!(buf, "{name}<")?;
141                    buf.with_indent(2, |buf| {
142                        for (i, t) in params.iter().enumerate() {
143                            t.fmt_pretty(buf)?;
144                            if i < params.len() - 1 {
145                                buf.kill_newline();
146                                writeln!(buf, ",")?;
147                            }
148                        }
149                        Ok(())
150                    })?;
151                    writeln!(buf, ">")
152                }
153            }
154            Self::TVar(tv) => writeln!(buf, "{tv}"),
155            Self::Fn(t) => t.fmt_pretty(buf),
156            Self::Error(t) => {
157                writeln!(buf, "Error<")?;
158                buf.with_indent(2, |buf| t.fmt_pretty(buf))?;
159                writeln!(buf, ">")
160            }
161            Self::Array(t) => {
162                writeln!(buf, "Array<")?;
163                buf.with_indent(2, |buf| t.fmt_pretty(buf))?;
164                writeln!(buf, ">")
165            }
166            Self::Map { key, value } => {
167                writeln!(buf, "Map<")?;
168                buf.with_indent(2, |buf| {
169                    key.fmt_pretty(buf)?;
170                    buf.kill_newline();
171                    writeln!(buf, ",")?;
172                    value.fmt_pretty(buf)
173                })?;
174                writeln!(buf, ">")
175            }
176            Self::ByRef(t) => {
177                write!(buf, "&")?;
178                t.fmt_pretty(buf)
179            }
180            Self::Tuple(ts) => {
181                writeln!(buf, "(")?;
182                buf.with_indent(2, |buf| {
183                    for (i, t) in ts.iter().enumerate() {
184                        t.fmt_pretty(buf)?;
185                        if i < ts.len() - 1 {
186                            buf.kill_newline();
187                            writeln!(buf, ",")?;
188                        }
189                    }
190                    Ok(())
191                })?;
192                writeln!(buf, ")")
193            }
194            Self::Variant(tag, ts) if ts.is_empty() => writeln!(buf, "`{tag}"),
195            Self::Variant(tag, ts) => {
196                writeln!(buf, "`{tag}(")?;
197                buf.with_indent(2, |buf| {
198                    for (i, t) in ts.iter().enumerate() {
199                        t.fmt_pretty(buf)?;
200                        if i < ts.len() - 1 {
201                            buf.kill_newline();
202                            writeln!(buf, ",")?;
203                        }
204                    }
205                    Ok(())
206                })?;
207                writeln!(buf, ")")
208            }
209            Self::Struct(ts) => {
210                writeln!(buf, "{{")?;
211                buf.with_indent(2, |buf| {
212                    for (i, (n, t)) in ts.iter().enumerate() {
213                        write!(buf, "{n}: ")?;
214                        buf.with_indent(2, |buf| t.fmt_pretty(buf))?;
215                        if i < ts.len() - 1 {
216                            buf.kill_newline();
217                            writeln!(buf, ",")?;
218                        }
219                    }
220                    Ok(())
221                })?;
222                writeln!(buf, "}}")
223            }
224            Self::Set(s) => {
225                writeln!(buf, "[")?;
226                buf.with_indent(2, |buf| {
227                    for (i, t) in s.iter().enumerate() {
228                        t.fmt_pretty(buf)?;
229                        if i < s.len() - 1 {
230                            buf.kill_newline();
231                            writeln!(buf, ",")?;
232                        }
233                    }
234                    Ok(())
235                })?;
236                writeln!(buf, "]")
237            }
238            Self::Primitive(_) => {
239                // Primitives are simple enough to just use Display
240                writeln!(buf, "{self}")
241            }
242        }
243    }
244}