cly_impl/
printer.rs

1// SPDX-License-Identifier: GPL-3.0-or-later
2use 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}