User:Rdebath

Current Languages to go back to.

 * 1) RCEM
 * 2) DownRight
 * 3) Blind
 * 4) SNUSP
 * 5) Easy
 * 6) Extended_Brainfuck
 * 7) Grin
 * 8) Hcbf
 * 9) HighFive
 * 10) Malbrain
 * 11) pbrain
 * 12) Headache

My first BF converter
BEGIN { tx["<"] = "l"; tx[">"] = "r"; tx["+"] = "u"; tx["-"] = "d"; tx["."] = "p"; tx[","] = "i"; tx["["] = "w"; tx["]"] = "e"; print "#include" print "#define",tx[">"],"m+=1;" print "#define",tx["<"],"m-=1;" print "#define",tx["+"],"++*m;" print "#define",tx["-"],"--*m;" print "#define",tx["["],"while(*m){" print "#define",tx["]"],"}" print "#define",tx["."],"write(1,m,1);" print "#define",tx[","],"read(0,m,1);" print "#define a char mem[30000];int main{char*m=mem;" print "#define z return 0;}" l = "a" } {    for(i=1; i<=length($0); i++) { c = substr($0,i,1); v = tx[c]; l = l " " v; sub("^ ", "", l); if (length(l) > 76) { print l            l="" }    } } END{ print l,"z"; }
 * 1) !/usr/bin/mawk -f

I think it retains the essential flavour of brainfuck in the output C code.

a u u u u u u u u u u w r u u u u u u u r u u u u u u u u u u r u u u r u l l l l d e r u u p r u p u u u u u u u p p u u u p r u u p l l u u u u u u u u u u u u u u u p r p u u u p d d d d d d p d d d d d d d d p r u p r p z
 * 1) include
 * 2) define r m+=1;
 * 3) define l m-=1;
 * 4) define u ++*m;
 * 5) define d --*m;
 * 6) define w while(*m){
 * 7) define e }
 * 8) define p write(1,m,1);
 * 9) define i read(0,m,1);
 * 10) define a char mem[30000];int main{char*m=mem;
 * 11) define z return 0;}

Current Version of the awk based converter
This is the current version, it has a few more features and 'optimises' better than 98% of BF interpreters and compilers but it still makes a result that' just as ugly.

BF Style optimisations are:


 * Run length encoding
 * Removal of cancelling sequences eg: >>><<<
 * Replace '[-]' by a set zero
 * Combine set zero with following additions
 * Replace a Move And ADD loops (a MAAD loop) with additions and multiplications
 * Replace a set in a MAAD loop by a specific conditional set (allowing the rest of the loop to be a MAAD).

Notes: If you turn on the instruction counting it interferes with optimisation. This does not do any higher level optimisation, such as constant folding, loop invariant motion, strength reduction etc etc. It only does these minimal 'peephole' style optimisations.

# # # # # true, /^; exec awk -f "$0" -- "$@" ; exit #/ {} BEGIN { if (ARGC == 1 || (ARGC==2 && ARGV[1]== "-h")) { print "Usage: bf2c [options] files..." print " Options:" print " -c         Don't run the program, send it to stdout." print " -oFILE     Don't run the program, write it to FILE." print " -O -O3     Pass this option to 'cc'." print " -O0        Disable peephole optimisations." print " -d         Dump final memory and when a # is seen." print " -i         Enable counting of BF instructions." print " -#         Turn on both -d and -i" print " -M65536    Specify amount of memory to allocate." print " -Tunsigned Type for the tape cells." print " -Ctcc      Use the specified C compiler rather than 'cc'." print "" print "Note: the -i and -# options interfere with optimisation." print "     For the -i to count correctly -T must not be signed." aborting=1; exit }    memory = 65536; memoff = 1000; outfile = ""; CC = "cc"; noopt = 0 ll = 78; for(i=1; i<ARGC; i++) { arg = ARGV[i]; if (substr(arg,1,1) == "+") arg = "-" substr(arg,2); if (arg == "-c") { ARGV[i] = ""; norun=1 } if (arg == "-#") { ARGV[i] = ""; debug=1; icount=1; } if (arg == "-d") { ARGV[i] = ""; debug=1; } if (arg == "-i") { ARGV[i] = ""; icount=1 } if (arg == "-O0") { ARGV[i] = ""; noopt=1 } if (substr(arg,1,2) == "-M") { memory = substr(ARGV[i], 3) + memoff; ARGV[i] = "";} if (substr(arg,1,2) == "-T") { cell = substr(ARGV[i], 3); ARGV[i] = "";} if (substr(arg,1,2) == "-C") { CC = substr(ARGV[i], 3); ARGV[i] = "";} if (substr(arg,1,2) == "-O") { optflag = " -O" substr(ARGV[i], 3); ARGV[i] = "";} if (substr(arg,1,2) == "-o") { norun=1; outfile = substr(ARGV[i], 3); ARGV[i] = "";} }    header; if (icount) tc = "t "; else tc = ""; for (i=1; i<=8; i++) tx[substr("<>+-.,[]", i, 1)] = tc substr("lrudoibE", i, 1) " "; if (debug) tx["#"] = "# "; } {    s = "" for(i=1; i<=length($0); i++) { c = substr($0,i,1); s = s tx[c]; }    str = str s;     while (index(str, "E")) { if (!noopt) { gsub("b d E", "z", str); if (icount) { gsub("t b t d t E", "t T(*m*2)z", str); }        }         e = index(str, "E"); tstr = substr(str, e+2); str = substr(str, 1, e+1); optim; e = index(str, "E"); if (e) { lstr = lstr substr(str, 1, e+1); str = substr(str, e+2); print_line; }        str = str tstr; } } END { if (aborting) exit; optim; lstr = lstr str; str = ""; if (debug) lstr = lstr "# "; ll = 1; print_line; if (icount && !debug) { print "fprintf(stderr, \"\\nCommands executed: %\"PRIuCount\"\\n\", icount);" > of    } print "return 0;}" > of    if (!norun) { close(of); rv = system(CC optflag " -o " ef " " of); system("rm " of); if (rv == 0) { rv = system(ef " +deleteme+"); if (rv != 0) printf "Command returned exit status: %d\n", rv > "/dev/stderr" }        if (rv != 0) system("rm -f " ef); } else if (outfile != "") close(of); } function header { if (!norun) { ef="/tmp/ap" rand; of = ef ".c"    } else if (outfile != "") { of = outfile; } else of = "/dev/stdout"; if (cell != "") tcell=cell; else tcell="unsigned char"; if (!norun) print "#include " > of    if (cell != "" || icount || debug) print "#include " > of     if (cell == "" || !norun) print "#include " > of    if (tcell ~ /_/) print "#include " > of    else if (icount) { print "#ifdef __STDC__" > of        print "#include " > of         print "#if _POSIX_VERSION >= 199506L || defined(LLONG_MAX)" > of         print "#include " > of         print "#endif" > of         print "#endif" > of     } if (icount) { print "#ifdef UINTMAX_MAX" > of        print "uintmax_t icount = 0;" > of         print "#define PRIuCount PRIuMAX" > of         print "#else" > of         print "unsigned long icount = 0;" > of         print "#define PRIuCount \"lu\"" > of         print "#endif" > of         print "#define t icount++;" > of         print "#define T(x) icount += (x);" > of     } print "#define r m+=1;" > of    print "#define l m-=1;" > of     print "#define u *m+=1;"    > of     print "#define d *m-=1;"    > of     if (cell != "" ) { print "#define o putch(*m);" > of        print "#define i *m = getch(*m);" > of     } else { print "#define o write(1,m,1);" > of        print "#define i read(0,m,1);"  > of     } if (noopt) { print "#define b while(*m){"   > of         print "#define e }"             > of     } else { print "#define b while(*m)"    > of         print "#define z *m=0;" > of         print "#define S(x) *m= x;"     > of         print "#define R(x) m += x;"    > of         print "#define L(x) R(-x)"      > of         print "#define U(x) *m += x;"   > of         print "#define D(x) U(-x)"      > of         print "#define Q(x,y) if(*m)m[x]=(y);"  > of         print "#define M(x,y) m[x]+=(*m)*(y);"  > of         print "#define A(x) m[x]+=(*m);"        > of     } print "#define C",tcell        > of     tcell="C" if (cell != "") { print "void putch(int ch) { putchar(ch); }" > of; print "int getch(int och) { " \ "int ch; " \ "if((ch=getchar) != EOF) return ch; else return och; " \ "}" > of; }    print tcell,"mem[" memory "];" \ "int main(int argc, char ** argv){" \ "register",tcell "*m=mem+" memoff ";"   > of     if (oflush || cell != "" ) print "setbuf(stdout,0);" > of; if (!norun) { printf "if (argc>1 && strcmp(argv[1], \"+deleteme+\") == 0)" > of; printf " unlink(argv[0]);\n" > of; } } function print_line { if (noopt) { gsub("E", "e", lstr); } else { gsub("[Bb] ", "b{", lstr); gsub("E", "}", lstr); gsub(" *} *", "}", lstr); }    for { if (length(lstr) < ll) return; s = substr(lstr, 1, 79); if ((i= index(s, "#")) != 0) { print substr(lstr, 1, i-1) > of            lstr = substr(lstr, i+1); debug_mem; } else if (match(s, ".* ")) { print substr(s, 1, RLENGTH-1) > of            lstr = substr(lstr, RLENGTH+1); } else if (match(s, ".*[ )}]")) {             print substr(s, 1, RLENGTH) > of             lstr = substr(lstr, RLENGTH+1);         } else {             print lstr > of             lstr = "";         }     } } function debug_mem {     if (icount) {         print "fprintf(stderr, \"\\nCommands executed: %\"PRIuCount\"\\n\", icount);" > of     }     print "{ unsigned ii, jj=0;" > of;     print "  for(ii=" memoff "; ii of;     print "    if(mem[ii]) jj = ii+1;" > of;     print "  fprintf(stderr, \"Ptr: %2d: mem:\", m-mem-" memoff ");" > of;     print "  for(ii=" memoff "; ii of;     print "    fprintf(stderr, \" %3.0f\", (double)mem[ii]);" > of;     print "  fprintf(stderr, \"\\n\");" > of;     print "  if (mem-m-" memoff "<100) {" > of;     print "    fprintf(stderr, \"         ptr:\");" > of;     print "    for(ii=" memoff "; mem+ii<=m; ii++)" > of; print "     fprintf(stderr, \"   %s\", mem+ii==m?\"^\":\" \");" > of; print "   fprintf(stderr, \"\\n\");" > of; print " }" > of; print "}" > of; } function optim {    if (noopt) return; if (icount) { while (match(str, "t (t|u|d|l|r|i|o| )*")) { v = substr(str, RSTART, RLENGTH) v2 = v;            gsub("[^t]", "", v2); v2 = "T(" length(v2) ")" gsub("[t ]", "", v); gsub(".", "& ", v); str = substr(str, 1, RSTART-1) v v2 substr(str, RSTART+RLENGTH) }        gsub("T(1)", "t ", str); }    while ( match(str, "u d ") || match(str, "d u ") ||             match(str, "l r ") || match(str, "r l ")) { str = substr(str, 1, RSTART-1) substr(str, RSTART+RLENGTH) }    while (match(str, "b (z|u|d|l|r| )* E")) { v = substr(str, RSTART, RLENGTH) for(i in a) delete a[i]; for(i in z) delete z[i]; off = 0; c = split(v, p); for(i=1; i<=c; i++) { if (p[i] == "r"){off++; continue; } if (p[i] == "l"){off--; continue; } if (p[i] == "u"){a[off] ++; continue; } if (p[i] == "d"){a[off] --; continue; } if (p[i] == "z"){z[off] = 1; a[off] = 0; } }        if (z[0]==1 || a[0] != -1 || off != 0) { str = substr(str, 1, RSTART-1) "B" substr(str, RSTART+1) continue }        nv = ""; for(i in a) if(i != 0) { if (z[i]) { nv = nv sprintf("Q(%d,%d)", i, a[i]); } else if (a[i] == 1) { nv = nv sprintf("A(%d)", i); } else { nv = nv sprintf("M(%d,%d)", i, a[i]); }        }         nv = nv "z" str = substr(str, 1, RSTART-1) nv substr(str, RSTART+RLENGTH) continue }    while (match(str, "z u (u )*")) { str = substr(str, 1, RSTART-1) "S(" RLENGTH/2-1 ")" substr(str, RSTART+RLENGTH) }    while (match(str, "u u (u )*")) { str = substr(str, 1, RSTART-1) "U(" RLENGTH/2 ")" substr(str, RSTART+RLENGTH) }    while (match(str, "d d (d )*")) { str = substr(str, 1, RSTART-1) "D(" RLENGTH/2 ")" substr(str, RSTART+RLENGTH) }    while (match(str, "r r (r )*")) { str = substr(str, 1, RSTART-1) "R(" RLENGTH/2 ")" substr(str, RSTART+RLENGTH) }    while (match(str, "l l (l )*")) { str = substr(str, 1, RSTART-1) "L(" RLENGTH/2 ")" substr(str, RSTART+RLENGTH) } }
 * 1) !/bin/sh -
 * 2) vim: set filetype=awk:
 * 1) BF to C converter, compiler and runner.
 * 1) This converts BF to peephole optimised C then compiles it with the system C
 * 2) complier and runs the resulting executable.
 * 1) This script works with most versions of awk including the one described in
 * 2) the book "The AWK Programming Language", by Al Aho, Brian Kernighan,
 * 3) and Peter Weinberger.
 * 1) The 'mawk' version is the quickest followed by "original-awk" with the big
 * 2) fat GNU version rolling up eventually.
 * 1) Use the shell to fix the lack of -Wexec on some awks.

Info
Basic rules are that everything is complied with best optimisation or recommended optimisation (eg GCC) except that any generated C code is complied with TCC (ie no optimisation). Timings normally include the time taken for any compile stage that must be run after presenting the brainfuck code. The host machine for these tests is an Intel I7 running Debian Linux.

The *-gcc items are an exception to the timing rule in that the generated C is compiled with GCC and full optimisation and the time for this compile is not included in the final times. The optimisation levels on the interpreter are also 'turned up to eleven'.

The first column is an id tag for the BF interpreter and it's settings. It has a light colour wash that signifies the technology of the program. Blue is a C generator, green is an assembler generator or JIT, yellow is a plain interpreter normally written in C or C++. Pink is the special GCC tests and 'white/grey' is unclassified.

The total is the time for all tests that actually completed.

The Score is a measure of the speed of the interpreter, it's used to order the table.

The bitwidth column is the result of a cell size detecting BF program, it can fail like any other test but does not normally provide a run time. As it also runs some basic functionality tests so a major failure of this test means the interpreter is not run for the others. The test is in two parts so buggy or slow interpreters may lose the second part.

The Endtest column shows which of the end of file conventions this interpreter follows.

The rest of the columns are tests; the three before the gap are used to compute the score.

The colour coding of the tests is: Yellow, The test failed to provide the correct output but did finish, the orange border means that the program segfaulted or provided another indication of a serious fault or rejection of the program. Red, the test failed to complete within the allocated time. The graduation from green to blue to purple represents the time the test took to run; green=fast, blue=okish, purple=glacial. A brown test was skipped because it will not run within the available time on an interpreter with that cell size (The heavily optimising interpreters can be exceptions to this and are shown in "hotpink").

The sections are firstly "the list", secondly a few trivial tests, Thirdly the special GCC section and lastly my 'other' interpreters and unusual (slow!) flag options.