1use rucc_base::{Interner, Symbol};
38
39use crate::kind::{ArrayLen, FunctionId, Qualifiers, Type, TypeKind};
40use crate::types::{TypeId, Types};
41
42#[must_use]
44pub fn spell(types: &Types, names: &Interner, id: TypeId) -> String {
45 Speller { types, names }.declaration(id, Declarator::nothing())
46}
47
48#[must_use]
50pub fn declare(types: &Types, names: &Interner, id: TypeId, name: Symbol) -> String {
51 Speller { types, names }.declaration(id, Declarator::of(names.resolve(name).to_owned()))
52}
53
54#[derive(Debug)]
57struct Declarator {
58 text: String,
60 glued: bool,
66}
67
68impl Declarator {
69 fn nothing() -> Declarator {
71 Declarator { text: String::new(), glued: false }
72 }
73
74 fn of(text: String) -> Declarator {
76 Declarator { text, glued: false }
77 }
78
79 fn suffixed(self, suffix: &str) -> Declarator {
82 let glued = self.glued || self.text.is_empty();
83 Declarator { text: self.text + suffix, glued }
84 }
85}
86
87#[derive(Debug)]
89struct Speller<'a> {
90 types: &'a Types,
91 names: &'a Interner,
92}
93
94impl Speller<'_> {
95 fn declaration(&self, id: TypeId, inner: Declarator) -> String {
101 let ty = self.types.get(id);
102 let base = match ty.kind {
103 TypeKind::Pointer(pointee) => return self.pointer(ty, pointee, inner),
104 TypeKind::Array { elem, len } => return self.array(ty, elem, len, inner),
105 TypeKind::Function(function) => return self.function(function, inner),
106 TypeKind::Void => String::from("void"),
107 TypeKind::Bool => String::from("_Bool"),
110 TypeKind::Int(kind) => String::from(kind.as_str()),
111 TypeKind::Float(kind) => String::from(kind.as_str()),
112 TypeKind::Complex(kind) => format!("_Complex {}", kind.as_str()),
113 TypeKind::BitInt { signed, width } => {
114 let sign = if signed { "" } else { "unsigned " };
115 format!("{sign}_BitInt({width})")
116 }
117 TypeKind::Atomic(inner) => format!("_Atomic({})", self.spell(inner)),
122 TypeKind::Vector { elem, len } => format!("__vector({len}) {}", self.spell(elem)),
125 TypeKind::Record(record) => {
126 let info = self.types.record_info(record);
127 format!("{} {}", info.kind.as_str(), self.tag(info.tag))
128 }
129 TypeKind::Enum(enumeration) => {
130 let info = self.types.enum_info(enumeration);
131 format!("enum {}", self.tag(info.tag))
132 }
133 TypeKind::Typedef { name, .. } => self.names.resolve(name).to_owned(),
134 };
135
136 let mut out = String::new();
137 if let Some(quals) = quals_text(ty.quals) {
138 out.push_str(quals);
139 out.push(' ');
140 }
141 out.push_str(&base);
142 if !inner.text.is_empty() {
143 if !inner.glued {
144 out.push(' ');
145 }
146 out.push_str(&inner.text);
147 }
148 out
149 }
150
151 fn pointer(&self, ty: Type, pointee: TypeId, inner: Declarator) -> String {
154 let mut declarator = String::from("*");
155 if let Some(quals) = quals_text(ty.quals) {
156 declarator.push_str(quals);
157 if !inner.text.is_empty() {
158 declarator.push(' ');
159 }
160 }
161 declarator.push_str(&inner.text);
162 if matches!(self.types.kind(pointee), TypeKind::Array { .. } | TypeKind::Function(_)) {
167 declarator = format!("({declarator})");
168 }
169 self.declaration(pointee, Declarator::of(declarator))
170 }
171
172 fn array(&self, ty: Type, elem: TypeId, len: ArrayLen, inner: Declarator) -> String {
174 let mut suffix = String::from("[");
175 if let Some(quals) = quals_text(ty.quals) {
176 suffix.push_str(quals);
177 if !matches!(len, ArrayLen::Unknown) {
178 suffix.push(' ');
179 }
180 }
181 match len {
182 ArrayLen::Fixed(count) => suffix.push_str(&count.to_string()),
183 ArrayLen::Unknown => {}
184 ArrayLen::Star | ArrayLen::Variable(_) => suffix.push('*'),
187 }
188 suffix.push(']');
189 self.declaration(elem, inner.suffixed(&suffix))
190 }
191
192 fn function(&self, function: FunctionId, inner: Declarator) -> String {
194 let signature = self.types.signature(function);
195 let mut suffix = String::from("(");
196 for (index, ¶m) in signature.params.iter().enumerate() {
197 if index > 0 {
198 suffix.push_str(", ");
199 }
200 suffix.push_str(&self.spell(param));
201 }
202 if signature.variadic {
203 if !signature.params.is_empty() {
204 suffix.push_str(", ");
205 }
206 suffix.push_str("...");
207 } else if signature.params.is_empty() && signature.prototyped {
208 suffix.push_str("void");
211 }
212 suffix.push(')');
213 self.declaration(signature.ret, inner.suffixed(&suffix))
214 }
215
216 fn spell(&self, id: TypeId) -> String {
218 self.declaration(id, Declarator::nothing())
219 }
220
221 fn tag(&self, tag: Option<Symbol>) -> String {
223 match tag {
224 Some(name) => self.names.resolve(name).to_owned(),
225 None => String::from("<anonymous>"),
226 }
227 }
228}
229
230fn quals_text(quals: Qualifiers) -> Option<&'static str> {
232 match (
235 quals.has(Qualifiers::CONST),
236 quals.has(Qualifiers::VOLATILE),
237 quals.has(Qualifiers::RESTRICT),
238 ) {
239 (false, false, false) => None,
240 (true, false, false) => Some("const"),
241 (false, true, false) => Some("volatile"),
242 (false, false, true) => Some("restrict"),
243 (true, true, false) => Some("const volatile"),
244 (true, false, true) => Some("const restrict"),
245 (false, true, true) => Some("volatile restrict"),
246 (true, true, true) => Some("const volatile restrict"),
247 }
248}
249
250#[cfg(test)]
251mod tests {
252 use rucc_base::Interner;
253
254 use super::*;
255 use crate::kind::{ArrayLen, FloatKind, FunctionType, IntKind, RecordKind};
256
257 fn fixture() -> (Types, Interner) {
259 (Types::new(), Interner::new())
260 }
261
262 #[test]
263 fn a_basic_type_is_its_keywords() {
264 let (types, names) = fixture();
265 let int = types.int(IntKind::Int);
266 assert_eq!(spell(&types, &names, int), "int");
267 assert_eq!(spell(&types, &names, types.void()), "void");
268 assert_eq!(spell(&types, &names, types.boolean()), "_Bool");
269 let long_double = types.float(FloatKind::LongDouble);
270 assert_eq!(spell(&types, &names, long_double), "long double");
271 }
272
273 #[test]
274 fn a_qualifier_goes_in_front_of_what_it_qualifies() {
275 let (mut types, names) = fixture();
276 let int = types.int(IntKind::Int);
277 let qualified = types.qualified(int, Qualifiers::CONST.with(Qualifiers::VOLATILE));
278 assert_eq!(spell(&types, &names, qualified), "const volatile int");
279 }
280
281 #[test]
282 fn a_pointers_own_qualifier_goes_after_the_star() {
283 let (mut types, names) = fixture();
284 let char_type = types.int(IntKind::Char);
285 let constant = types.qualified(char_type, Qualifiers::CONST);
286 let pointer = types.pointer(constant);
287 let constant_pointer = types.qualified(pointer, Qualifiers::CONST);
288 assert_eq!(spell(&types, &names, constant_pointer), "const char *const");
289 }
290
291 #[test]
292 fn a_qualified_pointer_with_a_name_keeps_them_apart() {
293 let (mut types, mut names) = fixture();
294 let int = types.int(IntKind::Int);
295 let pointer = types.pointer(int);
296 let restricted = types.qualified(pointer, Qualifiers::RESTRICT);
297 let p = names.intern("p");
298 assert_eq!(declare(&types, &names, restricted, p), "int *restrict p");
299 }
300
301 #[test]
302 fn a_declarator_is_written_around_the_name() {
303 let (mut types, mut names) = fixture();
304 let int = types.int(IntKind::Int);
305 let char_type = types.int(IntKind::Char);
306 let signature =
307 FunctionType { ret: int, params: vec![char_type], variadic: false, prototyped: true };
308 let function = types.function(signature);
309 let pointer = types.pointer(function);
310 let array = types.array(pointer, ArrayLen::Fixed(3));
311 let f = names.intern("f");
312 assert_eq!(declare(&types, &names, array, f), "int (*f[3])(char)");
313 }
314
315 #[test]
316 fn an_abstract_declarator_keeps_the_parentheses_the_name_would_have_needed() {
317 let (mut types, names) = fixture();
318 let int = types.int(IntKind::Int);
319 let array = types.array(int, ArrayLen::Fixed(3));
320 let pointer = types.pointer(array);
321 assert_eq!(spell(&types, &names, pointer), "int (*)[3]");
322 }
323
324 #[test]
326 fn a_suffix_with_nothing_in_front_of_it_goes_against_the_type() {
327 let (mut types, names) = fixture();
328 let int = types.int(IntKind::Int);
329 let array = types.array(int, ArrayLen::Fixed(4));
330 let nested = types.array(array, ArrayLen::Fixed(2));
331 let takes_an_int =
332 FunctionType { ret: int, params: vec![int], variadic: false, prototyped: true };
333 let function = types.function(takes_an_int.clone());
334 let to_int = types.pointer(int);
335 let gives_a_pointer = types.function(FunctionType { ret: to_int, ..takes_an_int });
336 let to_array = types.pointer(array);
337
338 assert_eq!(spell(&types, &names, array), "int[4]");
339 assert_eq!(spell(&types, &names, nested), "int[2][4]");
340 assert_eq!(spell(&types, &names, function), "int(int)");
341 assert_eq!(spell(&types, &names, gives_a_pointer), "int *(int)");
342 assert_eq!(spell(&types, &names, to_array), "int (*)[4]");
344 }
345
346 #[test]
347 fn an_array_of_arrays_reads_left_to_right() {
348 let (mut types, mut names) = fixture();
349 let int = types.int(IntKind::Int);
350 let inner = types.array(int, ArrayLen::Fixed(3));
351 let outer = types.array(inner, ArrayLen::Fixed(2));
352 let a = names.intern("a");
353 assert_eq!(declare(&types, &names, outer, a), "int a[2][3]");
354 }
355
356 #[test]
357 fn an_array_without_a_size_says_so_and_a_variable_one_says_only_that_it_has_one() {
358 let (mut types, names) = fixture();
359 let int = types.int(IntKind::Int);
360 let unknown = types.array(int, ArrayLen::Unknown);
361 let variable = types.array(int, ArrayLen::Variable(crate::kind::VlaId(0)));
362 assert_eq!(spell(&types, &names, unknown), "int[]");
363 assert_eq!(spell(&types, &names, variable), "int[*]");
364 }
365
366 #[test]
367 fn a_prototype_with_no_parameters_is_not_a_function_without_one() {
368 let (mut types, names) = fixture();
369 let int = types.int(IntKind::Int);
370 let prototyped =
371 FunctionType { ret: int, params: Vec::new(), variadic: false, prototyped: true };
372 let old = FunctionType { ret: int, params: Vec::new(), variadic: false, prototyped: false };
373 let prototyped = types.function(prototyped);
374 let old = types.function(old);
375 let prototyped = types.pointer(prototyped);
376 let old = types.pointer(old);
377 assert_eq!(spell(&types, &names, prototyped), "int (*)(void)");
378 assert_eq!(spell(&types, &names, old), "int (*)()");
379 }
380
381 #[test]
382 fn a_variadic_function_ends_in_the_ellipsis() {
383 let (mut types, names) = fixture();
384 let int = types.int(IntKind::Int);
385 let char_type = types.int(IntKind::Char);
386 let signature =
387 FunctionType { ret: int, params: vec![char_type], variadic: true, prototyped: true };
388 let function = types.function(signature);
389 let pointer = types.pointer(function);
390 assert_eq!(spell(&types, &names, pointer), "int (*)(char, ...)");
391 }
392
393 #[test]
394 fn a_typedef_is_spelled_as_itself_and_its_canonical_form_as_what_it_stands_for() {
395 let (mut types, mut names) = fixture();
396 let ulong = types.int(IntKind::ULong);
397 let name = names.intern("size_t");
398 let size_t = types.typedef(name, ulong);
399 let pointer = types.pointer(size_t);
400 assert_eq!(spell(&types, &names, pointer), "size_t *");
401 let canonical = types.canonical(pointer);
402 assert_eq!(spell(&types, &names, canonical), "unsigned long *");
403 }
404
405 #[test]
406 fn a_tag_that_was_never_written_is_named_the_way_gcc_names_it() {
407 let (mut types, mut names) = fixture();
408 let tag = names.intern("S");
409 let named = types.declare_record(RecordKind::Struct, Some(tag));
410 let unnamed = types.declare_record(RecordKind::Union, None);
411 let named = types.record(named);
412 let unnamed = types.record(unnamed);
413 assert_eq!(spell(&types, &names, named), "struct S");
414 assert_eq!(spell(&types, &names, unnamed), "union <anonymous>");
415 }
416
417 #[test]
418 fn an_atomic_type_is_written_as_the_type_it_is() {
419 let (mut types, names) = fixture();
420 let int = types.int(IntKind::Int);
421 let atomic = types.atomic(int);
422 let pointer = types.pointer(atomic);
423 assert_eq!(spell(&types, &names, atomic), "_Atomic(int)");
424 assert_eq!(spell(&types, &names, pointer), "_Atomic(int) *");
425 }
426
427 #[test]
428 fn a_vector_is_written_the_way_gcc_writes_one() {
429 let (mut types, names) = fixture();
430 let int = types.int(IntKind::Int);
431 let vector = types.vector(int, 4);
432 assert_eq!(spell(&types, &names, vector), "__vector(4) int");
433 }
434}