1 // A Transpiler for the Brainf*** language to C  | 
         | 
     2 //===============================================  | 
         | 
     3 //  | 
         | 
     4 // Call with  | 
         | 
     5 //  | 
         | 
     6 //  amm bfc0.sc <<bf_program.bf>>  | 
         | 
     7 //  | 
         | 
     8   | 
         | 
     9   | 
         | 
    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   | 
         | 
    54 // running the c-compiler over the transpiled  | 
         | 
    55 // BF program and running the result  | 
         | 
    56 import sys.process._  | 
         | 
    57   | 
         | 
    58 def compile_run(prog: String) = { | 
         | 
    59   compile("tmp", prog) | 
         | 
    60   "gcc -O3 -o tmp tmp.c".!  | 
         | 
    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   | 
         | 
    72 // Running Testcases  | 
         | 
    73 //===================  | 
         | 
    74   | 
         | 
    75 @doc(" the argument should be a BF program ") | 
         | 
    76 @main  | 
         | 
    77 def main(fname: String) = { | 
         | 
    78   val bf_str = os.read(os.pwd / fname)  | 
         | 
    79   println(s"${time_needed(1, run(bf_str))} secs") | 
         | 
    80 }    | 
         | 
    81   | 
         | 
    82   | 
         | 
    83   | 
         |