1use std::fmt::{self, Write};
8
9use inform::common::IndentWriterCommon;
10
11use crate::ast;
12
13pub struct Printer<'writer, W: fmt::Write> {
14 w: inform::fmt::IndentWriter<'writer, W>,
15}
16
17impl<'writer, W: fmt::Write> Printer<'writer, W> {
18 pub fn new(writer: &'writer mut W, indent: usize) -> Self {
19 Self {
20 w: inform::fmt::IndentWriter::new(writer, indent),
21 }
22 }
23
24 pub fn print_imported_function_alias(
25 &mut self,
26 imported_function_alias: &ast::ImportedFunctionAlias,
27 ) -> fmt::Result {
28 write!(self.w, "as {}", imported_function_alias.name)
29 }
30
31 pub fn print_imported_function(
32 &mut self,
33 imported_function: &ast::ImportedFunction,
34 ) -> fmt::Result {
35 write!(self.w, "{}", imported_function.name)?;
36
37 if let Some(alias) = &imported_function.alias {
38 write!(self.w, " ")?;
39 self.print_imported_function_alias(alias)?;
40 }
41
42 Ok(())
43 }
44
45 pub fn print_import(&mut self, import: &ast::Import) -> fmt::Result {
46 write!(self.w, "from \"{}\" import ", import.path)?;
47 for (i, imported_function) in import.imported_functions.iter().enumerate() {
48 if i > 0 {
49 write!(self.w, ", ")?;
50 }
51 self.print_imported_function(imported_function)?;
52 }
53 writeln!(self.w, ";")?;
54
55 Ok(())
56 }
57
58 pub fn print_type(&mut self, ty: &ast::Type) -> fmt::Result {
59 match ty {
60 ast::Type::Int => write!(self.w, "int"),
61 ast::Type::Bool => write!(self.w, "bool"),
62 ast::Type::Float => write!(self.w, "float"),
63 ast::Type::Char => write!(self.w, "char"),
64 ast::Type::Ptr(inner) => {
65 write!(self.w, "ptr<")?;
66 self.print_type(inner)?;
67 write!(self.w, ">")
68 }
69 }
70 }
71
72 pub fn print_type_annotation(&mut self, type_annotation: &ast::TypeAnnotation) -> fmt::Result {
73 write!(self.w, ": ")?;
74 self.print_type(&type_annotation.ty)
75 }
76
77 pub fn print_label(&mut self, label: &ast::Label) -> fmt::Result {
78 write!(self.w, "{}", label.name)
79 }
80
81 pub fn print_constant_value(&mut self, constant_value: &ast::ConstantValue) -> fmt::Result {
82 match constant_value {
83 ast::ConstantValue::IntegerLiteral(integer) => {
84 write!(self.w, "{}", integer)
85 }
86 ast::ConstantValue::BooleanLiteral(boolean) => {
87 write!(self.w, "{}", boolean)
88 }
89 ast::ConstantValue::FloatLiteral(float) => {
90 write!(self.w, "{}", float)
91 }
92 ast::ConstantValue::CharacterLiteral(character) => {
93 write!(self.w, "{}", character)
94 }
95 }
96 }
97
98 pub fn print_constant(&mut self, constant: &ast::Constant) -> fmt::Result {
99 write!(self.w, "{}", constant.name)?;
100 if let Some(type_annotation) = &constant.type_annotation {
101 self.print_type_annotation(type_annotation)?;
102 }
103 write!(self.w, " = const ")?;
104 self.print_constant_value(&constant.value)?;
105 write!(self.w, ";")
106 }
107
108 pub fn print_value_operation_op(
109 &mut self,
110 value_operation_op: &ast::ValueOperationOp,
111 ) -> fmt::Result {
112 match value_operation_op {
113 ast::ValueOperationOp::Add(lhs, rhs) => {
114 write!(self.w, "add {} {}", lhs, rhs)
115 }
116 ast::ValueOperationOp::Mul(lhs, rhs) => {
117 write!(self.w, "mul {} {}", lhs, rhs)
118 }
119 ast::ValueOperationOp::Sub(lhs, rhs) => {
120 write!(self.w, "sub {} {}", lhs, rhs)
121 }
122 ast::ValueOperationOp::Div(lhs, rhs) => {
123 write!(self.w, "div {} {}", lhs, rhs)
124 }
125 ast::ValueOperationOp::Eq(lhs, rhs) => {
126 write!(self.w, "eq {} {}", lhs, rhs)
127 }
128 ast::ValueOperationOp::Lt(lhs, rhs) => {
129 write!(self.w, "lt {} {}", lhs, rhs)
130 }
131 ast::ValueOperationOp::Gt(lhs, rhs) => {
132 write!(self.w, "gt {} {}", lhs, rhs)
133 }
134 ast::ValueOperationOp::Le(lhs, rhs) => {
135 write!(self.w, "le {} {}", lhs, rhs)
136 }
137 ast::ValueOperationOp::Ge(lhs, rhs) => {
138 write!(self.w, "ge {} {}", lhs, rhs)
139 }
140 ast::ValueOperationOp::Not(value) => {
141 write!(self.w, "not {}", value)
142 }
143 ast::ValueOperationOp::And(lhs, rhs) => {
144 write!(self.w, "and {} {}", lhs, rhs)
145 }
146 ast::ValueOperationOp::Or(lhs, rhs) => {
147 write!(self.w, "or {} {}", lhs, rhs)
148 }
149 ast::ValueOperationOp::Call(function_name, arguments) => {
150 write!(
151 self.w,
152 "call {} {}",
153 function_name,
154 arguments
155 .iter()
156 .map(|argument| argument.to_string())
157 .collect::<Vec<_>>()
158 .join(" ")
159 )
160 }
161 ast::ValueOperationOp::Id(value) => {
162 write!(self.w, "id {}", value)
163 }
164 ast::ValueOperationOp::Fadd(lhs, rhs) => {
165 write!(self.w, "fadd {} {}", lhs, rhs)
166 }
167 ast::ValueOperationOp::Fmul(lhs, rhs) => {
168 write!(self.w, "fmul {} {}", lhs, rhs)
169 }
170 ast::ValueOperationOp::Fsub(lhs, rhs) => {
171 write!(self.w, "fsub {} {}", lhs, rhs)
172 }
173 ast::ValueOperationOp::Fdiv(lhs, rhs) => {
174 write!(self.w, "fdiv {} {}", lhs, rhs)
175 }
176 ast::ValueOperationOp::Feq(lhs, rhs) => {
177 write!(self.w, "feq {} {}", lhs, rhs)
178 }
179 ast::ValueOperationOp::Flt(lhs, rhs) => {
180 write!(self.w, "flt {} {}", lhs, rhs)
181 }
182 ast::ValueOperationOp::Fle(lhs, rhs) => {
183 write!(self.w, "fle {} {}", lhs, rhs)
184 }
185 ast::ValueOperationOp::Fgt(lhs, rhs) => {
186 write!(self.w, "fgt {} {}", lhs, rhs)
187 }
188 ast::ValueOperationOp::Fge(lhs, rhs) => {
189 write!(self.w, "fge {} {}", lhs, rhs)
190 }
191 ast::ValueOperationOp::Alloc(size) => {
192 write!(self.w, "alloc {}", size)
193 }
194 ast::ValueOperationOp::Load(pointer) => {
195 write!(self.w, "load {}", pointer)
196 }
197 ast::ValueOperationOp::PtrAdd(pointer, offset) => {
198 write!(self.w, "ptradd {} {}", pointer, offset)
199 }
200 ast::ValueOperationOp::Ceq(lhs, rhs) => {
201 write!(self.w, "ceq {} {}", lhs, rhs)
202 }
203 ast::ValueOperationOp::Clt(lhs, rhs) => {
204 write!(self.w, "clt {} {}", lhs, rhs)
205 }
206 ast::ValueOperationOp::Cle(lhs, rhs) => {
207 write!(self.w, "cle {} {}", lhs, rhs)
208 }
209 ast::ValueOperationOp::Cgt(lhs, rhs) => {
210 write!(self.w, "cgt {} {}", lhs, rhs)
211 }
212 ast::ValueOperationOp::Cge(lhs, rhs) => {
213 write!(self.w, "cge {} {}", lhs, rhs)
214 }
215 ast::ValueOperationOp::Char2Int(value) => write!(self.w, "char2int {}", value),
216 ast::ValueOperationOp::Int2Char(value) => write!(self.w, "int2char {}", value),
217 }
218 }
219
220 pub fn print_value_operation(&mut self, value_operation: &ast::ValueOperation) -> fmt::Result {
221 write!(self.w, "{}", value_operation.name)?;
222 if let Some(type_annotation) = &value_operation.type_annotation {
223 self.print_type_annotation(type_annotation)?;
224 }
225 write!(self.w, " = ")?;
226 self.print_value_operation_op(&value_operation.op)?;
227 write!(self.w, ";")
228 }
229
230 pub fn print_effect_operation_op(
231 &mut self,
232 effect_operation_op: &ast::EffectOperationOp,
233 ) -> fmt::Result {
234 match effect_operation_op {
235 ast::EffectOperationOp::Jmp(destination) => {
236 write!(self.w, "jmp ")?;
237 self.print_label(destination)
238 }
239 ast::EffectOperationOp::Br(condition, if_true, if_false) => {
240 write!(self.w, "br {} ", condition)?;
241 self.print_label(if_true)?;
242 write!(self.w, " ")?;
243 self.print_label(if_false)
244 }
245 ast::EffectOperationOp::Call(function_name, arguments) => {
246 write!(
247 self.w,
248 "call {} {}",
249 function_name,
250 arguments
251 .iter()
252 .map(|argument| argument.to_string())
253 .collect::<Vec<_>>()
254 .join(" ")
255 )
256 }
257 ast::EffectOperationOp::Ret(value) => {
258 write!(self.w, "ret")?;
259 if let Some(value) = value {
260 write!(self.w, " {}", value)?;
261 }
262 Ok(())
263 }
264 ast::EffectOperationOp::Print(arguments) => {
265 write!(
266 self.w,
267 "print {}",
268 arguments
269 .iter()
270 .map(|argument| argument.to_string())
271 .collect::<Vec<_>>()
272 .join(" ")
273 )
274 }
275 ast::EffectOperationOp::Nop => write!(self.w, "nop"),
276 ast::EffectOperationOp::Store(pointer, value) => {
277 write!(self.w, "store {} {}", pointer, value)
278 }
279 ast::EffectOperationOp::Free(pointer) => write!(self.w, "free {}", pointer),
280 }
281 }
282
283 pub fn print_effect_operation(
284 &mut self,
285 effect_operation: &ast::EffectOperation,
286 ) -> fmt::Result {
287 self.print_effect_operation_op(&effect_operation.op)?;
288 write!(self.w, ";")
289 }
290
291 pub fn print_instruction(&mut self, instruction: &ast::Instruction) -> fmt::Result {
292 match instruction {
293 ast::Instruction::Constant(constant) => self.print_constant(constant),
294 ast::Instruction::ValueOperation(value_operation) => {
295 self.print_value_operation(value_operation)
296 }
297 ast::Instruction::EffectOperation(effect_operation) => {
298 self.print_effect_operation(effect_operation)
299 }
300 }
301 }
302
303 pub fn print_function_code(&mut self, code: &ast::FunctionCode) -> fmt::Result {
304 match code {
305 ast::FunctionCode::Label { label, comment, .. } => {
306 self.w.decrease_indent();
307 self.print_label(label)?;
308 write!(self.w, ":")?;
309 self.w.increase_indent();
310 if let Some(comment) = comment {
311 writeln!(self.w, " {}", comment)?;
312 }
313 writeln!(self.w)
314 }
315 ast::FunctionCode::Instruction { inner, comment } => {
316 self.print_instruction(inner)?;
317 if let Some(comment) = comment {
318 writeln!(self.w, " {}", comment)?;
319 }
320 writeln!(self.w)
321 }
322 ast::FunctionCode::Comment(comment) => {
323 writeln!(self.w, "{}", comment)
324 }
325 ast::FunctionCode::EmptyLine(_) => writeln!(self.w),
326 }
327 }
328
329 pub fn print_function(&mut self, function: &ast::Function) -> fmt::Result {
330 write!(self.w, "{}(", function.name)?;
331
332 for (i, (name, type_annotation)) in function.parameters.iter().enumerate() {
333 if i > 0 {
334 write!(self.w, ", ")?;
335 }
336 write!(self.w, "{}", name)?;
337 self.print_type_annotation(type_annotation)?;
338 }
339
340 write!(self.w, ")")?;
341
342 if let Some(return_type) = &function.return_type {
343 self.print_type_annotation(return_type)?;
344 }
345
346 writeln!(self.w, " {{")?;
347 self.w.increase_indent();
348
349 for code in &function.body {
350 self.print_function_code(code)?;
351 }
352
353 self.w.decrease_indent();
354 writeln!(self.w, "}}")?;
355
356 Ok(())
357 }
358
359 pub fn print_comment(&mut self, comment: &str) -> fmt::Result {
360 writeln!(self.w, "{}", comment)
361 }
362
363 pub fn print_newline(&mut self) -> fmt::Result {
364 writeln!(self.w)
365 }
366
367 pub fn print_top_level_item(&mut self, item: &ast::TopLevelItem) -> fmt::Result {
368 match item {
369 ast::TopLevelItem::Import(import) => self.print_import(import),
370 ast::TopLevelItem::Function(function) => self.print_function(function),
371 ast::TopLevelItem::Comment(comment) => self.print_comment(comment),
372 ast::TopLevelItem::Newline(_) => self.print_newline(),
373 }
374 }
375
376 pub fn print_program(&mut self, program: &ast::Program) -> fmt::Result {
377 for item in &program.items {
378 self.print_top_level_item(item)?;
379 }
380
381 Ok(())
382 }
383}