| 633 |      1 | // A Transpiler for the Brainf*** language
 | 
|  |      2 | //=========================================
 | 
|  |      3 | 
 | 
|  |      4 | import io.Source
 | 
|  |      5 | import scala.util._
 | 
|  |      6 | 
 | 
|  |      7 | 
 | 
|  |      8 | // loding a bf-file 
 | 
|  |      9 | def load_bff(name: String) : String = 
 | 
|  |     10 |   Try(Source.fromFile(name)("ISO-8859-1").mkString).getOrElse("")
 | 
|  |     11 | 
 | 
|  |     12 | 
 | 
|  |     13 | // simple instructions
 | 
|  |     14 | def instr(c: Char) : String = c match {
 | 
|  |     15 |   case '>' => "ptr++;"
 | 
|  |     16 |   case '<' => "ptr--;"
 | 
|  |     17 |   case '+' => "(*ptr)++;"
 | 
|  |     18 |   case '-' => "(*ptr)--;"
 | 
|  |     19 |   case '.' => "putchar(*ptr);"
 | 
|  |     20 |   case ',' => "*ptr = getchar();\n"
 | 
|  |     21 |   case '['  => "while(*ptr){"
 | 
|  |     22 |   case ']'  => "}"
 | 
|  |     23 |   case _ => ""
 | 
|  |     24 | }
 | 
|  |     25 | 
 | 
|  |     26 | def instrs(prog: String) : String =
 | 
|  |     27 |   prog.toList.map(instr(_)).mkString
 | 
|  |     28 | 
 | 
|  |     29 | 
 | 
|  |     30 | def compile_str(prog: String) : String = {
 | 
|  |     31 |   "#include <string.h>\n" ++
 | 
|  |     32 |   "#include <stdio.h>\n" ++
 | 
|  |     33 |   "char field[30000];\n" ++
 | 
|  |     34 |   "char *ptr = &field[15000];" ++
 | 
|  |     35 |   "int main()\n{\n" ++
 | 
|  |     36 |   "memset(field, '\\0', 30000);\n" ++
 | 
|  |     37 |   instrs(prog) ++
 | 
|  |     38 |   "\n return 0;\n}"
 | 
|  |     39 | }
 | 
|  |     40 | 
 | 
|  |     41 | def compile(name: String, prog: String) = {
 | 
|  |     42 |   val fw = new java.io.FileWriter(name + ".c") 
 | 
|  |     43 |   val is = compile_str(prog)
 | 
|  |     44 |   //println(is)
 | 
|  |     45 |   fw.write(is) 
 | 
|  |     46 |   fw.close()
 | 
|  |     47 | }
 | 
|  |     48 | 
 | 
| 636 |     49 | // running the c-compiler over the transpiled
 | 
|  |     50 | // BF program and running the result
 | 
| 633 |     51 | import sys.process._
 | 
|  |     52 | 
 | 
|  |     53 | def compile_run(prog: String) = {
 | 
|  |     54 |   compile("tmp", prog)
 | 
|  |     55 |   "gcc -O0 -o tmp tmp.c".!
 | 
|  |     56 |   "./tmp".!
 | 
|  |     57 |   ()
 | 
|  |     58 | }
 | 
|  |     59 | 
 | 
|  |     60 | def time_needed[T](n: Int, code: => T) = {
 | 
|  |     61 |   val start = System.nanoTime()
 | 
|  |     62 |   for (i <- 0 until n) code
 | 
|  |     63 |   val end = System.nanoTime()
 | 
|  |     64 |   (end - start)/(n * 1.0e9)
 | 
|  |     65 | }
 | 
|  |     66 | 
 | 
| 637 |     67 | // the mandelbrot program
 | 
| 636 |     68 | val b0 = load_bff("mandelbrot.bf")
 | 
| 633 |     69 | 
 | 
| 636 |     70 | println(s"${time_needed(1, compile_run(b0))} secs")
 | 
| 633 |     71 | 
 | 
|  |     72 | 
 | 
|  |     73 | 
 | 
|  |     74 | // a benchmark program (counts down from 'Z' to 'A')
 | 
|  |     75 | val b1 = """>++[<+++++++++++++>-]<[[>+>+<<-]>[<+>-]++++++++
 | 
|  |     76 |             [>++++++++<-]>.[-]<<>++++++++++[>++++++++++[>++
 | 
|  |     77 |             ++++++++[>++++++++++[>++++++++++[>++++++++++[>+
 | 
|  |     78 |             +++++++++[-]<-]<-]<-]<-]<-]<-]<-]++++++++++."""
 | 
|  |     79 | 
 | 
|  |     80 | println(s"${time_needed(1, compile_run(b1))} secs")
 |