Skip to main content

lisette_syntax/
display.rs

1use std::fmt;
2
3use crate::types::Type;
4
5impl Type {
6    pub fn stringify(&self) -> String {
7        match self {
8            Type::Nominal {
9                id, params: args, ..
10            } => {
11                let args_formatted = args
12                    .iter()
13                    .map(|a| a.stringify())
14                    .collect::<Vec<_>>()
15                    .join(", ");
16
17                let name = id.last_segment();
18
19                if name == "Unit" {
20                    return "()".to_string();
21                }
22
23                if name == "bool" {
24                    return "bool".to_string();
25                }
26
27                if name.starts_with("Tuple") {
28                    return format!("({})", args_formatted);
29                }
30
31                if name == "Ref" {
32                    return format!("Ref<{}>", args_formatted);
33                }
34
35                if args.is_empty() {
36                    return name.to_string();
37                }
38
39                format!("{}<{}>", name, args_formatted)
40            }
41
42            Type::Var { id, hint } => match hint {
43                Some(name) => format!("?{}", name),
44                None => format!("?{}", id.as_u32()),
45            },
46
47            Type::Function {
48                params: args,
49                param_mutability,
50                return_type,
51                ..
52            } => {
53                let args_formatted = args
54                    .iter()
55                    .enumerate()
56                    .map(|(i, a)| {
57                        let is_mut = param_mutability.get(i).copied().unwrap_or(false);
58                        if is_mut {
59                            format!("mut {}", a.stringify())
60                        } else {
61                            a.stringify()
62                        }
63                    })
64                    .collect::<Vec<_>>()
65                    .join(", ");
66
67                let ret_formatted = (*return_type).stringify();
68
69                format!("fn ({}) -> {}", args_formatted, ret_formatted)
70            }
71
72            Type::Forall { .. } => {
73                unreachable!("Forall types are always instantiated before display")
74            }
75
76            Type::Parameter(name) => name.to_string(),
77
78            Type::Never => "Never".to_string(),
79
80            Type::Tuple(elements) => {
81                let formatted = elements
82                    .iter()
83                    .map(|e| e.stringify())
84                    .collect::<Vec<_>>()
85                    .join(", ");
86                format!("({})", formatted)
87            }
88
89            Type::Error => "<error>".to_string(),
90
91            Type::ImportNamespace(module_id) => {
92                let path = module_id.strip_prefix("go:").unwrap_or(module_id);
93                path.rsplit('/').next().unwrap_or(module_id).to_string()
94            }
95
96            Type::ReceiverPlaceholder => "self".to_string(),
97
98            Type::Simple(kind) => match kind {
99                crate::types::SimpleKind::Unit => "()".to_string(),
100                _ => kind.leaf_name().to_string(),
101            },
102
103            Type::Compound { kind, args } => {
104                let args_formatted = args
105                    .iter()
106                    .map(|a| a.stringify())
107                    .collect::<Vec<_>>()
108                    .join(", ");
109                if args.is_empty() {
110                    kind.leaf_name().to_string()
111                } else {
112                    format!("{}<{}>", kind.leaf_name(), args_formatted)
113                }
114            }
115        }
116    }
117}
118
119impl fmt::Display for Type {
120    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
121        let (types, _generics) = Self::remove_vars(&[self]);
122        write!(f, "{}", types[0].stringify())
123    }
124}