| author | Christian Urban <christian.urban@kcl.ac.uk> | 
| Sat, 09 Oct 2021 12:29:15 +0100 | |
| changeset 843 | f3204dd2b6dc | 
| parent 825 | fb9f63a22114 | 
| child 990 | 8cb2e171d952 | 
| permissions | -rw-r--r-- | 
| 
738
 
03f46065ef04
updated
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents: 
736 
diff
changeset
 | 
1  | 
// A Transpiler for the Brainf*** language to C  | 
| 
 
03f46065ef04
updated
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents: 
736 
diff
changeset
 | 
2  | 
//===============================================  | 
| 
 
03f46065ef04
updated
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents: 
736 
diff
changeset
 | 
3  | 
//  | 
| 
 
03f46065ef04
updated
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents: 
736 
diff
changeset
 | 
4  | 
// Call with  | 
| 
 
03f46065ef04
updated
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents: 
736 
diff
changeset
 | 
5  | 
//  | 
| 
 
03f46065ef04
updated
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents: 
736 
diff
changeset
 | 
6  | 
// amm bfc0.sc <<bf_program.bf>>  | 
| 
 
03f46065ef04
updated
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents: 
736 
diff
changeset
 | 
7  | 
//  | 
| 740 | 8  | 
//  | 
9  | 
// Note: An interesting exercise is to call  | 
|
| 742 | 10  | 
// gcc with -O3 instead of -O0 (see invocation  | 
11  | 
// below).  | 
|
12  | 
||
| 633 | 13  | 
|
14  | 
// simple instructions  | 
|
15  | 
def instr(c: Char) : String = c match {
 | 
|
16  | 
case '>' => "ptr++;"  | 
|
17  | 
case '<' => "ptr--;"  | 
|
18  | 
case '+' => "(*ptr)++;"  | 
|
19  | 
case '-' => "(*ptr)--;"  | 
|
20  | 
case '.' => "putchar(*ptr);"  | 
|
| 740 | 21  | 
case ',' => "*ptr = getchar();"  | 
| 633 | 22  | 
  case '['  => "while(*ptr){"
 | 
23  | 
case ']' => "}"  | 
|
24  | 
case _ => ""  | 
|
25  | 
}  | 
|
26  | 
||
27  | 
def instrs(prog: String) : String =  | 
|
28  | 
prog.toList.map(instr(_)).mkString  | 
|
29  | 
||
| 742 | 30  | 
// adding boilerplate  | 
| 740 | 31  | 
def compile(prog: String) : String =  | 
32  | 
s"""#include <string.h>  | 
|
33  | 
#include <stdio.h>  | 
|
| 746 | 34  | 
int field[30000];  | 
35  | 
int *ptr = &field[15000];  | 
|
| 740 | 36  | 
      int main() { 
 | 
37  | 
memset(field, '\\0', 30000);  | 
|
38  | 
      ${instrs(prog)} 
 | 
|
39  | 
return 0;}"""  | 
|
| 633 | 40  | 
|
| 742 | 41  | 
|
42  | 
def compile_to_file(name: String, prog: String) =  | 
|
| 740 | 43  | 
os.write.over(os.pwd / name, compile(prog))  | 
44  | 
||
45  | 
||
46  | 
// running the c-compiler over the transpiled  | 
|
47  | 
// BF program and running the resulting binary  | 
|
48  | 
||
| 742 | 49  | 
def compile_and_run(prog: String) = {
 | 
| 740 | 50  | 
val tn = "tmp"  | 
| 742 | 51  | 
  compile_to_file(s"${tn}.c", prog)
 | 
| 740 | 52  | 
  os.proc("gcc", "-O0", "-o", tn, s"${tn}.c").call() // call gcc
 | 
53  | 
  os.proc("./tmp").call(stdout = os.Inherit)         // run binary
 | 
|
| 633 | 54  | 
}  | 
55  | 
||
| 740 | 56  | 
// Running Testcases  | 
57  | 
//===================  | 
|
| 633 | 58  | 
|
59  | 
def time_needed[T](n: Int, code: => T) = {
 | 
|
60  | 
val start = System.nanoTime()  | 
|
61  | 
for (i <- 0 until n) code  | 
|
62  | 
val end = System.nanoTime()  | 
|
63  | 
(end - start)/(n * 1.0e9)  | 
|
64  | 
}  | 
|
65  | 
||
| 825 | 66  | 
//@doc(" the argument should be a BF program ")
 | 
| 
738
 
03f46065ef04
updated
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents: 
736 
diff
changeset
 | 
67  | 
@main  | 
| 
 
03f46065ef04
updated
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents: 
736 
diff
changeset
 | 
68  | 
def main(fname: String) = {
 | 
| 
 
03f46065ef04
updated
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents: 
736 
diff
changeset
 | 
69  | 
val bf_str = os.read(os.pwd / fname)  | 
| 742 | 70  | 
  println(s"${time_needed(1, compile_and_run(bf_str))} secs")
 | 
| 
738
 
03f46065ef04
updated
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents: 
736 
diff
changeset
 | 
71  | 
}  | 
| 633 | 72  | 
|
73  | 
||
74  |