1use crate::ast::{
3 Annotation, Array, Declaration, DeclarationType, Expr, ExprType, Record, RecordField, Type,
4 TypeVariant,
5};
6use std::fmt::{Display, Formatter, Result};
7
8pub struct Printer<'a> {
9 input: &'a str,
10 d: &'a [Declaration],
11}
12
13pub fn printer<'a>(input: &'a str, d: &'a [Declaration]) -> Printer<'a> {
14 Printer { input, d }
15}
16
17impl<'a> Display for Printer<'a> {
18 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
19 let mut pos = 0;
20 for d in self.d {
21 let mut printer = Printer_ {
22 input: self.input,
23 pos,
24 f,
25 };
26 printer.print_decl(d)?;
27 pos = printer.pos;
28 }
29 f.write_str(&self.input[pos..])
30 }
31}
32
33struct Printer_<'a, 'b> {
34 input: &'a str,
35 pos: usize,
36 f: &'a mut Formatter<'b>,
37}
38
39impl<'a, 'b> Printer_<'a, 'b> {
40 fn print_decl(&mut self, d: &Declaration) -> Result {
41 match &d.ty {
42 DeclarationType::Type(ty) => self.print_type(ty),
43 DeclarationType::Const(c) => self.print_top_level_expr(c),
44 }
45 }
46
47 fn print_type(&mut self, t: &Type) -> Result {
48 self.set_pos(t.lo)?;
49 if let Some(l) = t.layout {
50 write!(self.f, "{{ size: {}, ", l.size_bits)?;
51 if l.field_alignment_bits == l.pointer_alignment_bits {
52 write!(self.f, "alignment: {}", l.field_alignment_bits)?;
53 } else {
54 write!(
55 self.f,
56 "field_alignment: {}, pointer_alignment: {}",
57 l.field_alignment_bits, l.pointer_alignment_bits,
58 )?;
59 }
60 if l.required_alignment_bits != 8 {
61 write!(
62 self.f,
63 ", required_alignment: {}",
64 l.required_alignment_bits
65 )?;
66 }
67 write!(self.f, " }}")?;
68 }
69 self.pos = t.layout_hi;
70 self.print_annotations(&t.annotations)?;
71 match &t.variant {
72 TypeVariant::Record(r) => self.print_record(r),
73 TypeVariant::Typedef(t) => self.print_type(t),
74 TypeVariant::Array(a) => self.print_array(a),
75 TypeVariant::Enum(a) => self.print_enum(a),
76 _ => Ok(()),
77 }
78 }
79
80 fn print_annotations(&mut self, a: &[Annotation]) -> Result {
81 for a in a {
82 self.print_annotation(a)?;
83 }
84 Ok(())
85 }
86
87 fn print_enum(&mut self, a: &[Expr]) -> Result {
88 for a in a {
89 self.print_top_level_expr(a)?;
90 }
91 Ok(())
92 }
93
94 fn print_annotation(&mut self, a: &Annotation) -> Result {
95 match a {
96 Annotation::PragmaPack(e) => self.print_top_level_expr(e),
97 Annotation::AttrPacked => Ok(()),
98 Annotation::Aligned(None) => Ok(()),
99 Annotation::Aligned(Some(e)) => self.print_top_level_expr(e),
100 }
101 }
102
103 fn print_array(&mut self, a: &Array) -> Result {
104 if let Some(n) = &a.num_elements {
105 self.print_top_level_expr(n)?;
106 }
107 self.print_type(&a.element_type)
108 }
109
110 fn print_record(&mut self, r: &Record) -> Result {
111 for f in &r.fields {
112 self.print_record_field(f)?;
113 }
114 Ok(())
115 }
116
117 fn print_record_field(&mut self, f: &RecordField) -> Result {
118 self.set_pos(f.lo)?;
119 if let Some(l) = f.layout {
120 write!(
121 self.f,
122 "{{ offset: {}, size: {} }}",
123 l.offset_bits, l.size_bits
124 )?;
125 }
126 self.pos = f.layout_hi;
127 self.print_annotations(&f.annotations)?;
128 self.print_type(&f.ty)?;
129 if let Some(bw) = &f.bit_width {
130 self.print_top_level_expr(bw)?;
131 }
132 Ok(())
133 }
134
135 fn print_top_level_expr(&mut self, e: &Expr) -> Result {
136 if let ExprType::Lit(_) = e.ty {
137 return Ok(());
138 }
139 self.set_pos(e.span.0)?;
140 if let Some(l) = e.value {
141 write!(self.f, "{{{}}}", l)?;
142 }
143 self.pos = e.value_hi;
144 Ok(())
145 }
146
147 fn set_pos(&mut self, pos: usize) -> Result {
148 self.f.write_str(&self.input[self.pos..pos])?;
149 self.pos = pos;
150 Ok(())
151 }
152}