1 // A Transpiler for the Brainf*** language |
1 // A Transpiler for the Brainf*** language |
2 //========================================= |
2 //========================================= |
3 // |
3 // |
4 // This version "optimises" the code by replacing |
4 // This version "optimises" the code by replacing |
5 // for example +++ by (*ptr) += 3, instead of |
5 // for example +++ by (*ptr) += 3, instead of three |
6 // (*ptr)++, (*ptr)++, (*ptr)++ |
6 // separate (*ptr)++, (*ptr)++, (*ptr)++ |
7 // |
7 // |
8 // Call with |
8 // Call with |
9 // |
9 // |
10 // amm bfc1.sc <<bf_program.bf>> |
10 // amm bfc1.sc <<bf_program.bf>> |
11 // |
11 // |
12 |
12 |
13 |
13 |
14 // generating "compound" c-instructions |
14 // generate "compound" c-instructions |
15 def instr2(c: Char, n: Int) : String = c match { |
15 def instr2(c: Char, n: Int) : String = c match { |
16 case '>' => s"ptr += $n ;" |
16 case '>' => s"ptr += $n ;" |
17 case '<' => s"ptr -= $n ;" |
17 case '<' => s"ptr -= $n ;" |
18 case '+' => s"(*ptr) += $n ;" |
18 case '+' => s"(*ptr) += $n ;" |
19 case '-' => s"(*ptr) -= $n ;" |
19 case '-' => s"(*ptr) -= $n ;" |
38 } |
38 } |
39 |
39 |
40 def instrs2(prog: String) : String = |
40 def instrs2(prog: String) : String = |
41 splice(prog.toList, Nil).reverse.mkString |
41 splice(prog.toList, Nil).reverse.mkString |
42 |
42 |
43 // adding the boilerplate |
43 // adding boilerplate |
44 def compile(prog: String) : String = |
44 def compile(prog: String) : String = |
45 s"""#include <string.h> |
45 s"""#include <string.h> |
46 #include <stdio.h> |
46 #include <stdio.h> |
47 char field[30000]; |
47 char field[30000]; |
48 char *ptr = &field[15000]; |
48 char *ptr = &field[15000]; |
49 int main() { |
49 int main() { |
50 memset(field, '\\0', 30000); |
50 memset(field, '\\0', 30000); |
51 ${instrs2(prog)} |
51 ${instrs2(prog)} |
52 return 0;}""" |
52 return 0;}""" |
53 |
53 |
54 def compile_file(name: String, prog: String) = |
54 def compile_to_file(name: String, prog: String) = |
55 os.write.over(os.pwd / name, compile(prog)) |
55 os.write.over(os.pwd / name, compile(prog)) |
56 |
56 |
57 |
57 |
58 // running the c-compiler over the transpiled |
58 // running the c-compiler over the transpiled |
59 // BF program and running the resulting binary |
59 // BF program and running the resulting binary |
60 |
60 |
61 def compile_run(prog: String) = { |
61 def compile_and_run(prog: String) = { |
62 val tn = "tmp" |
62 val tn = "tmp" |
63 compile_file(s"${tn}.c", prog) |
63 compile_to_file(s"${tn}.c", prog) |
64 os.proc("gcc", "-O0", "-o", tn, s"${tn}.c").call() // call gcc |
64 os.proc("gcc", "-O0", "-o", tn, s"${tn}.c").call() // call gcc |
65 os.proc("./tmp").call(stdout = os.Inherit) // run binary |
65 os.proc("./tmp").call(stdout = os.Inherit) // run binary |
66 } |
66 } |
67 |
67 |
68 // Running Testcases |
68 // Running Testcases |