1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
pub trait IRFormatter {
    fn increase_indent(&mut self);
    fn decrease_indent(&mut self);
    fn get_indent(&self) -> u32;
    fn write_direct(&mut self, data: &str);

    fn indent(&mut self) {
        for _ in 0..self.get_indent() {
            self.write_direct("  ");
        }
    }

    fn indent_write(&mut self, data: &str) {
        self.indent();
        self.write_direct(data)
    }

    fn start_region(&mut self) {
        self.write_direct("{\n");
        self.increase_indent();
    }

    fn end_region(&mut self) {
        self.decrease_indent();
        self.indent_write("}");
    }
}

pub struct StdoutPrinter {
    indent: u32,
}

impl Default for StdoutPrinter {
    fn default() -> Self {
        Self::new()
    }
}

impl StdoutPrinter {
    pub fn new() -> Self {
        StdoutPrinter { indent: 0 }
    }
}

impl IRFormatter for StdoutPrinter {
    fn increase_indent(&mut self) {
        self.indent += 1;
    }

    fn decrease_indent(&mut self) {
        self.indent -= 1;
    }

    fn get_indent(&self) -> u32 {
        self.indent
    }

    fn write_direct(&mut self, data: &str) {
        print!("{}", data);
    }
}

pub struct StringPrinter {
    indent: u32,
    data: String,
}

impl Default for StringPrinter {
    fn default() -> Self {
        Self::new()
    }
}

impl StringPrinter {
    pub fn new() -> Self {
        StringPrinter {
            indent: 0,
            data: String::new(),
        }
    }

    pub fn get(&self) -> String {
        self.data.clone()
    }
}

impl IRFormatter for StringPrinter {
    fn increase_indent(&mut self) {
        self.indent += 1;
    }

    fn decrease_indent(&mut self) {
        self.indent -= 1;
    }

    fn get_indent(&self) -> u32 {
        self.indent
    }

    fn write_direct(&mut self, data: &str) {
        self.data += data;
    }
}