|  | @@ -1,59 +1,63 @@
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -use super::{ir, optimize};
 | 
	
		
			
				|  |  | +use super::{ir, optimize, formatter};
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  use ir::Instruction;
 | 
	
		
			
				|  |  |  use ir::ConstVisitor;
 | 
	
		
			
				|  |  | +use formatter::Formatter;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -struct Transpiler {
 | 
	
		
			
				|  |  | -    pub code: String
 | 
	
		
			
				|  |  | +struct CTranspiler {
 | 
	
		
			
				|  |  | +    pub code_buf: Formatter
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  pub fn transpile_c(instrs: &Vec<ir::Instruction>) -> String {
 | 
	
		
			
				|  |  | -    let mut transpiler = Transpiler::default();
 | 
	
		
			
				|  |  | +    let mut transpiler = CTranspiler::default();
 | 
	
		
			
				|  |  |      transpiler.visit_instructions(instrs);
 | 
	
		
			
				|  |  |      transpiler.finalize();
 | 
	
		
			
				|  |  | -    return transpiler.code;
 | 
	
		
			
				|  |  | +    return transpiler.code_buf.get_code();
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -impl Default for Transpiler {
 | 
	
		
			
				|  |  | +impl Default for CTranspiler {
 | 
	
		
			
				|  |  |      fn default() -> Self {
 | 
	
		
			
				|  |  | -        let mut transpiler = Transpiler{ code: "".to_string() };
 | 
	
		
			
				|  |  | +        let mut transpiler = CTranspiler{ code_buf: Formatter::new() };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        transpiler.code += r#"#include <stdio.h>
 | 
	
		
			
				|  |  | +        transpiler.code_buf.add_line(r#"#include <stdio.h>
 | 
	
		
			
				|  |  |  #include <stdlib.h>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  int main() {
 | 
	
		
			
				|  |  | -    unsigned char* buffer = calloc(2000000000, 1);
 | 
	
		
			
				|  |  | -    buffer += 1000000000;
 | 
	
		
			
				|  |  | -"#;
 | 
	
		
			
				|  |  | +    unsigned char* restrict buffer = (unsigned char*) calloc(2000000000, 1);
 | 
	
		
			
				|  |  | +    buffer += 1000000000;"#);
 | 
	
		
			
				|  |  | +        transpiler.code_buf.indent();
 | 
	
		
			
				|  |  |          transpiler
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -impl Transpiler {
 | 
	
		
			
				|  |  | +impl CTranspiler {
 | 
	
		
			
				|  |  |      pub fn finalize(&mut self) {
 | 
	
		
			
				|  |  | -        self.code += "}\n";
 | 
	
		
			
				|  |  | +        self.code_buf.unindent();
 | 
	
		
			
				|  |  | +        self.code_buf.add_line("}");
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -impl ir::ConstVisitor for Transpiler {
 | 
	
		
			
				|  |  | +impl ir::ConstVisitor for CTranspiler {
 | 
	
		
			
				|  |  |      type Ret = ();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      fn visit_nop(&mut self, nop: &Instruction) {
 | 
	
		
			
				|  |  | -        self.code += "\n";
 | 
	
		
			
				|  |  | +        self.code_buf.add_line("");
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      fn visit_add(&mut self, add: &'_ Instruction) {
 | 
	
		
			
				|  |  |          if let Instruction::Add{ offset, value } = add {
 | 
	
		
			
				|  |  | -            self.code += &format!("buffer[{}] += {};\n", offset, value);
 | 
	
		
			
				|  |  | +            self.code_buf.add_line(&format!("buffer[{}] += {};", offset, value));
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      fn visit_set(&mut self, set: &'_ Instruction) {
 | 
	
		
			
				|  |  |          if let Instruction::Set{ offset, value } = set {
 | 
	
		
			
				|  |  | -            self.code += &format!("buffer[{}] = {};\n", offset, value);
 | 
	
		
			
				|  |  | +            self.code_buf.add_line(&format!("buffer[{}] = {};", offset, value));
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -67,42 +71,44 @@ impl ir::ConstVisitor for Transpiler {
 | 
	
		
			
				|  |  |                  if factor == 0 {
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |                  else if factor == 1 {
 | 
	
		
			
				|  |  | -                    self.code += &format!("buffer[{}] += buffer[0];\n", glob_offset + offset);
 | 
	
		
			
				|  |  | +                    self.code_buf.add_line(&format!("buffer[{}] += buffer[0];", glob_offset + offset));
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |                  else if factor == -1 {
 | 
	
		
			
				|  |  | -                    self.code += &format!("buffer[{}] -= buffer[0];\n", glob_offset + offset);
 | 
	
		
			
				|  |  | +                    self.code_buf.add_line(&format!("buffer[{}] -= buffer[0];", glob_offset + offset));
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |                  else {
 | 
	
		
			
				|  |  | -                    self.code += &format!("buffer[{}] += {} * buffer[0];\n", glob_offset + offset, factor);
 | 
	
		
			
				|  |  | +                    self.code_buf.add_line(&format!("buffer[{}] += {} * buffer[0];", glob_offset + offset, factor));
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | -            self.code += "buffer[0] = 0;\n";
 | 
	
		
			
				|  |  | +            self.code_buf.add_line("buffer[0] = 0;");
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      fn visit_move_ptr(&mut self, mp: &'_ Instruction) {
 | 
	
		
			
				|  |  |          if let Instruction::MovePtr(offset) = mp {
 | 
	
		
			
				|  |  | -            self.code += &format!("buffer += {};\n", offset);
 | 
	
		
			
				|  |  | +            self.code_buf.add_line(&format!("buffer += {};", offset));
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      fn visit_loop(&mut self, l: &Instruction) {
 | 
	
		
			
				|  |  |          if let Instruction::Loop(insts) = l {
 | 
	
		
			
				|  |  | -            self.code += "while(buffer[0]) {\n";
 | 
	
		
			
				|  |  | +            self.code_buf.add_line("while(buffer[0]) {");
 | 
	
		
			
				|  |  | +            self.code_buf.indent();
 | 
	
		
			
				|  |  |              self.visit_instructions(insts);
 | 
	
		
			
				|  |  | -            self.code += "}\n";
 | 
	
		
			
				|  |  | +            self.code_buf.unindent();
 | 
	
		
			
				|  |  | +            self.code_buf.add_line("}");
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      
 | 
	
		
			
				|  |  |      fn visit_read(&mut self, r: &Instruction) {
 | 
	
		
			
				|  |  |          if let Instruction::Read(offset) = r {
 | 
	
		
			
				|  |  | -            self.code += &format!("buffer[{}] = getchar();\n", offset);
 | 
	
		
			
				|  |  | +            self.code_buf.add_line(&format!("buffer[{}] = getchar();", offset));
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      fn visit_write(&mut self, w: &Instruction) {
 | 
	
		
			
				|  |  |          if let Instruction::Write(offset) = w {
 | 
	
		
			
				|  |  | -            self.code += &format!("putchar(buffer[{}]);\n", offset);
 | 
	
		
			
				|  |  | +            self.code_buf.add_line(&format!("putchar(buffer[{}]);", offset));
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 |