Skip to main content

graphix_compiler/typ/
print.rs

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