Nicolas Winkler 5 роки тому
батько
коміт
8e73ebe023
3 змінених файлів з 194 додано та 0 видалено
  1. 125 0
      src/trans/c.rs
  2. 63 0
      src/trans/java.rs
  3. 6 0
      src/trans/mod.rs

+ 125 - 0
src/trans/c.rs

@@ -0,0 +1,125 @@
+
+use super::super::{ir, optimize, formatter};
+
+use ir::Instruction;
+use ir::ConstVisitor;
+use formatter::Formatter;
+
+struct CTranspiler {
+    pub code_buf: Formatter
+}
+
+
+pub fn transpile(instrs: &Vec<ir::Instruction>) -> String {
+    let mut transpiler = CTranspiler::default();
+    transpiler.visit_instructions(instrs);
+    transpiler.finalize();
+    return transpiler.code_buf.get_code();
+}
+
+
+impl Default for CTranspiler {
+    fn default() -> Self {
+        let mut transpiler = CTranspiler{ code_buf: Formatter::new() };
+
+        transpiler.code_buf.add_line(r#"#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+#define OFF(X) (ptr + (uint16_t) (X))
+
+int main() {
+    uint8_t* mem = (uint8_t*) calloc(0x10000, 1);
+    uint16_t ptr = 0;"#);
+        transpiler.code_buf.indent();
+        transpiler
+    }
+}
+
+impl CTranspiler {
+    pub fn finalize(&mut self) {
+        self.code_buf.add_line("free(mem);");
+        self.code_buf.unindent();
+        self.code_buf.add_line("}");
+    }
+}
+
+
+impl ir::ConstVisitor for CTranspiler {
+    type Ret = ();
+
+    fn visit_nop(&mut self, nop: &Instruction) {
+        self.code_buf.add_line("");
+    }
+
+    fn visit_add(&mut self, add: &'_ Instruction) {
+        if let Instruction::Add{ offset, value } = add {
+            self.code_buf.add_line(&format!("mem[OFF({})] += {};", offset, value));
+        }
+    }
+
+    fn visit_set(&mut self, set: &'_ Instruction) {
+        if let Instruction::Set{ offset, value } = set {
+            self.code_buf.add_line(&format!("mem[OFF({})] = {};", offset, value));
+        }
+    }
+
+    fn visit_linear_loop(&mut self, l: &Instruction) {
+        if let Instruction::LinearLoop{ offset: glob_offset, factors } = l {
+            for (&offset, &factor) in factors {
+                if offset == 0 {
+                    continue;
+                }
+
+                if factor == 0 {
+                }
+                else if factor == 1 {
+                    self.code_buf.add_line(&format!("mem[OFF({})] += mem[OFF({})];", glob_offset + offset, glob_offset));
+                }
+                else if factor == -1 {
+                    self.code_buf.add_line(&format!("mem[OFF({})] -= mem[OFF({})];", glob_offset + offset, glob_offset));
+                }
+                else {
+                    self.code_buf.add_line(&format!("mem[OFF({})] += {} * mem[OFF({})];", glob_offset + offset, factor, glob_offset));
+                }
+            }
+            self.code_buf.add_line(&format!("mem[OFF({})] = 0;", glob_offset));
+        }
+    }
+
+    fn visit_move_ptr(&mut self, mp: &Instruction) {
+        if let Instruction::MovePtr(offset) = mp {
+            self.code_buf.add_line(&format!("ptr = OFF({});", offset));
+        }
+    }
+
+    fn visit_loop(&mut self, l: &Instruction) {
+        if let Instruction::Loop(insts) = l {
+            if insts.len() == 1 {
+                if let Instruction::MovePtr(1) = insts[0] {
+                    //self.code_buf.add_line("printf(\"strlen(%s, %d)\\n\", buffer, strlen(buffer));");
+                    self.code_buf.add_line("ptr = OFF(strlen(&mem[ptr]));");
+                    return;
+                }
+            }
+            self.code_buf.add_line("while(mem[OFF(0)]) {");
+            self.code_buf.indent();
+            self.visit_instructions(insts);
+            self.code_buf.unindent();
+            self.code_buf.add_line("}");
+        }
+    }
+    
+    fn visit_read(&mut self, r: &Instruction) {
+        if let Instruction::Read(offset) = r {
+            self.code_buf.add_line(&format!("mem[OFF({})] = getchar();", offset));
+        }
+    }
+
+    fn visit_write(&mut self, w: &Instruction) {
+        if let Instruction::Write(offset) = w {
+            self.code_buf.add_line(&format!("putchar(mem[OFF({})]);", offset));
+        }
+    }
+}

+ 63 - 0
src/trans/java.rs

@@ -0,0 +1,63 @@
+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("class Brainfuck {");
+    formatter.indent();
+    formatter.add_line("public static void main(String[] args) {");
+    formatter.indent();
+    formatter.add_line("byte[] mem = new byte[0x10000];");
+    formatter.add_line("int ptr = 0;");
+    formatter.add_line("");
+
+    generate(&mut formatter, instrs);
+
+    formatter.unindent();
+    formatter.add_line("}");
+    formatter.unindent();
+    formatter.add_line("}");
+
+    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] += {};", 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];", 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();
+                formatter.add_line("}");
+            },
+            Instruction::Read(offset) => {
+                formatter.add_line(&format!("mem[(ptr + {}) & 0xFFFF] = (byte) System.in.read();", offset));
+            },
+            Instruction::Write(offset) => {
+                formatter.add_line(&format!("System.out.write(mem[(ptr + {}) & 0xFFFF]);", offset));
+                formatter.add_line(&format!("System.out.flush();"));
+            }
+        }
+    }
+}

+ 6 - 0
src/trans/mod.rs

@@ -0,0 +1,6 @@
+
+
+
+pub mod c;
+pub mod java;
+