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