1#[cfg(test)]
2mod tests;
3use super::BrainfuckInstr;
4const ALLOCATE_AND_START: &str = include_str!("compiler/alloc_start.asm");
6const EXIT_SYSCALL: &str = include_str!("compiler/exit.asm");
8
9pub fn compile(code: &[BrainfuckInstr]) -> String {
11 let mut output = String::new();
12 output.push_str(ALLOCATE_AND_START);
13 let mut total_loops = 0;
14 let mut loop_no_stack = Vec::new();
15 for instruction in code {
16 translate_instruction(
18 instruction,
19 &mut total_loops,
20 &mut loop_no_stack,
21 &mut output
22 );
23 }
24 output.push_str(EXIT_SYSCALL);
25 output
26}
27fn translate_instruction(instruction: &BrainfuckInstr, total_loops: &mut u32, loop_no_stack: &mut Vec<u32>, output: &mut String) {
29 use BrainfuckInstr::*;
30 output.push_str(match instruction {
31 PointerDec => "dec rsi",
32 PointerInc => "inc rsi",
33 DataDec => "dec byte [rsi]",
34 DataInc => "inc byte [rsi]",
35 GetByte => "mov rdx,1\nmov rdi,0\nmov rax,0\nsyscall",
36 PutByte => "mov rdx,1\nmov rdi,1\nmov rax,1\nsyscall",
37 WhileNonzero => {
38 *total_loops += 1;
39 loop_no_stack.push(*total_loops);
40 let asm = format!(
41 "cmp byte [rsi],0\nje .end_{x}\n.while_{x}:\n",
42 x = total_loops
45 );
46 output.push_str(&asm);
47 return },
50 EndWhile => {
51 let asm = format!(
52 "cmp byte [rsi],0\njne .while_{x}\n.end_{x}:\n",
53 x = loop_no_stack.pop().expect("There should be a loop number on the stack at this point.")
54 );
55 output.push_str(&asm);
56 return },
58 BrainfuckInstr::PointerSub(x) => {
63 let asm = format!("sub rsi,{x}\n", x = x);
64 output.push_str(&asm);
65 return
66 },
67 BrainfuckInstr::PointerAdd(x) => {
68 let asm = format!("add rsi,{x}\n", x = x);
69 output.push_str(&asm);
70 return
71 },
72 BrainfuckInstr::DataSub(x) => {
73 let asm = format!("sub byte [rsi],{x}\n", x = x);
74 output.push_str(&asm);
75 return
76 },
77 BrainfuckInstr::DataAdd(x) => {
78 let asm = format!("add byte [rsi],{x}\n", x = x);
79 output.push_str(&asm);
80 return
81 },
82 BrainfuckInstr::Print(x) => {
83 let asm = format!("mov rdx,{x}\nmov rdi,1\nmov rax,1\nsyscall\n", x = x);
85 output.push_str(&asm);
86 return
87 }
88 });
89 output.push('\n');
90}