1use rucc_base::{Interner, Symbol};
48
49use crate::asm::{AsmId, AsmQuals};
50use crate::ast::{
51 AsmOperandList, Ast, AttrList, DesignatorList, EnumeratorList, ExprList, GenericList,
52 MemberList, ParamList, StrId, StrList, SymbolList,
53};
54use crate::attr::{AttrArg, AttrSyntax};
55use crate::decl::{
56 ArraySize, Decl, DeclId, DeclaratorId, Derived, Field, Member, Param, ParamKind, TypeNameId,
57};
58use crate::expr::{BinaryOp, Expr, ExprId, UnaryOp};
59use crate::init::{Designator, Init, InitId};
60use crate::spec::TypeofArg;
61use crate::spec::{AlignSpec, Builtin, BuiltinSet, DeclSpecsId, FuncSpecs, Quals, TypeSpec};
62use crate::stmt::{ForInit, Stmt, StmtId};
63
64const COMMA: u8 = 1;
66const ASSIGN: u8 = 2;
68const COND: u8 = 3;
70const LOG_OR: u8 = 4;
72const LOG_AND: u8 = 5;
74const BIT_OR: u8 = 6;
76const BIT_XOR: u8 = 7;
78const BIT_AND: u8 = 8;
80const EQUALITY: u8 = 9;
82const RELATIONAL: u8 = 10;
84const SHIFT: u8 = 11;
86const ADDITIVE: u8 = 12;
88const MULTIPLICATIVE: u8 = 13;
90const CAST: u8 = 14;
92const UNARY: u8 = 15;
94const POSTFIX: u8 = 16;
96const PRIMARY: u8 = 17;
98
99const fn binding(op: BinaryOp) -> u8 {
101 match op {
102 BinaryOp::Mul | BinaryOp::Div | BinaryOp::Rem => MULTIPLICATIVE,
103 BinaryOp::Add | BinaryOp::Sub => ADDITIVE,
104 BinaryOp::Shl | BinaryOp::Shr => SHIFT,
105 BinaryOp::Lt | BinaryOp::Gt | BinaryOp::Le | BinaryOp::Ge => RELATIONAL,
106 BinaryOp::Eq | BinaryOp::Ne => EQUALITY,
107 BinaryOp::BitAnd => BIT_AND,
108 BinaryOp::BitXor => BIT_XOR,
109 BinaryOp::BitOr => BIT_OR,
110 BinaryOp::LogAnd => LOG_AND,
111 BinaryOp::LogOr => LOG_OR,
112 }
113}
114
115const BUILTIN_SPELLINGS: &[(BuiltinSet, &str)] = &[
120 (BuiltinSet::SIGNED, "signed"),
121 (BuiltinSet::UNSIGNED, "unsigned"),
122 (BuiltinSet::SHORT, "short"),
123 (BuiltinSet::VOID, "void"),
124 (BuiltinSet::BOOL, "_Bool"),
125 (BuiltinSet::CHAR, "char"),
126 (BuiltinSet::INT, "int"),
127 (BuiltinSet::INT128, "__int128"),
128 (BuiltinSet::FLOAT, "float"),
129 (BuiltinSet::DOUBLE, "double"),
130 (BuiltinSet::COMPLEX, "_Complex"),
131 (BuiltinSet::IMAGINARY, "_Imaginary"),
132 (BuiltinSet::FLOAT16, "_Float16"),
133 (BuiltinSet::FLOAT32, "_Float32"),
134 (BuiltinSet::FLOAT64, "_Float64"),
135 (BuiltinSet::FLOAT128, "_Float128"),
136 (BuiltinSet::FLOAT32X, "_Float32x"),
137 (BuiltinSet::FLOAT64X, "_Float64x"),
138 (BuiltinSet::FLOAT128X, "_Float128x"),
139 (BuiltinSet::FLOAT80, "__float80"),
140 (BuiltinSet::DECIMAL32, "_Decimal32"),
141 (BuiltinSet::DECIMAL64, "_Decimal64"),
142 (BuiltinSet::DECIMAL128, "_Decimal128"),
143];
144
145fn pastes(last: char, next: char) -> bool {
151 let word = |c: char| c.is_ascii_alphanumeric() || c == '_' || c == '$';
152 if word(last) && word(next) {
153 return true;
154 }
155 if (last == '.' && next.is_ascii_digit()) || (last.is_ascii_digit() && next == '.') {
158 return true;
159 }
160 matches!(
161 (last, next),
162 ('+', '+' | '=')
163 | ('-', '-' | '=' | '>')
164 | ('*', '=')
165 | ('/', '=' | '/' | '*')
166 | ('%', '=' | '>' | ':')
167 | ('<', '<' | '=' | ':' | '%')
168 | ('>', '>' | '=')
169 | ('=', '=')
170 | ('!', '=')
171 | ('&', '&' | '=')
172 | ('|', '|' | '=')
173 | ('^', '=')
174 | ('.', '.')
175 | (':', '>' | ':')
176 | ('#', '#')
177 )
178}
179
180fn join(mut left: String, right: &str) -> String {
182 if let (Some(last), Some(next)) = (left.chars().next_back(), right.chars().next()) {
183 if pastes(last, next) {
184 left.push(' ');
185 }
186 }
187 left.push_str(right);
188 left
189}
190
191#[must_use]
193pub fn print(ast: &Ast, names: &Interner) -> String {
194 let mut printer = Printer::new(ast, names);
195 printer.unit();
196 printer.finish()
197}
198
199#[derive(Debug)]
201pub struct Printer<'a> {
202 ast: &'a Ast,
203 names: &'a Interner,
204 out: String,
205 depth: usize,
206}
207
208impl<'a> Printer<'a> {
209 #[must_use]
211 pub fn new(ast: &'a Ast, names: &'a Interner) -> Printer<'a> {
212 Printer { ast, names, out: String::new(), depth: 0 }
213 }
214
215 #[must_use]
217 pub fn finish(self) -> String {
218 self.out
219 }
220
221 pub fn unit(&mut self) {
223 let ast = self.ast;
224 for (index, &decl) in ast.top_level().iter().enumerate() {
225 if index > 0 {
226 self.newline();
227 }
228 self.decl(decl);
229 }
230 if !self.out.is_empty() {
231 self.out.push('\n');
232 }
233 }
234
235 pub fn decl(&mut self, id: DeclId) {
237 let ast = self.ast;
238 match ast[id] {
239 Decl::Error => self.token(";"),
242 Decl::Var { specs, declarators } => {
243 self.decl_specs(specs);
244 for (index, item) in ast[declarators].iter().enumerate() {
245 if index > 0 {
246 self.token(",");
247 }
248 self.space();
249 let text = self.declarator_text(item.declarator);
250 self.token(&text);
251 if let Some(label) = item.asm_label {
252 self.space();
253 self.token("__asm__");
254 self.token("(");
255 self.string(label);
256 self.token(")");
257 }
258 self.attributes(item.attrs);
259 if let Some(init) = item.init {
260 self.space();
261 self.token("=");
262 self.space();
263 self.init(init);
264 }
265 }
266 self.token(";");
267 }
268 Decl::Function { specs, declarator, params, body } => {
269 self.decl_specs(specs);
270 self.space();
271 let text = self.declarator_text(declarator);
272 self.token(&text);
273 self.depth += 1;
274 for ¶m in &ast[params] {
275 self.newline();
276 self.decl(param);
277 }
278 self.depth -= 1;
279 self.newline();
280 self.stmt(body);
281 }
282 Decl::StaticAssert { cond, message } => {
283 self.static_assert(cond, message);
284 }
285 Decl::Asm(asm) => {
286 self.asm(asm);
287 self.token(";");
288 }
289 Decl::Attributes(attrs) => {
290 self.attributes(attrs);
291 self.token(";");
292 }
293 }
294 }
295
296 pub fn stmt(&mut self, id: StmtId) {
298 let ast = self.ast;
299 match ast[id] {
300 Stmt::Error | Stmt::Empty => self.token(";"),
303 Stmt::Expr(expr) => {
304 self.expr_at(expr, COMMA);
305 self.token(";");
306 }
307 Stmt::Decl(decl) => self.decl(decl),
308 Stmt::Compound(items) => {
309 self.token("{");
310 self.depth += 1;
311 for &item in &ast[items] {
312 self.newline();
313 self.stmt(item);
314 }
315 self.depth -= 1;
316 self.newline();
317 self.token("}");
318 }
319 Stmt::If { cond, then, otherwise } => {
320 self.token("if");
321 self.space();
322 self.token("(");
323 self.expr_at(cond, COMMA);
324 self.token(")");
325 if otherwise.is_some() && self.dangling(then) {
326 self.braced(then);
327 } else {
328 self.body(then);
329 }
330 if let Some(otherwise) = otherwise {
331 self.newline();
332 self.token("else");
333 if matches!(ast[otherwise], Stmt::If { .. }) {
334 self.space();
335 self.stmt(otherwise);
336 } else {
337 self.body(otherwise);
338 }
339 }
340 }
341 Stmt::Switch { scrutinee, body } => {
342 self.token("switch");
343 self.space();
344 self.token("(");
345 self.expr_at(scrutinee, COMMA);
346 self.token(")");
347 self.body(body);
348 }
349 Stmt::While { cond, body } => {
350 self.token("while");
351 self.space();
352 self.token("(");
353 self.expr_at(cond, COMMA);
354 self.token(")");
355 self.body(body);
356 }
357 Stmt::DoWhile { body, cond } => {
358 self.token("do");
359 self.body(body);
360 self.newline();
361 self.token("while");
362 self.space();
363 self.token("(");
364 self.expr_at(cond, COMMA);
365 self.token(")");
366 self.token(";");
367 }
368 Stmt::For { init, cond, step, body } => {
369 self.token("for");
370 self.space();
371 self.token("(");
372 match init {
373 ForInit::None => self.token(";"),
374 ForInit::Expr(expr) => {
375 self.expr_at(expr, COMMA);
376 self.token(";");
377 }
378 ForInit::Decl(decl) => self.decl(decl),
381 }
382 if let Some(cond) = cond {
383 self.space();
384 self.expr_at(cond, COMMA);
385 }
386 self.token(";");
387 if let Some(step) = step {
388 self.space();
389 self.expr_at(step, COMMA);
390 }
391 self.token(")");
392 self.body(body);
393 }
394 Stmt::Goto(name) => {
395 self.token("goto");
396 self.space();
397 self.name(name);
398 self.token(";");
399 }
400 Stmt::GotoExpr(expr) => {
401 self.token("goto");
402 self.space();
403 self.token("*");
404 self.expr_at(expr, CAST);
405 self.token(";");
406 }
407 Stmt::Continue => {
408 self.token("continue");
409 self.token(";");
410 }
411 Stmt::Break => {
412 self.token("break");
413 self.token(";");
414 }
415 Stmt::Return(value) => {
416 self.token("return");
417 if let Some(value) = value {
418 self.space();
419 self.expr_at(value, COMMA);
420 }
421 self.token(";");
422 }
423 Stmt::Label { name, body, attrs } => {
424 self.attributes(attrs);
425 self.space();
426 self.name(name);
427 self.token(":");
428 self.labelled(body);
429 }
430 Stmt::Case { lo, hi, body } => {
431 self.token("case");
432 self.space();
433 self.expr_at(lo, COND);
434 if let Some(hi) = hi {
435 self.space();
436 self.token("...");
437 self.space();
438 self.expr_at(hi, COND);
439 }
440 self.token(":");
441 self.labelled(body);
442 }
443 Stmt::Default { body } => {
444 self.token("default");
445 self.token(":");
446 self.labelled(body);
447 }
448 Stmt::LocalLabels(names) => {
449 self.token("__label__");
450 self.name_list(names);
451 self.token(";");
452 }
453 Stmt::Asm(asm) => {
454 self.asm(asm);
455 self.token(";");
456 }
457 }
458 }
459
460 pub fn expr(&mut self, id: ExprId) {
462 self.expr_at(id, COMMA);
463 }
464
465 pub fn type_name(&mut self, id: TypeNameId) {
467 let ast = self.ast;
468 let name = ast[id];
469 self.decl_specs(name.specs);
470 let text = self.declarator_text(name.declarator);
471 if !text.is_empty() {
472 self.space();
473 self.token(&text);
474 }
475 }
476
477 fn body(&mut self, id: StmtId) {
480 if matches!(self.ast[id], Stmt::Compound(_)) {
481 self.space();
482 self.stmt(id);
483 } else {
484 self.depth += 1;
485 self.newline();
486 self.stmt(id);
487 self.depth -= 1;
488 }
489 }
490
491 fn braced(&mut self, id: StmtId) {
494 self.space();
495 self.token("{");
496 self.depth += 1;
497 self.newline();
498 self.stmt(id);
499 self.depth -= 1;
500 self.newline();
501 self.token("}");
502 }
503
504 fn labelled(&mut self, body: Option<StmtId>) {
506 if let Some(body) = body {
507 self.newline();
508 self.stmt(body);
509 }
510 }
511
512 fn dangling(&self, id: StmtId) -> bool {
515 match self.ast[id] {
516 Stmt::If { otherwise: Some(otherwise), .. } => self.dangling(otherwise),
517 Stmt::If { otherwise: None, .. } => true,
518 Stmt::While { body, .. } | Stmt::Switch { body, .. } | Stmt::For { body, .. } => {
519 self.dangling(body)
520 }
521 Stmt::Label { body: Some(body), .. }
522 | Stmt::Case { body: Some(body), .. }
523 | Stmt::Default { body: Some(body) } => self.dangling(body),
524 _ => false,
525 }
526 }
527
528 fn static_assert(&mut self, cond: ExprId, message: Option<StrId>) {
530 self.token("_Static_assert");
531 self.token("(");
532 self.expr_at(cond, ASSIGN);
533 if let Some(message) = message {
534 self.token(",");
535 self.space();
536 self.string(message);
537 }
538 self.token(")");
539 self.token(";");
540 }
541
542 fn asm(&mut self, id: AsmId) {
544 let ast = self.ast;
545 let asm = ast[id];
546 self.token("__asm__");
547 if asm.quals.has(AsmQuals::VOLATILE) {
548 self.token("volatile");
549 }
550 if asm.quals.has(AsmQuals::INLINE) {
551 self.token("inline");
552 }
553 if asm.quals.has(AsmQuals::GOTO) {
554 self.token("goto");
555 }
556 self.token("(");
557 self.string(asm.template);
558 let sections = if !asm.labels.is_empty() {
561 4
562 } else if !asm.clobbers.is_empty() {
563 3
564 } else if !asm.inputs.is_empty() {
565 2
566 } else {
567 usize::from(!asm.outputs.is_empty())
568 };
569 for section in 0..sections {
570 self.space();
571 self.token(":");
572 match section {
573 0 => self.asm_operands(asm.outputs),
574 1 => self.asm_operands(asm.inputs),
575 2 => self.string_list(asm.clobbers),
576 _ => self.name_list(asm.labels),
577 }
578 }
579 self.token(")");
580 }
581
582 fn asm_operands(&mut self, list: AsmOperandList) {
584 let ast = self.ast;
585 for (index, operand) in ast[list].iter().enumerate() {
586 if index > 0 {
587 self.token(",");
588 }
589 self.space();
590 if let Some(name) = operand.name {
591 self.token("[");
592 self.name(name);
593 self.token("]");
594 self.space();
595 }
596 self.string(operand.constraint);
597 self.space();
598 self.token("(");
599 self.expr_at(operand.value, COMMA);
600 self.token(")");
601 }
602 }
603
604 fn string_list(&mut self, list: StrList) {
606 let ast = self.ast;
607 for (index, &item) in ast[list].iter().enumerate() {
608 if index > 0 {
609 self.token(",");
610 }
611 self.space();
612 self.string(item);
613 }
614 }
615
616 fn name_list(&mut self, list: SymbolList) {
618 let ast = self.ast;
619 for (index, &item) in ast[list].iter().enumerate() {
620 if index > 0 {
621 self.token(",");
622 }
623 self.space();
624 self.name(item);
625 }
626 }
627
628 fn decl_specs(&mut self, id: DeclSpecsId) {
630 let specs = self.ast[id];
631 self.attributes(specs.attrs);
632 if let Some(storage) = specs.storage {
633 self.token(storage.spelling());
634 }
635 if specs.thread_local {
636 self.token("_Thread_local");
637 }
638 if specs.constexpr {
639 self.token("constexpr");
640 }
641 if specs.func.has(FuncSpecs::INLINE) {
642 self.token("inline");
643 }
644 if specs.func.has(FuncSpecs::NORETURN) {
645 self.token("_Noreturn");
646 }
647 if let Some(align) = specs.align {
648 self.token("_Alignas");
649 self.token("(");
650 match align {
651 AlignSpec::Type(ty) => self.type_name(ty),
652 AlignSpec::Expr(expr) => self.expr_at(expr, ASSIGN),
653 }
654 self.token(")");
655 }
656 self.quals(specs.quals);
657 self.type_spec(specs.ty);
658 }
659
660 fn quals(&mut self, quals: Quals) {
662 if quals.has(Quals::CONST) {
663 self.token("const");
664 }
665 if quals.has(Quals::VOLATILE) {
666 self.token("volatile");
667 }
668 if quals.has(Quals::RESTRICT) {
669 self.token("restrict");
670 }
671 if quals.has(Quals::ATOMIC) {
672 self.token("_Atomic");
673 }
674 }
675
676 fn type_spec(&mut self, ty: TypeSpec) {
678 match ty {
679 TypeSpec::None => {}
680 TypeSpec::Builtin(builtin) => self.builtin(builtin),
681 TypeSpec::Record { kind, tag, fields, attrs, pack: _ } => {
687 self.token(kind.spelling());
688 self.attributes(attrs);
689 if let Some(tag) = tag {
690 self.space();
691 self.name(tag);
692 }
693 if let Some(fields) = fields {
694 self.members(fields);
695 }
696 }
697 TypeSpec::Enum { tag, enumerators, underlying, attrs } => {
698 self.token("enum");
699 self.attributes(attrs);
700 if let Some(tag) = tag {
701 self.space();
702 self.name(tag);
703 }
704 if let Some(underlying) = underlying {
705 self.space();
706 self.token(":");
707 self.space();
708 self.type_name(underlying);
709 }
710 if let Some(enumerators) = enumerators {
711 self.enumerators(enumerators);
712 }
713 }
714 TypeSpec::Typedef(name) => self.name(name),
715 TypeSpec::Typeof { unqual, operand } => {
716 self.token(if unqual { "__typeof_unqual__" } else { "__typeof__" });
717 self.token("(");
718 match operand {
719 TypeofArg::Expr(expr) => self.expr_at(expr, COMMA),
720 TypeofArg::Type(ty) => self.type_name(ty),
721 }
722 self.token(")");
723 }
724 TypeSpec::Atomic(ty) => {
725 self.token("_Atomic");
726 self.token("(");
727 self.type_name(ty);
728 self.token(")");
729 }
730 TypeSpec::Auto(which) => self.token(which.spelling()),
731 TypeSpec::VaList => self.token("__builtin_va_list"),
732 }
733 }
734
735 fn builtin(&mut self, builtin: Builtin) {
737 for &(which, spelling) in BUILTIN_SPELLINGS {
738 if builtin.set.has(which) {
739 self.token(spelling);
740 }
741 if which == BuiltinSet::SHORT {
744 for _ in 0..builtin.longs {
745 self.token("long");
746 }
747 }
748 }
749 if let Some(width) = builtin.width {
752 self.token("_BitInt");
753 self.token("(");
754 self.expr_at(width, COMMA);
755 self.token(")");
756 }
757 }
758
759 fn members(&mut self, list: MemberList) {
761 let ast = self.ast;
762 let members = &ast[list];
763 self.space();
764 self.token("{");
765 self.depth += 1;
766 let mut index = 0;
767 while index < members.len() {
768 self.newline();
769 match members[index] {
770 Member::StaticAssert { cond, message, .. } => {
771 self.static_assert(cond, message);
772 index += 1;
773 }
774 Member::Field(first) => {
775 self.decl_specs(first.specs);
776 if first.declarator.is_none() && first.bits.is_none() {
777 index += 1;
780 } else {
781 let mut written = 0;
785 while let Some(&Member::Field(field)) = members.get(index) {
786 if field.specs != first.specs
787 || (field.declarator.is_none() && field.bits.is_none())
788 {
789 break;
790 }
791 if written > 0 {
792 self.token(",");
793 }
794 self.space();
795 self.field(field);
796 written += 1;
797 index += 1;
798 }
799 }
800 self.token(";");
801 }
802 }
803 }
804 self.depth -= 1;
805 self.newline();
806 self.token("}");
807 }
808
809 fn field(&mut self, field: Field) {
811 if let Some(declarator) = field.declarator {
812 let text = self.declarator_text(declarator);
813 self.token(&text);
814 }
815 if let Some(bits) = field.bits {
816 self.space();
817 self.token(":");
818 self.space();
819 self.expr_at(bits, COND);
820 }
821 self.attributes(field.attrs);
822 }
823
824 fn enumerators(&mut self, list: EnumeratorList) {
826 let ast = self.ast;
827 self.space();
828 self.token("{");
829 self.depth += 1;
830 for (index, enumerator) in ast[list].iter().enumerate() {
831 if index > 0 {
832 self.token(",");
833 }
834 self.newline();
835 self.name(enumerator.name);
836 self.attributes(enumerator.attrs);
837 if let Some(value) = enumerator.value {
838 self.space();
839 self.token("=");
840 self.space();
841 self.expr_at(value, COND);
842 }
843 }
844 self.depth -= 1;
845 self.newline();
846 self.token("}");
847 }
848
849 fn declarator_text(&mut self, id: DeclaratorId) -> String {
856 let ast = self.ast;
857 let declarator = ast[id];
858 let mut text = match declarator.name {
859 Some(name) => self.names.resolve(name).to_string(),
860 None => String::new(),
861 };
862 let mut pointered = false;
863 for step in &ast[declarator.derived] {
864 match *step {
865 Derived::Pointer { quals, attrs } => {
866 let prefix = self.capture(|p| {
867 p.token("*");
868 p.quals(quals);
869 p.attributes(attrs);
870 });
871 text = join(prefix, &text);
872 pointered = true;
873 }
874 Derived::Array { size, quals, has_static } => {
875 if pointered {
876 text = format!("({text})");
877 }
878 let suffix = self.capture(|p| {
879 p.token("[");
880 if has_static {
881 p.token("static");
882 }
883 p.quals(quals);
884 match size {
885 ArraySize::Unspecified => {}
886 ArraySize::Star => p.token("*"),
887 ArraySize::Expr(expr) => p.expr_at(expr, ASSIGN),
888 }
889 p.token("]");
890 });
891 text = join(text, &suffix);
892 pointered = false;
893 }
894 Derived::Function { params, variadic, kind } => {
895 if pointered {
896 text = format!("({text})");
897 }
898 let suffix = self.capture(|p| p.parameters(params, variadic, kind));
899 text = join(text, &suffix);
900 pointered = false;
901 }
902 }
903 }
904 text
905 }
906
907 fn parameters(&mut self, params: ParamList, variadic: bool, kind: ParamKind) {
909 let ast = self.ast;
910 self.token("(");
911 match kind {
912 ParamKind::Void => self.token("void"),
913 ParamKind::Empty => {}
914 ParamKind::Identifiers => {
915 for (index, param) in ast[params].iter().enumerate() {
916 if index > 0 {
917 self.token(",");
918 self.space();
919 }
920 if let Some(name) = ast[param.declarator].name {
921 self.name(name);
922 }
923 }
924 }
925 ParamKind::Prototype => {
926 for (index, param) in ast[params].iter().enumerate() {
927 if index > 0 {
928 self.token(",");
929 self.space();
930 }
931 self.parameter(*param);
932 }
933 if variadic {
934 if !params.is_empty() {
935 self.token(",");
936 self.space();
937 }
938 self.token("...");
939 }
940 }
941 }
942 self.token(")");
943 }
944
945 fn parameter(&mut self, param: Param) {
947 if let Some(specs) = param.specs {
948 self.decl_specs(specs);
949 }
950 let text = self.declarator_text(param.declarator);
951 if !text.is_empty() {
952 self.space();
953 self.token(&text);
954 }
955 self.attributes(param.attrs);
956 }
957
958 fn attributes(&mut self, list: AttrList) {
960 let ast = self.ast;
961 for attr in &ast[list] {
962 self.space();
963 match attr.syntax {
964 AttrSyntax::Standard => self.token("[["),
965 AttrSyntax::Gnu => self.token("__attribute__(("),
966 AttrSyntax::Declspec => self.token("__declspec("),
967 }
968 if let Some(namespace) = attr.namespace {
969 self.name(namespace);
970 self.token("::");
971 }
972 self.name(attr.name);
973 if !attr.args.is_empty() {
974 self.token("(");
975 for (index, arg) in ast[attr.args].iter().enumerate() {
976 if index > 0 {
977 self.token(",");
978 self.space();
979 }
980 match *arg {
981 AttrArg::Ident(name) => self.name(name),
982 AttrArg::Expr(expr) => self.expr_at(expr, ASSIGN),
983 }
984 }
985 self.token(")");
986 }
987 match attr.syntax {
988 AttrSyntax::Standard => self.token("]]"),
989 AttrSyntax::Gnu => self.token("))"),
990 AttrSyntax::Declspec => self.token(")"),
991 }
992 self.space();
995 }
996 }
997
998 fn init(&mut self, id: InitId) {
1000 let ast = self.ast;
1001 match ast[id] {
1002 Init::Expr(expr) => self.expr_at(expr, ASSIGN),
1003 Init::List(items) => {
1004 self.token("{");
1005 for (index, item) in ast[items].iter().enumerate() {
1006 if index > 0 {
1007 self.token(",");
1008 }
1009 self.space();
1010 let designators = &ast[item.designators];
1011 for designator in designators {
1012 self.designator(*designator);
1013 }
1014 let obsolete = matches!(designators.last(), Some(Designator::ObsoleteField(_)));
1016 if !designators.is_empty() && !obsolete {
1017 self.space();
1018 self.token("=");
1019 self.space();
1020 }
1021 self.init(item.init);
1022 }
1023 self.space();
1024 self.token("}");
1025 }
1026 }
1027 }
1028
1029 fn designator(&mut self, designator: Designator) {
1031 match designator {
1032 Designator::Field(name) => {
1033 self.token(".");
1034 self.name(name);
1035 }
1036 Designator::Index(index) => {
1037 self.token("[");
1038 self.expr_at(index, COMMA);
1039 self.token("]");
1040 }
1041 Designator::Range { lo, hi } => {
1042 self.token("[");
1043 self.expr_at(lo, COND);
1044 self.space();
1045 self.token("...");
1046 self.space();
1047 self.expr_at(hi, COND);
1048 self.token("]");
1049 }
1050 Designator::ObsoleteField(name) => {
1051 self.name(name);
1052 self.token(":");
1053 self.space();
1054 }
1055 }
1056 }
1057
1058 fn expr_at(&mut self, id: ExprId, min: u8) {
1060 if self.precedence(id) < min {
1061 self.token("(");
1062 self.expression(id);
1063 self.token(")");
1064 } else {
1065 self.expression(id);
1066 }
1067 }
1068
1069 fn precedence(&self, id: ExprId) -> u8 {
1071 match self.ast[id] {
1072 Expr::Comma { .. } => COMMA,
1073 Expr::Assign { .. } => ASSIGN,
1074 Expr::Cond { .. } => COND,
1075 Expr::Binary { op, .. } => binding(op),
1076 Expr::Cast { .. } => CAST,
1077 Expr::Unary { op, .. } => {
1078 if op.is_postfix() {
1079 POSTFIX
1080 } else {
1081 UNARY
1082 }
1083 }
1084 Expr::SizeofExpr(_) | Expr::AlignofExpr(_) | Expr::Extension(_) => UNARY,
1085 Expr::Index { .. }
1086 | Expr::Call { .. }
1087 | Expr::Member { .. }
1088 | Expr::CompoundLiteral { .. } => POSTFIX,
1089 _ => PRIMARY,
1090 }
1091 }
1092
1093 fn expression(&mut self, id: ExprId) {
1095 let ast = self.ast;
1096 match ast[id] {
1097 Expr::Error => self.token("0"),
1100 Expr::Name(name) => self.name(name),
1101 Expr::Int(constant) => {
1102 let constant = ast[constant];
1103 let text = format!("{}{}", constant.value, constant.ty.suffix());
1104 self.token(&text);
1105 }
1106 Expr::Float(constant) => {
1107 let constant = ast[constant];
1108 let mut text = constant.value.to_hex();
1109 text.push_str(constant.ty.suffix());
1110 if constant.imaginary {
1111 text.push('i');
1112 }
1113 self.token(&text);
1114 }
1115 Expr::Char(constant) => {
1116 let text = ast[constant].spell();
1117 self.token(&text);
1118 }
1119 Expr::Str(literal) => self.string(literal),
1120 Expr::Bool(value) => self.token(if value { "true" } else { "false" }),
1121 Expr::Nullptr => self.token("nullptr"),
1122 Expr::Index { base, index } => {
1123 self.expr_at(base, POSTFIX);
1124 self.token("[");
1125 self.expr_at(index, COMMA);
1126 self.token("]");
1127 }
1128 Expr::Call { callee, args } => {
1129 self.expr_at(callee, POSTFIX);
1130 self.token("(");
1131 self.arguments(args);
1132 self.token(")");
1133 }
1134 Expr::Member { base, name, arrow } => {
1135 self.expr_at(base, POSTFIX);
1136 self.token(if arrow { "->" } else { "." });
1137 self.name(name);
1138 }
1139 Expr::Unary { op, operand } => {
1140 if op.is_postfix() {
1141 self.expr_at(operand, POSTFIX);
1142 self.token(op.spelling());
1143 } else {
1144 self.token(op.spelling());
1145 let inner = match op {
1146 UnaryOp::PreInc | UnaryOp::PreDec => UNARY,
1147 _ => CAST,
1148 };
1149 self.expr_at(operand, inner);
1150 }
1151 }
1152 Expr::Binary { op, lhs, rhs } => {
1153 let at = binding(op);
1154 self.expr_at(lhs, at);
1155 self.space();
1156 self.token(op.spelling());
1157 self.space();
1158 self.expr_at(rhs, at + 1);
1161 }
1162 Expr::Assign { op, lhs, rhs } => {
1163 self.expr_at(lhs, UNARY);
1164 self.space();
1165 match op {
1166 Some(op) => {
1167 let text = format!("{}=", op.spelling());
1168 self.token(&text);
1169 }
1170 None => self.token("="),
1171 }
1172 self.space();
1173 self.expr_at(rhs, ASSIGN);
1174 }
1175 Expr::Cond { cond, then, otherwise } => {
1176 self.expr_at(cond, COND + 1);
1177 self.space();
1178 self.token("?");
1179 if let Some(then) = then {
1180 self.space();
1181 self.expr_at(then, COMMA);
1182 }
1183 self.space();
1184 self.token(":");
1185 self.space();
1186 self.expr_at(otherwise, COND);
1187 }
1188 Expr::Comma { lhs, rhs } => {
1189 self.expr_at(lhs, COMMA);
1190 self.token(",");
1191 self.space();
1192 self.expr_at(rhs, ASSIGN);
1193 }
1194 Expr::Cast { ty, operand } => {
1195 self.token("(");
1196 self.type_name(ty);
1197 self.token(")");
1198 self.expr_at(operand, CAST);
1199 }
1200 Expr::CompoundLiteral { ty, init } => {
1201 self.token("(");
1202 self.type_name(ty);
1203 self.token(")");
1204 self.init(init);
1205 }
1206 Expr::SizeofExpr(operand) => {
1209 self.token("sizeof");
1210 self.space();
1211 self.expr_at(operand, PRIMARY);
1212 }
1213 Expr::SizeofType(ty) => {
1214 self.token("sizeof");
1215 self.token("(");
1216 self.type_name(ty);
1217 self.token(")");
1218 }
1219 Expr::AlignofExpr(operand) => {
1220 self.token("__alignof__");
1221 self.space();
1222 self.expr_at(operand, PRIMARY);
1223 }
1224 Expr::AlignofType(ty) => {
1225 self.token("_Alignof");
1226 self.token("(");
1227 self.type_name(ty);
1228 self.token(")");
1229 }
1230 Expr::Generic { control, assocs } => {
1231 self.token("_Generic");
1232 self.token("(");
1233 self.expr_at(control, ASSIGN);
1234 self.associations(assocs);
1235 self.token(")");
1236 }
1237 Expr::StmtExpr(body) => {
1238 self.token("(");
1239 self.stmt(body);
1240 self.token(")");
1241 }
1242 Expr::LabelAddr(name) => {
1243 self.token("&&");
1244 self.name(name);
1245 }
1246 Expr::Offsetof { ty, path } => {
1247 self.token("__builtin_offsetof");
1248 self.token("(");
1249 self.type_name(ty);
1250 self.token(",");
1251 self.space();
1252 self.member_path(path);
1253 self.token(")");
1254 }
1255 Expr::ChooseExpr { cond, then, otherwise } => {
1256 self.token("__builtin_choose_expr");
1257 self.token("(");
1258 self.expr_at(cond, ASSIGN);
1259 self.token(",");
1260 self.space();
1261 self.expr_at(then, ASSIGN);
1262 self.token(",");
1263 self.space();
1264 self.expr_at(otherwise, ASSIGN);
1265 self.token(")");
1266 }
1267 Expr::TypesCompatible { a, b } => {
1268 self.token("__builtin_types_compatible_p");
1269 self.token("(");
1270 self.type_name(a);
1271 self.token(",");
1272 self.space();
1273 self.type_name(b);
1274 self.token(")");
1275 }
1276 Expr::VaArg { list, ty } => {
1277 self.token("__builtin_va_arg");
1278 self.token("(");
1279 self.expr_at(list, ASSIGN);
1280 self.token(",");
1281 self.space();
1282 self.type_name(ty);
1283 self.token(")");
1284 }
1285 Expr::VaStart { list, last } => {
1286 self.token("__builtin_va_start");
1287 self.token("(");
1288 self.expr_at(list, ASSIGN);
1289 if let Some(last) = last {
1290 self.token(",");
1291 self.space();
1292 self.expr_at(last, ASSIGN);
1293 }
1294 self.token(")");
1295 }
1296 Expr::VaEnd { list } => {
1297 self.token("__builtin_va_end");
1298 self.token("(");
1299 self.expr_at(list, ASSIGN);
1300 self.token(")");
1301 }
1302 Expr::VaCopy { dst, src } => {
1303 self.token("__builtin_va_copy");
1304 self.token("(");
1305 self.expr_at(dst, ASSIGN);
1306 self.token(",");
1307 self.space();
1308 self.expr_at(src, ASSIGN);
1309 self.token(")");
1310 }
1311 Expr::Extension(operand) => {
1312 self.token("__extension__");
1313 self.space();
1314 self.expr_at(operand, CAST);
1315 }
1316 }
1317 }
1318
1319 fn arguments(&mut self, args: ExprList) {
1322 let ast = self.ast;
1323 for (index, &arg) in ast[args].iter().enumerate() {
1324 if index > 0 {
1325 self.token(",");
1326 self.space();
1327 }
1328 self.expr_at(arg, ASSIGN);
1329 }
1330 }
1331
1332 fn associations(&mut self, assocs: GenericList) {
1334 let ast = self.ast;
1335 for assoc in &ast[assocs] {
1336 self.token(",");
1337 self.space();
1338 match assoc.ty {
1339 Some(ty) => self.type_name(ty),
1340 None => self.token("default"),
1341 }
1342 self.token(":");
1343 self.space();
1344 self.expr_at(assoc.value, ASSIGN);
1345 }
1346 }
1347
1348 fn member_path(&mut self, path: DesignatorList) {
1350 let ast = self.ast;
1351 for (index, step) in ast[path].iter().enumerate() {
1352 match (index, *step) {
1353 (0, Designator::Field(name)) => self.name(name),
1354 (_, step) => self.designator(step),
1355 }
1356 }
1357 }
1358
1359 fn string(&mut self, id: StrId) {
1361 let ast = self.ast;
1362 let text = ast[id].spell();
1363 self.token(&text);
1364 }
1365
1366 fn name(&mut self, symbol: Symbol) {
1368 let names = self.names;
1369 self.token(names.resolve(symbol));
1370 }
1371
1372 fn capture(&mut self, write: impl FnOnce(&mut Printer<'a>)) -> String {
1374 let held = std::mem::take(&mut self.out);
1375 write(self);
1376 std::mem::replace(&mut self.out, held)
1377 }
1378
1379 fn token(&mut self, text: &str) {
1381 if text.is_empty() {
1382 return;
1383 }
1384 if text.starts_with([';', ',', ')', ']']) {
1385 self.unspace();
1386 }
1387 if let (Some(last), Some(next)) = (self.out.chars().next_back(), text.chars().next()) {
1388 if pastes(last, next) {
1389 self.out.push(' ');
1390 }
1391 }
1392 self.out.push_str(text);
1393 }
1394
1395 fn unspace(&mut self) {
1398 let kept = self.out.trim_end_matches(' ');
1399 if !kept.ends_with('\n') {
1400 self.out.truncate(kept.len());
1401 }
1402 }
1403
1404 fn space(&mut self) {
1406 if !self.out.is_empty() && !self.out.ends_with([' ', '\n']) {
1407 self.out.push(' ');
1408 }
1409 }
1410
1411 fn newline(&mut self) {
1413 while self.out.ends_with(' ') {
1414 self.out.pop();
1415 }
1416 self.out.push('\n');
1417 for _ in 0..self.depth {
1418 self.out.push_str(" ");
1419 }
1420 }
1421}
1422
1423#[cfg(test)]
1424mod tests {
1425 use rucc_diag::Span;
1426 use rucc_lex::{CharConstant, Encoding, StringLiteral};
1427
1428 use super::*;
1429 use crate::decl::Declarator;
1430 use crate::spec::{DeclSpecs, StorageClass};
1431
1432 struct Fixture {
1433 ast: Ast,
1434 names: Interner,
1435 }
1436
1437 impl Fixture {
1438 fn new() -> Fixture {
1439 Fixture { ast: Ast::new(), names: Interner::new() }
1440 }
1441
1442 fn text(&self, write: impl FnOnce(&mut Printer<'_>)) -> String {
1443 let mut printer = Printer::new(&self.ast, &self.names);
1444 write(&mut printer);
1445 printer.finish()
1446 }
1447 }
1448
1449 #[test]
1450 fn two_tokens_that_would_join_get_a_space() {
1451 let mut fixture = Fixture::new();
1452 let one = fixture.ast.expr(Expr::Bool(true), Span::DUMMY);
1453 let minus = fixture.ast.expr(Expr::Unary { op: UnaryOp::Minus, operand: one }, Span::DUMMY);
1454 let twice =
1455 fixture.ast.expr(Expr::Unary { op: UnaryOp::Minus, operand: minus }, Span::DUMMY);
1456 assert_eq!(fixture.text(|p| p.expr(twice)), "- -true");
1457 }
1458
1459 #[test]
1460 fn the_variable_argument_family_prints_as_it_was_written() {
1461 let mut fixture = Fixture::new();
1462 let ap = fixture.names.intern("ap");
1463 let copy = fixture.names.intern("copy");
1464 let n = fixture.names.intern("n");
1465 let ap = fixture.ast.expr(Expr::Name(ap), Span::DUMMY);
1466 let copy = fixture.ast.expr(Expr::Name(copy), Span::DUMMY);
1467 let n = fixture.ast.expr(Expr::Name(n), Span::DUMMY);
1468
1469 let start = fixture.ast.expr(Expr::VaStart { list: ap, last: Some(n) }, Span::DUMMY);
1470 assert_eq!(fixture.text(|p| p.expr(start)), "__builtin_va_start(ap, n)");
1471
1472 let alone = fixture.ast.expr(Expr::VaStart { list: ap, last: None }, Span::DUMMY);
1475 assert_eq!(fixture.text(|p| p.expr(alone)), "__builtin_va_start(ap)");
1476
1477 let copied = fixture.ast.expr(Expr::VaCopy { dst: copy, src: ap }, Span::DUMMY);
1478 assert_eq!(fixture.text(|p| p.expr(copied)), "__builtin_va_copy(copy, ap)");
1479
1480 let end = fixture.ast.expr(Expr::VaEnd { list: ap }, Span::DUMMY);
1481 assert_eq!(fixture.text(|p| p.expr(end)), "__builtin_va_end(ap)");
1482 }
1483
1484 #[test]
1485 fn parentheses_go_where_the_grammar_needs_them_and_nowhere_else() {
1486 let mut fixture = Fixture::new();
1487 let a = fixture.names.intern("a");
1488 let b = fixture.names.intern("b");
1489 let c = fixture.names.intern("c");
1490 let a = fixture.ast.expr(Expr::Name(a), Span::DUMMY);
1491 let b = fixture.ast.expr(Expr::Name(b), Span::DUMMY);
1492 let c = fixture.ast.expr(Expr::Name(c), Span::DUMMY);
1493
1494 let sum = fixture.ast.expr(Expr::Binary { op: BinaryOp::Add, lhs: a, rhs: b }, Span::DUMMY);
1495 let scaled =
1496 fixture.ast.expr(Expr::Binary { op: BinaryOp::Mul, lhs: sum, rhs: c }, Span::DUMMY);
1497 assert_eq!(fixture.text(|p| p.expr(scaled)), "(a + b) * c");
1498
1499 let product =
1500 fixture.ast.expr(Expr::Binary { op: BinaryOp::Mul, lhs: b, rhs: c }, Span::DUMMY);
1501 let total =
1502 fixture.ast.expr(Expr::Binary { op: BinaryOp::Add, lhs: a, rhs: product }, Span::DUMMY);
1503 assert_eq!(fixture.text(|p| p.expr(total)), "a + b * c");
1504
1505 let inner =
1507 fixture.ast.expr(Expr::Binary { op: BinaryOp::Sub, lhs: b, rhs: c }, Span::DUMMY);
1508 let outer =
1509 fixture.ast.expr(Expr::Binary { op: BinaryOp::Sub, lhs: a, rhs: inner }, Span::DUMMY);
1510 assert_eq!(fixture.text(|p| p.expr(outer)), "a - (b - c)");
1511 }
1512
1513 #[test]
1514 fn a_declarator_reads_outward_from_its_name() {
1515 let mut fixture = Fixture::new();
1516 let f = fixture.names.intern("f");
1517 let three = fixture.ast.expr(Expr::Bool(true), Span::DUMMY);
1518 let derived = fixture.ast.add_derived_list(&[
1519 Derived::Array { size: ArraySize::Expr(three), quals: Quals::NONE, has_static: false },
1520 Derived::Pointer { quals: Quals::NONE, attrs: AttrList::EMPTY },
1521 Derived::Function { params: ParamList::EMPTY, variadic: false, kind: ParamKind::Void },
1522 ]);
1523 let declarator = fixture.ast.add_declarator(Declarator {
1524 name: Some(f),
1525 name_span: Span::DUMMY,
1526 derived,
1527 span: Span::DUMMY,
1528 });
1529 let specs = fixture.ast.add_specs(DeclSpecs::empty(Span::DUMMY));
1530 let ty = fixture.ast.add_type_name(crate::decl::TypeName {
1531 specs,
1532 declarator,
1533 span: Span::DUMMY,
1534 });
1535 assert_eq!(fixture.text(|p| p.type_name(ty)), "(*f[true])(void)");
1536 }
1537
1538 #[test]
1539 fn a_declaration_keeps_its_declarators_together() {
1540 let mut fixture = Fixture::new();
1541 let a = fixture.names.intern("a");
1542 let b = fixture.names.intern("b");
1543 let mut specs = DeclSpecs::empty(Span::DUMMY);
1544 specs.storage = Some(StorageClass::Static);
1545 specs.ty = TypeSpec::Builtin(Builtin { set: BuiltinSet::INT, longs: 0, width: None });
1546 let specs = fixture.ast.add_specs(specs);
1547 let mut declarators = Vec::new();
1548 for (name, stars) in [(a, 0), (b, 1)] {
1549 let derived = if stars == 0 {
1550 crate::ast::DerivedList::EMPTY
1551 } else {
1552 fixture.ast.add_derived_list(&[Derived::Pointer {
1553 quals: Quals::NONE,
1554 attrs: AttrList::EMPTY,
1555 }])
1556 };
1557 let declarator = fixture.ast.add_declarator(Declarator {
1558 name: Some(name),
1559 name_span: Span::DUMMY,
1560 derived,
1561 span: Span::DUMMY,
1562 });
1563 declarators.push(crate::decl::InitDeclarator {
1564 declarator,
1565 init: None,
1566 asm_label: None,
1567 attrs: AttrList::EMPTY,
1568 span: Span::DUMMY,
1569 });
1570 }
1571 let declarators = fixture.ast.add_init_declarator_list(&declarators);
1572 let decl = fixture.ast.decl(Decl::Var { specs, declarators }, Span::DUMMY);
1573 assert_eq!(fixture.text(|p| p.decl(decl)), "static int a, *b;");
1574 }
1575
1576 #[test]
1577 fn a_byte_escape_in_a_string_takes_three_octal_digits() {
1578 let literal = StringLiteral {
1579 elements: vec![0xff, u32::from(b'0'), u32::from(b'a')],
1580 encoding: Encoding::Plain,
1581 remarks: rucc_lex::Remarks::NONE,
1582 };
1583 assert_eq!(literal.spell(), "\"\\3770a\"");
1584 }
1585
1586 #[test]
1587 fn a_wide_escape_closes_the_literal_rather_than_swallowing_what_follows() {
1588 let literal = StringLiteral {
1589 elements: vec![0x1234, u32::from(b'a'), u32::from(b'z')],
1590 encoding: Encoding::Utf32,
1591 remarks: rucc_lex::Remarks::NONE,
1592 };
1593 assert_eq!(literal.spell(), "U\"\\x1234\" U\"az\"");
1594 }
1595
1596 #[test]
1597 fn a_character_constant_is_written_as_a_character_where_it_can_be() {
1598 let plain = CharConstant {
1599 value: i64::from(b'a'),
1600 encoding: Encoding::Plain,
1601 remarks: rucc_lex::Remarks::NONE,
1602 };
1603 assert_eq!(plain.spell(), "'a'");
1604
1605 let quote = CharConstant { encoding: Encoding::Plain, value: i64::from(b'\''), ..plain };
1606 assert_eq!(quote.spell(), "'\\''");
1607
1608 let negative = CharConstant { value: -1, ..plain };
1609 assert_eq!(negative.spell(), "'\\xff'");
1610
1611 let many = CharConstant { value: 0x6162, ..plain };
1612 assert_eq!(many.spell(), "'\\x61\\x62'");
1613 }
1614}