| author | Christian Urban <christian.urban@kcl.ac.uk> | 
| Fri, 24 Jul 2020 13:06:09 +0100 | |
| changeset 739 | b44a4631e089 | 
| parent 738 | 03f46065ef04 | 
| permissions | -rw-r--r-- | 
| 738 
03f46065ef04
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
736diff
changeset | 1 | // A Transpiler for the Brainf*** language to C | 
| 
03f46065ef04
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
736diff
changeset | 2 | //=============================================== | 
| 
03f46065ef04
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
736diff
changeset | 3 | // | 
| 
03f46065ef04
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
736diff
changeset | 4 | // Call with | 
| 
03f46065ef04
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
736diff
changeset | 5 | // | 
| 
03f46065ef04
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
736diff
changeset | 6 | // amm bfc0.sc <<bf_program.bf>> | 
| 
03f46065ef04
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
736diff
changeset | 7 | // | 
| 633 | 8 | |
| 738 
03f46065ef04
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
736diff
changeset | 9 | |
| 633 | 10 | import scala.util._ | 
| 11 | ||
| 12 | ||
| 13 | // loding a bf-file | |
| 14 | def load_bff(name: String) : String = | |
| 15 |   Try(Source.fromFile(name)("ISO-8859-1").mkString).getOrElse("")
 | |
| 16 | ||
| 17 | ||
| 18 | // simple instructions | |
| 19 | def instr(c: Char) : String = c match {
 | |
| 20 | case '>' => "ptr++;" | |
| 21 | case '<' => "ptr--;" | |
| 22 | case '+' => "(*ptr)++;" | |
| 23 | case '-' => "(*ptr)--;" | |
| 24 | case '.' => "putchar(*ptr);" | |
| 25 | case ',' => "*ptr = getchar();\n" | |
| 26 |   case '['  => "while(*ptr){"
 | |
| 27 | case ']' => "}" | |
| 28 | case _ => "" | |
| 29 | } | |
| 30 | ||
| 31 | def instrs(prog: String) : String = | |
| 32 | prog.toList.map(instr(_)).mkString | |
| 33 | ||
| 34 | ||
| 35 | def compile_str(prog: String) : String = {
 | |
| 36 | "#include <string.h>\n" ++ | |
| 37 | "#include <stdio.h>\n" ++ | |
| 38 | "char field[30000];\n" ++ | |
| 39 | "char *ptr = &field[15000];" ++ | |
| 40 |   "int main()\n{\n" ++
 | |
| 41 | "memset(field, '\\0', 30000);\n" ++ | |
| 42 | instrs(prog) ++ | |
| 43 | "\n return 0;\n}" | |
| 44 | } | |
| 45 | ||
| 46 | def compile(name: String, prog: String) = {
 | |
| 47 | val fw = new java.io.FileWriter(name + ".c") | |
| 48 | val is = compile_str(prog) | |
| 49 | //println(is) | |
| 50 | fw.write(is) | |
| 51 | fw.close() | |
| 52 | } | |
| 53 | ||
| 636 | 54 | // running the c-compiler over the transpiled | 
| 55 | // BF program and running the result | |
| 633 | 56 | import sys.process._ | 
| 57 | ||
| 58 | def compile_run(prog: String) = {
 | |
| 59 |   compile("tmp", prog)
 | |
| 638 | 60 | "gcc -O3 -o tmp tmp.c".! | 
| 633 | 61 | "./tmp".! | 
| 62 | () | |
| 63 | } | |
| 64 | ||
| 65 | def time_needed[T](n: Int, code: => T) = {
 | |
| 66 | val start = System.nanoTime() | |
| 67 | for (i <- 0 until n) code | |
| 68 | val end = System.nanoTime() | |
| 69 | (end - start)/(n * 1.0e9) | |
| 70 | } | |
| 71 | ||
| 738 
03f46065ef04
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
736diff
changeset | 72 | // Running Testcases | 
| 
03f46065ef04
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
736diff
changeset | 73 | //=================== | 
| 633 | 74 | |
| 738 
03f46065ef04
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
736diff
changeset | 75 | @doc(" the argument should be a BF program ")
 | 
| 
03f46065ef04
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
736diff
changeset | 76 | @main | 
| 
03f46065ef04
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
736diff
changeset | 77 | def main(fname: String) = {
 | 
| 
03f46065ef04
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
736diff
changeset | 78 | val bf_str = os.read(os.pwd / fname) | 
| 
03f46065ef04
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
736diff
changeset | 79 |   println(s"${time_needed(1, run(bf_str))} secs")
 | 
| 
03f46065ef04
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
736diff
changeset | 80 | } | 
| 633 | 81 | |
| 82 | ||
| 83 |