|  | @@ -0,0 +1,54 @@
 | 
	
		
			
				|  |  | +use super::super::{ir, formatter};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +use ir::Instruction;
 | 
	
		
			
				|  |  | +use formatter::Formatter;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +pub fn transpile(instrs: &Vec<ir::Instruction>) -> String {
 | 
	
		
			
				|  |  | +    let mut formatter = Formatter::new();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    formatter.add_line("import sys");
 | 
	
		
			
				|  |  | +    formatter.add_line("mem = [0] * 0x10000");
 | 
	
		
			
				|  |  | +    formatter.add_line("ptr = 0");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    generate(&mut formatter, instrs);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    formatter.get_code()
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +fn generate(formatter: &mut Formatter, instrs: &Vec<Instruction>) {
 | 
	
		
			
				|  |  | +    for instr in instrs {
 | 
	
		
			
				|  |  | +        match instr {
 | 
	
		
			
				|  |  | +            Instruction::Nop => {},
 | 
	
		
			
				|  |  | +            Instruction::Add{ offset, value } => {
 | 
	
		
			
				|  |  | +                formatter.add_line(&format!("mem[(ptr + {}) & 0xFFFF] = (mem[(ptr + {}) & 0xFFFF] + {}) & 0xFF", offset, offset, value));
 | 
	
		
			
				|  |  | +            },
 | 
	
		
			
				|  |  | +            Instruction::Set{ offset, value } => {
 | 
	
		
			
				|  |  | +                formatter.add_line(&format!("mem[(ptr + {}) & 0xFFFF] = {}", offset, value));
 | 
	
		
			
				|  |  | +            },
 | 
	
		
			
				|  |  | +            Instruction::LinearLoop{ offset, factors } => {
 | 
	
		
			
				|  |  | +                for (off, factor) in factors {
 | 
	
		
			
				|  |  | +                    formatter.add_line(&format!("mem[(ptr + {}) & 0xFFFF] = (mem[(ptr + {}) & 0xFFFF] + {} * mem[(ptr + {}) & 0xFFFF]) & 0xFF",
 | 
	
		
			
				|  |  | +                                                offset + off, offset + off, factor, offset));
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                formatter.add_line(&format!("mem[(ptr + {}) & 0xFFFF] = 0", offset));
 | 
	
		
			
				|  |  | +            },
 | 
	
		
			
				|  |  | +            Instruction::MovePtr(offset) => {
 | 
	
		
			
				|  |  | +                formatter.add_line(&format!("ptr += {}", offset));
 | 
	
		
			
				|  |  | +            },
 | 
	
		
			
				|  |  | +            Instruction::Loop(instructions) => {
 | 
	
		
			
				|  |  | +                formatter.add_line("while mem[ptr & 0xFFFF] != 0:");
 | 
	
		
			
				|  |  | +                formatter.indent();
 | 
	
		
			
				|  |  | +                generate(formatter, instructions);
 | 
	
		
			
				|  |  | +                formatter.unindent();
 | 
	
		
			
				|  |  | +            },
 | 
	
		
			
				|  |  | +            Instruction::Read(offset) => {
 | 
	
		
			
				|  |  | +                formatter.add_line(&format!("mem[(ptr + {}) & 0xFFFF] = sys.stdin.buffer.read(1)", offset));
 | 
	
		
			
				|  |  | +            },
 | 
	
		
			
				|  |  | +            Instruction::Write(offset) => {
 | 
	
		
			
				|  |  | +                formatter.add_line(&format!("sys.stdout.buffer.write(mem[(ptr + {}) & 0xFFFF].to_bytes(1, 'little'))", offset));
 | 
	
		
			
				|  |  | +                formatter.add_line("sys.stdout.buffer.flush()");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 |