// A Transpiler for the Brainf*** language to C
//===============================================
//
// Call with
//
// amm bfc0.sc <<bf_program.bf>>
//
import scala.util._
// loding a bf-file
def load_bff(name: String) : String =
Try(Source.fromFile(name)("ISO-8859-1").mkString).getOrElse("")
// simple instructions
def instr(c: Char) : String = c match {
case '>' => "ptr++;"
case '<' => "ptr--;"
case '+' => "(*ptr)++;"
case '-' => "(*ptr)--;"
case '.' => "putchar(*ptr);"
case ',' => "*ptr = getchar();\n"
case '[' => "while(*ptr){"
case ']' => "}"
case _ => ""
}
def instrs(prog: String) : String =
prog.toList.map(instr(_)).mkString
def compile_str(prog: String) : String = {
"#include <string.h>\n" ++
"#include <stdio.h>\n" ++
"char field[30000];\n" ++
"char *ptr = &field[15000];" ++
"int main()\n{\n" ++
"memset(field, '\\0', 30000);\n" ++
instrs(prog) ++
"\n return 0;\n}"
}
def compile(name: String, prog: String) = {
val fw = new java.io.FileWriter(name + ".c")
val is = compile_str(prog)
//println(is)
fw.write(is)
fw.close()
}
// running the c-compiler over the transpiled
// BF program and running the result
import sys.process._
def compile_run(prog: String) = {
compile("tmp", prog)
"gcc -O3 -o tmp tmp.c".!
"./tmp".!
()
}
def time_needed[T](n: Int, code: => T) = {
val start = System.nanoTime()
for (i <- 0 until n) code
val end = System.nanoTime()
(end - start)/(n * 1.0e9)
}
// Running Testcases
//===================
@doc(" the argument should be a BF program ")
@main
def main(fname: String) = {
val bf_str = os.read(os.pwd / fname)
println(s"${time_needed(1, run(bf_str))} secs")
}