progs/bf/bfc1.sc
changeset 742 b5b5583a3a08
parent 740 923b946347e6
child 746 6916229b817b
equal deleted inserted replaced
741:e66bd5c563eb 742:b5b5583a3a08
     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
    77 
    77 
    78 @doc(" the argument should be a BF program ")
    78 @doc(" the argument should be a BF program ")
    79 @main
    79 @main
    80 def main(fname: String) = {
    80 def main(fname: String) = {
    81   val bf_str = os.read(os.pwd / fname)
    81   val bf_str = os.read(os.pwd / fname)
    82   println(s"${time_needed(1, compile_run(bf_str))} secs")
    82   println(s"${time_needed(1, compile_and_run(bf_str))} secs")
    83 }  
    83 }  
    84 
    84