progs/bfc1.scala
changeset 736 d3e477fe6c66
parent 735 fc2e3609d5e5
child 737 14a348d050b3
equal deleted inserted replaced
735:fc2e3609d5e5 736:d3e477fe6c66
     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 // "splicing" a BF program counting occurrences
       
    13 def splice(cs: List[Char], acc: List[(Char, Int)]) : List[(Char, Int)] = (cs, acc) match {
       
    14   case (Nil, acc) => acc
       
    15   case (c :: cs, Nil) => splice(cs, List((c, 1)))
       
    16   case (c :: cs, (d, n) :: acc) => 
       
    17     if (c == d) splice(cs, (c, n + 1) :: acc)
       
    18     else splice(cs, (c, 1) :: (d, n) :: acc)
       
    19 }
       
    20 
       
    21 def spl(s: String) = splice(s.toList, Nil).reverse
       
    22 
       
    23 // generating "compound" c-instructions 
       
    24 def instr2(c: Char, n: Int) : String = c match {
       
    25   case '>' => "ptr += " + n.toString + ";"
       
    26   case '<' => "ptr -= " + n.toString + ";"
       
    27   case '+' => "(*ptr) += " + n.toString + ";"
       
    28   case '-' => "(*ptr) -= " + n.toString + ";"
       
    29   case '.' => "putchar(*ptr);" * n
       
    30   case ',' => "*ptr = getchar();\n" * n
       
    31   case '['  => "while(*ptr){" * n
       
    32   case ']'  => "}" * n
       
    33   case _ => ""
       
    34 }
       
    35 
       
    36 
       
    37 def instrs2(prog: String) : String =
       
    38   spl(prog).map{ case (c, n) => instr2(c, n) }.mkString
       
    39 
       
    40 
       
    41 def compile_str(prog: String) : String = {
       
    42   "#include <string.h>\n" ++
       
    43   "#include <stdio.h>\n" ++
       
    44   "char field[30000];\n" ++
       
    45   "char *ptr = &field[15000];" ++
       
    46   "int main()\n{\n" ++
       
    47   "memset(field, '\\0', 30000);\n" ++
       
    48   instrs2(prog) ++
       
    49   "\n return 0;\n}"
       
    50 }
       
    51 
       
    52 def compile(name: String, prog: String) = {
       
    53   val fw = new java.io.FileWriter(name + ".c") 
       
    54   val is = compile_str(prog)
       
    55   //println(is)
       
    56   fw.write(is) 
       
    57   fw.close()
       
    58 }
       
    59 
       
    60 import sys.process._
       
    61 
       
    62 def compile_run(prog: String) = {
       
    63   compile("tmp", prog)
       
    64   "gcc -O0 -o tmp tmp.c".!
       
    65   "./tmp".!
       
    66   ()
       
    67 }
       
    68 
       
    69 def time_needed[T](n: Int, code: => T) = {
       
    70   val start = System.nanoTime()
       
    71   for (i <- 0 until n) code
       
    72   val end = System.nanoTime()
       
    73   (end - start) / (n * 1.0e9)
       
    74 }
       
    75 
       
    76 // the mandelbrot program
       
    77 val b0 = load_bff("mandelbrot.bf")
       
    78 
       
    79 println(s"${time_needed(1, compile_run(b0))} secs")
       
    80 
       
    81 
       
    82 
       
    83 // a benchmark program (counts down from 'Z' to 'A')
       
    84 val b1 = """>++[<+++++++++++++>-]<[[>+>+<<-]>[<+>-]++++++++
       
    85             [>++++++++<-]>.[-]<<>++++++++++[>++++++++++[>++
       
    86             ++++++++[>++++++++++[>++++++++++[>++++++++++[>+
       
    87             +++++++++[-]<-]<-]<-]<-]<-]<-]<-]++++++++++."""
       
    88 
       
    89 println(s"${time_needed(1, compile_run(b1))} secs")
       
    90 
       
    91