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(part) => {
116 format!("_Complex {}", self.declaration(part, Declarator::nothing()))
117 }
118 TypeKind::BitInt { signed, width } => {
119 let sign = if signed { "" } else { "unsigned " };
120 format!("{sign}_BitInt({width})")
121 }
122 TypeKind::Atomic(inner) => format!("_Atomic({})", self.spell(inner)),
127 TypeKind::Vector { elem, len } => format!("__vector({len}) {}", self.spell(elem)),
130 TypeKind::Record(record) => {
131 let info = self.types.record_info(record);
132 format!("{} {}", info.kind.as_str(), self.tag(info.tag))
133 }
134 TypeKind::Enum(enumeration) => {
135 let info = self.types.enum_info(enumeration);
136 format!("enum {}", self.tag(info.tag))
137 }
138 TypeKind::Typedef { name, .. } => self.names.resolve(name).to_owned(),
139 };
140
141 let mut out = String::new();
142 if let Some(quals) = quals_text(ty.quals) {
143 out.push_str(quals);
144 out.push(' ');
145 }
146 out.push_str(&base);
147 if !inner.text.is_empty() {
148 if !inner.glued {
149 out.push(' ');
150 }
151 out.push_str(&inner.text);
152 }
153 out
154 }
155
156 fn pointer(&self, ty: Type, pointee: TypeId, inner: Declarator) -> String {
159 let mut declarator = String::from("*");
160 if let Some(quals) = quals_text(ty.quals) {
161 declarator.push_str(quals);
162 if !inner.text.is_empty() {
163 declarator.push(' ');
164 }
165 }
166 declarator.push_str(&inner.text);
167 if matches!(self.types.kind(pointee), TypeKind::Array { .. } | TypeKind::Function(_)) {
172 declarator = format!("({declarator})");
173 }
174 self.declaration(pointee, Declarator::of(declarator))
175 }
176
177 fn array(&self, ty: Type, elem: TypeId, len: ArrayLen, inner: Declarator) -> String {
179 let mut suffix = String::from("[");
180 if let Some(quals) = quals_text(ty.quals) {
181 suffix.push_str(quals);
182 if !matches!(len, ArrayLen::Unknown) {
183 suffix.push(' ');
184 }
185 }
186 match len {
187 ArrayLen::Fixed(count) => suffix.push_str(&count.to_string()),
188 ArrayLen::Unknown => {}
189 ArrayLen::Star | ArrayLen::Variable(_) => suffix.push('*'),
192 }
193 suffix.push(']');
194 self.declaration(elem, inner.suffixed(&suffix))
195 }
196
197 fn function(&self, function: FunctionId, inner: Declarator) -> String {
199 let signature = self.types.signature(function);
200 let mut suffix = String::from("(");
201 for (index, ¶m) in signature.params.iter().enumerate() {
202 if index > 0 {
203 suffix.push_str(", ");
204 }
205 suffix.push_str(&self.spell(param));
206 }
207 if signature.variadic {
208 if !signature.params.is_empty() {
209 suffix.push_str(", ");
210 }
211 suffix.push_str("...");
212 } else if signature.params.is_empty() && signature.prototyped {
213 suffix.push_str("void");
216 }
217 suffix.push(')');
218 self.declaration(signature.ret, inner.suffixed(&suffix))
219 }
220
221 fn spell(&self, id: TypeId) -> String {
223 self.declaration(id, Declarator::nothing())
224 }
225
226 fn tag(&self, tag: Option<Symbol>) -> String {
228 match tag {
229 Some(name) => self.names.resolve(name).to_owned(),
230 None => String::from("<anonymous>"),
231 }
232 }
233}
234
235fn quals_text(quals: Qualifiers) -> Option<&'static str> {
237 match (
240 quals.has(Qualifiers::CONST),
241 quals.has(Qualifiers::VOLATILE),
242 quals.has(Qualifiers::RESTRICT),
243 ) {
244 (false, false, false) => None,
245 (true, false, false) => Some("const"),
246 (false, true, false) => Some("volatile"),
247 (false, false, true) => Some("restrict"),
248 (true, true, false) => Some("const volatile"),
249 (true, false, true) => Some("const restrict"),
250 (false, true, true) => Some("volatile restrict"),
251 (true, true, true) => Some("const volatile restrict"),
252 }
253}
254
255#[cfg(test)]
256mod tests {
257 use rucc_base::Interner;
258
259 use super::*;
260 use crate::kind::{ArrayLen, FloatKind, FunctionType, IntKind, RecordKind};
261
262 fn fixture() -> (Types, Interner) {
264 (Types::new(), Interner::new())
265 }
266
267 #[test]
268 fn a_basic_type_is_its_keywords() {
269 let (types, names) = fixture();
270 let int = types.int(IntKind::Int);
271 assert_eq!(spell(&types, &names, int), "int");
272 assert_eq!(spell(&types, &names, types.void()), "void");
273 assert_eq!(spell(&types, &names, types.boolean()), "_Bool");
274 let long_double = types.float(FloatKind::LongDouble);
275 assert_eq!(spell(&types, &names, long_double), "long double");
276 }
277
278 #[test]
279 fn a_qualifier_goes_in_front_of_what_it_qualifies() {
280 let (mut types, names) = fixture();
281 let int = types.int(IntKind::Int);
282 let qualified = types.qualified(int, Qualifiers::CONST.with(Qualifiers::VOLATILE));
283 assert_eq!(spell(&types, &names, qualified), "const volatile int");
284 }
285
286 #[test]
287 fn a_pointers_own_qualifier_goes_after_the_star() {
288 let (mut types, names) = fixture();
289 let char_type = types.int(IntKind::Char);
290 let constant = types.qualified(char_type, Qualifiers::CONST);
291 let pointer = types.pointer(constant);
292 let constant_pointer = types.qualified(pointer, Qualifiers::CONST);
293 assert_eq!(spell(&types, &names, constant_pointer), "const char *const");
294 }
295
296 #[test]
297 fn a_qualified_pointer_with_a_name_keeps_them_apart() {
298 let (mut types, mut names) = fixture();
299 let int = types.int(IntKind::Int);
300 let pointer = types.pointer(int);
301 let restricted = types.qualified(pointer, Qualifiers::RESTRICT);
302 let p = names.intern("p");
303 assert_eq!(declare(&types, &names, restricted, p), "int *restrict p");
304 }
305
306 #[test]
307 fn a_declarator_is_written_around_the_name() {
308 let (mut types, mut names) = fixture();
309 let int = types.int(IntKind::Int);
310 let char_type = types.int(IntKind::Char);
311 let signature =
312 FunctionType { ret: int, params: vec![char_type], variadic: false, prototyped: true };
313 let function = types.function(signature);
314 let pointer = types.pointer(function);
315 let array = types.array(pointer, ArrayLen::Fixed(3));
316 let f = names.intern("f");
317 assert_eq!(declare(&types, &names, array, f), "int (*f[3])(char)");
318 }
319
320 #[test]
321 fn an_abstract_declarator_keeps_the_parentheses_the_name_would_have_needed() {
322 let (mut types, names) = fixture();
323 let int = types.int(IntKind::Int);
324 let array = types.array(int, ArrayLen::Fixed(3));
325 let pointer = types.pointer(array);
326 assert_eq!(spell(&types, &names, pointer), "int (*)[3]");
327 }
328
329 #[test]
331 fn a_suffix_with_nothing_in_front_of_it_goes_against_the_type() {
332 let (mut types, names) = fixture();
333 let int = types.int(IntKind::Int);
334 let array = types.array(int, ArrayLen::Fixed(4));
335 let nested = types.array(array, ArrayLen::Fixed(2));
336 let takes_an_int =
337 FunctionType { ret: int, params: vec![int], variadic: false, prototyped: true };
338 let function = types.function(takes_an_int.clone());
339 let to_int = types.pointer(int);
340 let gives_a_pointer = types.function(FunctionType { ret: to_int, ..takes_an_int });
341 let to_array = types.pointer(array);
342
343 assert_eq!(spell(&types, &names, array), "int[4]");
344 assert_eq!(spell(&types, &names, nested), "int[2][4]");
345 assert_eq!(spell(&types, &names, function), "int(int)");
346 assert_eq!(spell(&types, &names, gives_a_pointer), "int *(int)");
347 assert_eq!(spell(&types, &names, to_array), "int (*)[4]");
349 }
350
351 #[test]
352 fn an_array_of_arrays_reads_left_to_right() {
353 let (mut types, mut names) = fixture();
354 let int = types.int(IntKind::Int);
355 let inner = types.array(int, ArrayLen::Fixed(3));
356 let outer = types.array(inner, ArrayLen::Fixed(2));
357 let a = names.intern("a");
358 assert_eq!(declare(&types, &names, outer, a), "int a[2][3]");
359 }
360
361 #[test]
362 fn an_array_without_a_size_says_so_and_a_variable_one_says_only_that_it_has_one() {
363 let (mut types, names) = fixture();
364 let int = types.int(IntKind::Int);
365 let unknown = types.array(int, ArrayLen::Unknown);
366 let variable = types.array(int, ArrayLen::Variable(crate::kind::VlaId(0)));
367 assert_eq!(spell(&types, &names, unknown), "int[]");
368 assert_eq!(spell(&types, &names, variable), "int[*]");
369 }
370
371 #[test]
372 fn a_prototype_with_no_parameters_is_not_a_function_without_one() {
373 let (mut types, names) = fixture();
374 let int = types.int(IntKind::Int);
375 let prototyped =
376 FunctionType { ret: int, params: Vec::new(), variadic: false, prototyped: true };
377 let old = FunctionType { ret: int, params: Vec::new(), variadic: false, prototyped: false };
378 let prototyped = types.function(prototyped);
379 let old = types.function(old);
380 let prototyped = types.pointer(prototyped);
381 let old = types.pointer(old);
382 assert_eq!(spell(&types, &names, prototyped), "int (*)(void)");
383 assert_eq!(spell(&types, &names, old), "int (*)()");
384 }
385
386 #[test]
387 fn a_variadic_function_ends_in_the_ellipsis() {
388 let (mut types, names) = fixture();
389 let int = types.int(IntKind::Int);
390 let char_type = types.int(IntKind::Char);
391 let signature =
392 FunctionType { ret: int, params: vec![char_type], variadic: true, prototyped: true };
393 let function = types.function(signature);
394 let pointer = types.pointer(function);
395 assert_eq!(spell(&types, &names, pointer), "int (*)(char, ...)");
396 }
397
398 #[test]
399 fn a_typedef_is_spelled_as_itself_and_its_canonical_form_as_what_it_stands_for() {
400 let (mut types, mut names) = fixture();
401 let ulong = types.int(IntKind::ULong);
402 let name = names.intern("size_t");
403 let size_t = types.typedef(name, ulong);
404 let pointer = types.pointer(size_t);
405 assert_eq!(spell(&types, &names, pointer), "size_t *");
406 let canonical = types.canonical(pointer);
407 assert_eq!(spell(&types, &names, canonical), "unsigned long *");
408 }
409
410 #[test]
411 fn a_tag_that_was_never_written_is_named_the_way_gcc_names_it() {
412 let (mut types, mut names) = fixture();
413 let tag = names.intern("S");
414 let named = types.declare_record(RecordKind::Struct, Some(tag));
415 let unnamed = types.declare_record(RecordKind::Union, None);
416 let named = types.record(named);
417 let unnamed = types.record(unnamed);
418 assert_eq!(spell(&types, &names, named), "struct S");
419 assert_eq!(spell(&types, &names, unnamed), "union <anonymous>");
420 }
421
422 #[test]
423 fn an_atomic_type_is_written_as_the_type_it_is() {
424 let (mut types, names) = fixture();
425 let int = types.int(IntKind::Int);
426 let atomic = types.atomic(int);
427 let pointer = types.pointer(atomic);
428 assert_eq!(spell(&types, &names, atomic), "_Atomic(int)");
429 assert_eq!(spell(&types, &names, pointer), "_Atomic(int) *");
430 }
431
432 #[test]
433 fn a_vector_is_written_the_way_gcc_writes_one() {
434 let (mut types, names) = fixture();
435 let int = types.int(IntKind::Int);
436 let vector = types.vector(int, 4);
437 assert_eq!(spell(&types, &names, vector), "__vector(4) int");
438 }
439}