Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon.

Pages: 1-4041-8081-

My first Brainfuck

Name: The Amazing Anus !Anus3nMVO2 2009-08-31 1:43

I was bored as fuck so I decided to implement a Brainfuck interpreter in C.

/* brainfuck.c ... version 0.9
 *
 * usage: brainfuck <file>
 *
 */

 
#include <stdio.h>

/* 64kb -1b each
 *
 * The Brainfuck spec says that memory should be 30000 bytes, but I prefer to
 * use a whole 64kb for both code and memory.
 *
 */
#define BRAINF_CODESIZE   65535
#define BRAINF_MEMSIZE   65535


FILE* fp;

unsigned char* code, *memory;
short unsigned int codeptr, memptr;


int main(int argc, char* argv[])
{
     if (argc != 2)
          exit(1);

     if ((fp = fopen(argv[1], "r")) == NULL)
          exit(1);

     code = malloc(BRAINF_CODESIZE);
     memory = malloc(BRAINF_MEMSIZE);

     memset(code, 0, BRAINF_CODESIZE);
     memset(memory, 0, BRAINF_MEMSIZE);

     codeptr = 0;
     memptr = 0;

     while (!feof(fp))
     {
          fread(code, BRAINF_CODESIZE -1, 1, fp);
     }


     /*** Interpreting begins ***/
     while (code[codeptr])
     {
          switch (code[codeptr])
          {
               case '>':
                    ++memptr;
                    ++codeptr;
                    break;

               case '<':
                    --memptr;
                    ++codeptr;
                    break;

               case '+':
                    ++memory[memptr];
                    ++codeptr;
                    break;

               case '-':
                    --memory[memptr];
                    ++codeptr;
                    break;

               case '.':
                    putchar(memory[memptr]);
                    ++codeptr;
                    break;

               case ',':
                    memory[memptr] = getchar();
                    ++codeptr;
                    break;

               /* :NOTE: Some kind of error handling should take
                * place if no ']' is found.
                */
               case '[':
                    if (!memory[memptr])
                    {
                         while ((code[codeptr] != ']') && (code[codeptr]))
                         {
                              ++codeptr;
                         }
                    }
                    else
                         ++codeptr;
                    break;


               /* :NOTE: Some kind of error handling should take
                * place if no '[' is found.
                */
               case ']':
                    if (memory[memptr])
                    {
                         while ((code[codeptr] != '[') && (codeptr))
                              --codeptr;
                    }
                    else
                         ++codeptr;
                    break;

               /* invalid instruction
                * For now we will just continue executing when this happens.
                * It should ignore characters 10, 13, & 32 anyways.
                */
               default:
                    ++codeptr;
                    break;
          }
     }

     free(code);
}

Name: Anonymous 2009-08-31 1:54

I was bored as fuck so I decided to read /prog/

Name: Anonymous 2009-08-31 2:01

fuck off and die, you dirty tripfag

Name: The Amazing Anus !Anus3nMVO2 2009-08-31 2:05

Please give me feedback if I did anything wrong (eg. that is poor style), or what you would have done that would have been more efficient or readable or whatever.

Name: Anonymous 2009-08-31 2:14

>>1
Your implementation of the loop is kind of pathetic. Instead, you should push the location of the last '[' onto a stack, so you can jump directly to it.

Tomorrow I'll see if I can find the one I wrote for an embedded MIPS emulator a few years ago, and show you how it's done.

Name: Anonymous 2009-08-31 2:15

Now write an ANSI C interpreter in brainfuck.

Name: The Amazing Anus !Anus3nMVO2 2009-08-31 2:18

>>5
Ok, thanks!

Name: Anonymous 2009-08-31 2:19

>>4
Your pointer semantics are counter-intuitive. I'm no fan of K&R, but that's another argument for another day.

Name: Anonymous 2009-08-31 2:33

fucking fail.  Loops are done so horridly I want to shoot myself.  Not only are they ugly as fuck but you can't nest them like in BF.
[ is while(memory[memptr]){
] is }

if you had something like this:
[[[ ]]]
if the first bracket failed you wouldn't just to the first ] you see, you would go to the matching one.

learn2jumpstack

Name: The Amazing Anus !Anus3nMVO2 2009-08-31 3:04

>>9
Ah yes, thanks for pointing that out.  I see I'll need to redesign this thing more than I thought.

Name: Anonymous 2009-08-31 3:48


; Common lisp

(defconstant +bf-memory+ 30000)              
(defparameter *memory* (make-array +bf-memory+      
                                   :initial-element 0     
                                   :element-type '(unsigned byte 8)))
(defun bf (str &optional (index 0)
           (position 0))
  (loop for c across (subseq str index)
     for index from index
     do    
     (case c                               
       (#\+ (incf (aref *memory* position)))
       (#\- (decf (aref *memory* position)))    
       (#\> (when (= (incf position) +bf-memory+)
              (setq position 0)))
       (#\< (if (zerop position)
                (setq position (1- +bf-memory+))
                (decf position)))                       
       (#\. (princ (code-char (aref *memory* position))))          
       (#\, (setf (aref *memory* position) (char-code (read-char))))
       (#\[ (unless (zerop (aref *memory* position))            
              (loop until (zerop (bf str (1+ index) position)))))
       (#\] (return (aref *memory* position))))))


Written just now. Use like (bf "++<>+>-"). Memory is circular.

Name: Anonymous 2009-08-31 6:32

If this was inspired by Xarn's latest blog post, why didn't you just look at the via-C compiler he posted for direction?

Name: Haxus the Brainfucker 2009-08-31 13:58

Haxus the Brainfucker

Name: xarnic dongs 2009-08-31 14:03

xarnic dongs

Name: Anonymous 2009-08-31 16:02

- Codesize and memsize should probably be 65536 instead of 65535. Remember that a size of N means that you can use elements 0 .. (N-1).
- You're relying on integer wraparound at 65536, which may or may not be correct depending on architecture. (Actually, you're relying on integer wraparound at 65535; see above.) You can use uint16_t instead if you need an unsigned integer that is always 16 bits.
- You're not checking the result of the two malloc calls. Shame on you.
- The code reading is wrong. It may read, say, 1024 bytes in the first iteration, stop on a (temporary) read error, notice that it's not yet at EOF, start again, and overwrite these 1024 bytes in the next fread call. Either stop in case of a read error and remove the loop, or handle it properly and keep tabs on the number of bytes successfully read. Also, the -1 here is wrong (the second argument to fread is a size, not a maximum value, so there's no need to subtract 1 from the real size).
- The '[' and ']' handlers are wrong, as has already been pointed out. >>5 is a good solution, but it requires you to keep a more complex state than you're currently using; if you want your implementation to be as simple and stateless as possible, you could use something like the following:


   case '[':
        if (!memory[memptr])
        {
             int bracketdepth = 1;
             while (backetdepth != 0)
             {
                 ++codeptr;
                 if (code[codeptr] == ']') bracketdepth--;
                 if (code[codeptr] == '[') bracketdepth++;
             }
             ++codeptr;
        }
        else
            ++codeptr;
        break;


It IS still a bit ugly though (although that may be more or less the point of anything brainfuck-related ;) )
- A minor stylistic issue: your code becomes somewhat clearer if you increment codeptr at the very end of the main loop, instead of at each branch. This has the downside of making [ and ] somewhat more complicated, so you have to decide for yourself whether it's actually an improvement.
- I'm pretty sure all characters other than +-<>.,[] are well-defined as being comments, so your default: clause is perfectly fine.
- Finally, you don't return a value (in particular, the value 0) at the end of main, something the compiler will probably have warned you about.

Name: Anonymous 2009-08-31 16:27

Remember that nice Brainfuck implementations really only need to guarantee 9999 cells, so unless you're writing it specifically to accommodate some non-conforming Brainfuck code, you don't even have to fuck around with mallocating.

Name: The Amazing Anus !Anus3nMVO2 2009-08-31 16:37

>>15
ooh very good!  I'll fix all of these things today.

Name: Anonymous 2009-08-31 16:58

You can use uint16_t instead if you need an unsigned integer that is always 16 bits.
This doesn't work for me.

brainfuck.c [Warning] data definition has no type or storage class

Apparently uint16_t isn't defined anywhere for my shitty setup.

Name: Anonymous 2009-08-31 17:33

>>18
You need to include <stdint.h> to use these types. For details, see http://linux.die.net/man/3/uint16_t .

Name: The Amazing Anus !Anus3nMVO2 2009-08-31 18:54

>>8
You're right.  I should have named "code" and "memory" with the letters "ptr" at the end, instead of naming the array index like that, shouldn't I?  Please explain anything else I did wrong with pointer semantics.

>>19
Thanks.

Just knocked off a few of those things.  I'll fix the whole nested brackets thing later.

Name: Anonymous 2009-08-31 19:04

>>20
>I should have named "code" and "memory" with the letters "ptr" at the end, instead of naming the array index like that, shouldn't I?

I (>>15) would suggest keeping "code" and "memory" as they are, and replacing "codeptr" and "memoryptr" by "codeindex" and "memoryindex", respectively. The ptr variables are wrong, because they aren't pointers, whereas "code" and "memory" describe their functions perfectly.

Name: Anonymous 2009-08-31 23:52

>>20
I mean the way you've declared your pointers.

unsigned char* bob, jill;

This is counter-intuitive, because it creates one unsigned char and one pointer to an unsigned char. jill is a regular unsigned char. What I mean is you should be defining your pointers as such:

unsigned char *bob, *jill;

Name: Anonymous 2009-09-01 7:36

>>22
Of course, the simple solution to this problem is to never declare multiple variables in a single declaration, which is often considered bad style anyway.

Name: Anonymous 2009-09-01 7:56

>>23
True, but after I switched to >>22's way of things, I stopped making that mistake altogether.

Name: Anonymous 2009-09-01 8:36

>>23
That still doesn't cover the usage semantics. You dereference by using unsigned char bobval = *bob; and then you have a straight-up variable that's copied from the data that bob points to.

Pointers are not proper types, they are variable modifiers. They are used on a per-variable basis, and as such, should always be hugging the variable they modify semantically.

Name: Anonymous 2009-09-01 8:45

>>25
What load of bollocks.
Pointers are not proper types,
In C, there are complete and incomplete types. Pointers belong to the former.
[pointers] should always be hugging the variable they modify semantically.
Pointers might 'hug' (what fucked up term is that? where did you find the relation between point and hug?), the address of something that is not an object. Consider the pointer to the incomplete type int[]: int (*foo)[];

Name: Anonymous 2009-09-01 9:46

>>26
Not bollocks. Pointers are not proper types. You cannot define a purely pointer variable. There must be some type to point to, if nothing else, void *. They might be complete or incomplete, it doesn't really matter. That's irrelevant to what I was saying.

There is no relationship between point and hug. There is a spacial relationship between the operator and the operand which constitutes hugging.

Name: Anonymous 2009-09-01 14:53

>>22
unsigned char* bob, jill;
Where the fuck are you looking?
>>1
unsigned char* code, *memory;

Name: The Amazing Anus !Anus3nMVO2 2009-09-02 19:37

Ok, finally got around to fixing it.

/* brainfuck.c ... version 0.91
 *
 * usage: brainfuck <file>
 *
 */

#include <stdio.h>
#include <stdint.h>

/* 64kb each
 *
 * The Brainfuck spec says that memory should be 30000 bytes, but I prefer to
 * use a whole 64kb for both code and memory.
 *
 */
#define BRAINF_CODESIZE   65536
#define BRAINF_MEMSIZE   65536


FILE* fp;

uint8_t* code, *memory;
uint16_t codeindex, memindex;
int16_t bracketdepth;


int main(int argc, char* argv[])
{
     if (argc != 2)
     {
          printf("usage: brainfuck <file>\n");
          exit(1);
     }

     if ((fp = fopen(argv[1], "r")) == NULL)
          exit(1);

     if ((code = malloc(BRAINF_CODESIZE)) == NULL)
          exit(1);

     if ((memory = malloc(BRAINF_MEMSIZE)) == NULL)
          exit(1);

     memset(code, 0, BRAINF_CODESIZE);
     memset(memory, 0, BRAINF_MEMSIZE);

     codeindex = 0;
     memindex = 0;

     fread(code, BRAINF_CODESIZE, 1, fp);

     if (ferror(fp))
          exit(1);

     bracketdepth = 0;


     /*** Interpreting begins.  Ends on NULL in codebyte. ***/
     while (code[codeindex])
     {
          switch (code[codeindex])
          {
               case '>':
                    ++memindex;
                    ++codeindex;
                    break;

               case '<':
                    --memindex;
                    ++codeindex;
                    break;

               case '+':
                    ++memory[memindex];
                    ++codeindex;
                    break;

               case '-':
                    --memory[memindex];
                    ++codeindex;
                    break;

               case '.':
                    putchar(memory[memindex]);
                    ++codeindex;
                    break;

               case ',':
                    memory[memindex] = getchar();
                    ++codeindex;
                    break;


               case '[':
                    if (!memory[memindex])
                    {
                         ++bracketdepth;
                         while (bracketdepth)
                         {
                              if (!code[++codeindex])  /* Exit if NULL */
                                   exit(1);

                              if (code[codeindex] == '[')
                                   ++bracketdepth;

                              if (code[codeindex] == ']')
                                   --bracketdepth;
                         }
                    }
                    else
                         ++codeindex;
                    break;


               case ']':
                    if (memory[memindex])
                    {
                         --bracketdepth;
                         while (bracketdepth)
                         {
                              if (codeindex-- == 0)  /* Exit if need to go */
                                   exit(1);          /* past first codebyte */

                              if (code[codeindex] == '[')
                                   ++bracketdepth;

                              if (code[codeindex] == ']')
                                   --bracketdepth;
                         }
                    }
                    else
                         ++codeindex;
                    break;


               /* non-instruction character */
               default:
                    ++codeindex;
                    break;
          }
     }

     free(code);

     return 0;
}


Again, tell me if I did anything wrong (eg. that is poor style), or what I could have done better, like more efficiently or would be more readable.


And here's a little program I found that will print out the Fibonacci numbers:

>++++++++++>+>+[
    [+++++[>++++++++<-]>.<++++++[>--------<-]+<<<]>.>>[
        [-]<[>+<-]>>[<<+>+>-]<[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-
            [>+<-[>+<-[>+<-[>[-]>+>+<<<-[>+<-]]]]]]]]]]]+>>>
    ]<<<
]


That code doesn't end itself so you'll have to terminate the process yourself if you run it.

Name: Anonymous 2009-09-02 19:41

>>11
That's a pretty clean implementation. Good Job!

Name: Anonymous 2009-09-02 22:40

>>28
You are a dense person.

Name: Anonymous 2009-09-02 23:13

>>31
i am actually quite sparse

Name: Anonymous 2009-09-02 23:52

>>28
unsigned char* is a problem semantically. I used an example to illustrate why this is a problem. Since you had difficulty understanding this, I must conclude that IHBT.

>>29
Global variables are considered poor form in many cases, just a note. It's fine for this particular program for a number of reasons, but that may not always be the case.

You could also abstract the logic into separate function(s) so as to implement some OOP PRINCIPLES, though that's largely superfluous and stupid in this case.

Having different exit codes to indicate the exit point is generally a good idea.

Another idea if you're interested would be checking the validity of the Brainfuck program first and issue warnings of some sort if it lacks validity. That's a bit harder than simply executing the program, but as far as lexical processing, it's hard to get any easier than that.

Name: Anonymous 2009-09-03 3:07

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char **argv)
{
    if (!(argc == 2 || argc == 3))
    {
    fprintf(stderr, "Usage: ./brainfuck source [memory]\n");
    exit(1);
    }

    FILE *inFP;

    if ((inFP = fopen(argv[1], "r")) == NULL)
    {
    fprintf(stderr, "Cannot open source file\n");
    exit(1);
    }

    char *sigma = "+-<>.,[]";
    int lb = 0, rb = 0, count = 0, i;
    char temp;

    while ((temp = fgetc(inFP)) != EOF)
    {
    for (i = 0; i < strlen(sigma); i++)
        if (sigma[i] == temp)
        count++;
    if (temp == '[')
        lb++;
    if (temp == ']')
    {
        rb++;
        if (lb - rb < 0)
        {
        fprintf(stderr, "Syntax error: bracket underflow\n");
        exit(1);
        }
    }
    }
    if (lb - rb > 0)
    {
    fprintf(stderr, "Syntax error: bracket overflow\n");
    exit(1);
    }

    rewind(inFP);

    char *source = (char *)malloc(sizeof(char) * count);
    int pos = 0;
    while ((temp = fgetc(inFP)) != EOF)
    for (i = 0; i < strlen(sigma); i++)
        if (sigma[i] == temp)
        source[pos++] = temp;

    int msize = 30000;
    if (argc == 3)
    msize = atoi(argv[2]);
    char *memory = (char *)malloc(sizeof(int) * msize);
    for (i = 0; i < msize; i++)
    memory[i] = 0;
    char *mptr = memory;
    char *sptr = source;
    char **stack = (char **)malloc(sizeof(char *) * lb);
    int stack_size = 0;
    while (sptr < source + count)
    {
    temp = *sptr;
    if (temp == '+') (*mptr)++;
    if (temp == '-') (*mptr)--;
    if (temp == '>') mptr++;
    if (temp == '<') mptr--;
    if (temp == ',') *mptr = fgetc(stdin);
    if (temp == '.') fputc(*mptr, stdout);
    if (temp == '[')
    {
        if (*mptr > 0)
        stack[stack_size++] = sptr;
        else
        while (*sptr != ']')
            sptr++;
    }
    if (temp == ']')
    {
        if (*mptr > 0)
        sptr = stack[stack_size-1];
        else
        --stack_size;
    }
    sptr++;
    }
   
    free(stack);
    free(memory);
    free(source);
}

Name: The Amazing Anus !Anus3nMVO2 2009-09-03 3:32

>>34
Congrats anon, your code is faster than both mine and some random interpreter I found online after coding mine.

$ time bf bench.bf
real    0.709 secs

$ time qdbf bench.bf
real    0.220 secs

$time bfanon bench.bf
real    0.190 secs


bf is my own interpreter.  qdbf is some shit I found online.  bfanon is what I called yours >>34.

Name: The Amazing Anus !Anus3nMVO2 2009-09-03 4:02

>>35
So as you can see, my interpreter sucks ass.

HOWEVER, when purely performing +-<> operations, my bf and the qdbf can crank out about 60,000 instructions in ~0.03 seconds.  Yours (bfanon) takes 0.15 seconds to do the exact same thing.

That makes >>34-chan's interpreter 5 times slower at executing instructions than the other 2.  Which is funny because mine takes 0.709 seconds to do the little benchmark thingy I wrote, whereas anon's does it fastest with qdbf close behind.  I guess this just means that my bracket code really sucks.

Name: Anonymous 2009-09-03 6:44

>>29
All your global variables are in fact local to the main function. This is pretty pedantic in this specific case, since main is the only function, but it's a bad habit to develop - avoid global variables unless you really, really can't.

The bracketdepth variable doesn't even need to be declared in the whole main function - you only need it in the [ and ] branches, without saving its state between two executions of [ or ]. In general, try to have a variable declared in the smallest possible scope; that way, I don't have to read the code in detail to find out whether the variable is used outside the relevant blocks. This greatly enhances readability and maintainability.

Oh, and you forgot to free(memory) at the end.


>>36
So as you can see, my interpreter sucks ass.
It's slowest, but that doesn't mean it sucks ass. For instance, it's also the simplest and easiest to read interpreter. Running speed is not the main goal of an interpreter, after all. If you want raw speed, write a compiler instead.

Name: Anonymous 2009-09-03 9:05

Let's see some benchmarks.

#include <stdio.h>
#include <stdlib.h>
#define CODESIZE 50000
int main(int argc, char** argv) {
    FILE *f = fopen(*++argv, "r");
    char c, d, code[CODESIZE];
    int syms[256], *j, count = 0, pos = 0, l;
    for(j = syms+256; j > syms; *--j = 0);
    syms['>'] = 1;
    syms['<'] = 1;
    syms['+'] = 1;
    syms['-'] = 1;
    syms['.'] = 1;
    syms[','] = 1;
    syms['['] = 1;
    syms[']'] = 1;
    for(;;) {
        while(count < pos) {
            for(;;) {
                c = fgetc(f);
                if(c == EOF) exit(1); /* Unexpected EOF */
                if(syms[c]) break;
            }
            *(code+count++) = c;
        }
        if(count > pos) c = *(code+pos++);
        else {
            for(;;) {
                c = fgetc(f);
                if(c == EOF) exit(0); /* End of program */
                if(syms[c]) break;
            }
            *(code+count++) = c;
            ++pos;
        }
        switch(c) {
            case '+': ++*j; break;
            case '-': --*j; break;
            case '.': fputc(*j, stdout); break;
            case '<': --j; break;
            case '>': ++j; break;
            case ',': *j = fgetc(stdin); break;
            case '[':
                if(!*j) {
                    l = 1;
                    for(;;) {
                        if(count > pos) d = *(code+pos++);
                        else {
                            for(;;) {
                                d = fgetc(f);
                                if(d == EOF) exit(1); /* Unexpected EOF */
                                if(syms[d]) break;
                            }
                            *(code+count++) = d;
                            ++pos;
                        }
                        if(d == '[') ++l;
                        else if(d == ']') {
                            if(--l < 0) exit(2); /* Unmatched open bracket */
                            else if(l == 0) break;
                        }
                    }
                }
                break;
            case ']':
                if(*j) {
                    l = 1;
                    --pos;
                    for(;;) {
                        if(pos <= 0) exit(3); /* Unmatched close bracket */
                        d = *(code+--pos);
                        if(d == ']') ++l;
                        else if(d == '[') {
                            if(--l < 0) exit(3); /* Unmatched close bracket */
                            else if(l == 0) break;
                        }
                    }
                }
                break;
            default: break;
        }
    }
}

Name: Anonymous 2009-09-03 9:11

>>38
What's this? Is this qdbf, or your attempt to make a fast implementation?

Name: Anonymous 2009-09-03 9:26

>>39
Neither. It was just a learning exercise because I wasn't familiar with the semantics of brainfuck before now.

Name: Anonymous 2009-09-03 12:21

>>36

Fine.  Go improve mine by improving load time optimization:  put in an array of numbers to tell you how many times each symbol appears in a row.  Like +++>>----< would in memory be:

source: +>-<
number: 3241

Then just += number[i] instead of repeated ++



By the way, anon < http://code.google.com/p/awib/source/browse/builds/awib-1.0rc6-BETA.b

Name: Anonymous 2009-09-03 12:34

>>41
If you're going for load time optimization, you can speed up the loops even more if, instead of using a stack, determine during load time which address to jump to for each [ and ] instruction.

Name: The Amazing Anus !Anus3nMVO2 2009-09-03 14:44

All times are averages after several runs.

$ time bf bench.bf
real    0.649 secs

$ time qdbf bench.bf
real    0.220 secs

$ time bfanon34 bench.bf
real    0.186 secs


Ok, it seems that I can't do anything to get >>38-chan's interpreter to accept my bench.bf program.  It also hangs forever if I try to run the quine on it... same with the program that prints the Fibonacci numbers.

The only thing that actually works is "Hello, World!"  I get corrupted stack and segmentation fault when I try to run the Fibonacci program on it.  I'll see if I can find out what its problem is.

Name: Anusymous 2009-09-03 15:30

>>43
You're an anus!

Name: The Amazing Anus !Anus3nMVO2 2009-09-03 15:35

>>44
I big anus that can talk and feel.

Name: Anonymous 2009-09-03 15:54

>>45
No question mark = imposter.

Name: Anonymous 2009-09-03 16:32

>>45
* I big anus that can talk, and feel?

Name: !Anusribs4k 2009-09-03 16:52

>>47
TYPO FUCK SAKE!!!!

Name: Anonymous 2009-09-03 20:26

>>48
Typographical errors

Here are some typographical errors, spotted by various readers. Page numbers refer to the online versions (which differ from the printed version).
• Page 128, second to last paragraph of section 3.7, first sentence. "addis" should be "is a".
• Page 134, the code for i'. The "n" under the big brace symbol should say "n pairs".
• Page 135. Equation 3.36 should have "NConstr", not "Constr".
• Page 230, second paragraph. "There one final gloss..." should be "There is one final gloss...".
• Page 278, the definition of nfib. Replace "n==0" by "n<=1".

Name: Anonymous 2009-09-03 20:52

>>1
I can't wait until Janefuck comes out.

Name: Anonymous 2009-09-04 1:16

>>43
I didn't test it, just got it to compile (actually it compiled straight away) and checked the Hello, World program on Wikipedia. That being said it runs your fibs program fine, how are you compiling/running? If you post the line number of the segfault I'll have a look.

Name: Anonymous 2009-09-04 1:47

>>51
I compiled it with gcc -o bfanon38 bfanon38.c

Ok, now I am able to successfully run the Fibonacci thing...  But bench.bf still causes yours to hang.  I could use a better benchmarking program, but it works fine on the other 3 so I'm not sure what it is about yours.

Name: Anonymous 2009-09-04 1:52

>>52
Post bench.bf

Name: Anonymous 2009-09-04 2:10

HOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com xHOT STRIPPING COEDS http://twentyfirstcenturycoeds.comicgenesis.com x

Name: Anonymous 2009-09-04 2:28

>>54
how the hell did this get past the autoban?

Name: Anonymous 2009-09-04 4:47

>>55
YHBT.

Name: Anonymous 2009-09-04 5:25

>>55
No autoban on the text boards- duh.

Name: Anonymous 2009-09-04 5:53

>>57
yes there is... or was.
i remember several times in which i have been banned because evidently i am a spambot. each time it happened i was posting four or five urls in the same post, so i just put two and two together.

Name: Anonymous 2009-09-04 6:33

There is an autobanner and it's apparently broken. I was deemed a spambot when I was making a regular posts. No URLs, no repetition.

Name: Anonymous 2009-09-04 13:49

>>58-59
Did you get a popup saying "spam.html" ?

Name: Anonymous 2009-09-04 13:51

>>60
Almost; I got an offer from Firefox to save a file with such name.

Name: Anonymous 2009-09-04 17:56

I think that bfanon38 hanging is something to do with not supporting cell wrap-around.  Working on a better bench.bf at the moment 'cause the last one is shit.

Name: Anonymous 2009-10-29 14:27

Bampu pantsu

Name: GNU pig disgusting 2009-10-29 20:45

I approve of the indentation used in this thread.

Name: Anonymous 2009-10-29 23:35

>>65
Oh holy fuck, I hadn't noticed until now.

Name: Anonymous 2009-10-30 13:02

>>43
The time given under "user" is a far better description of how fast a program runs than "real". Anyway, If you want fast, try beef or the program that beef stole its code from. It matches brackets while the code is loading by loading it into a binary tree. Run-time bracket matching is slower.

Name: Anonymous 2009-11-14 9:41

Why do people write brainfuck interpreters? The thing is so simple that you can write brainfuck in brainfuck. If you're using C, compile the damn code already

Name: Anonymous 2009-11-14 9:50

>>68
Well, why not?

how do i emitted compiled code???

Name: Anonymous 2009-11-14 9:58

>>68
There has been more than one brainfuck compiler posted, It's probably personal preference

Name: Anonymous 2009-11-14 10:30

>>68
C++ is so simple that you can write C++ in C++.

Name: Anonymous 2009-11-14 11:03

                       //`'''```,
             o        // LISP   `.,
       ,....OOo.   .c;.',,,.'``.,,.`
    .'      ____.,'.//
   / _____  \___/.'
  | / ||  \\---\|
  ||  ||   \\  ||
  co  co    co co

Name: Anonymous 2009-11-15 19:06

#include <iostream>

using std::cin;
using std::cout;
using std::cerr;
using std::endl;
#define MS (65536)
struct state {
        unsigned char * tape;
        size_t head;
        static state s;
private:
        state() : tape(new unsigned char[MS]), head() {}
};
state state::s;
state & s = state::s;

template <char c, int times = 1>
struct insn {
        enum { C = c };
        enum { T = 0 };
        void operator () () const {}
};

template <typename B, typename I>
struct block : B {
        typedef B base;
        typedef I insn_;

        block() {}
        block(B const &, I const &) {}

        void operator () () const { B::operator () (); I()(); }

        block<B, insn<I::C, I::T + 1>> operator , (insn<I::C, 1> const &)
        { return block<B, insn<I::C, I::T + 1>>(); }

        template <char c>
        block<block<B, I>, insn<c>> operator , (insn<c> const & i2)
        { return block<block<B, I>, insn<c>>(*this, i2); }
};

template <>
struct block<void, void> {
        typedef void insn_;

        void operator () () const { }

        template <char c>
        block<block, insn<c>> operator , (insn<c> const & i) { return block<block, insn<c>>(*this, i); }
        static block BF;
        block(block const &) {}
        block() {}
};
block<void, void> block<void, void>::BF;
block<void, void> & BF = block<void, void>::BF;

template <typename B>
struct block<B, insn<'['>> : block<void, void> {
        typedef insn<'['> insn_;

        typedef B prev_block;

        block() {}
        block(B const &, insn<'['> const &) {}

        void operator () () const { }

        template <char c>
        block<block<B, insn<'['>>, insn<c>> operator , (insn<c> const & i2)
        { return block<block<B, insn<'['>>, insn<c>>(*this, i2); }
};

template <typename B>
struct block<B, insn<']'>> : B::prev_block {
        typedef insn<']'> insn_;

        block() {}
        block(B const &, insn<']'> const &) {}

        void operator () () const {
                B::prev_block::operator () ();
                while (s.tape[s.head])
                { B()(); }
        }

        template <char c>
        block<block<B, insn<']'>>, insn<c>> operator , (insn<c> const & i2)
        { return block<block<B, insn<']'>>, insn<c>>(*this, i2); }
};

template <int times>
struct insn<'<', times> {
        static char const C = '<';
        static int const T = times;
        void operator () () const {
                if (s.head >= times) s.head -= times;
                else s.head = 0;
        }
};

template <int times>
struct insn<'>', times> {
        static char const C = '>';
        static int const T = times;
        void operator () () const {
                if (s.head + times < MS) s.head += times;
                else s.head = MS - 1;
        }
};

template <int times>
struct insn<'-', times> {
        static char const C = '-';
        static int const T = times;
        void operator () () const {
                s.tape[s.head] -= times;
        }
};

template <int times>
struct insn<'+', times> {
        static char const C = '+';
        static int const T = times;
        void operator () () const {
                s.tape[s.head] += times;
        }
};

template <int times>
struct insn<'.', times> {
        static char const C = '.';
        static int const T = times;
void dump(unsigned char c) const
{
        static int dotc = 155;

        if (dotc-- == 0) { cerr << "too much output" << endl; exit(1); }

        if (c == ' ' || c == '\n' || (c >= 'A' && c <= 'z')) cout << c;
        //else cout << "ip: " << ip << " head: " << head << " depth: " << depth << ' ' << (int)c << endl;
        else cout << (int)c;
}

        void operator () () const {
                for (int i = 0; i < times; i++) dump(s.tape[s.head]);
        }
};

template <int times>
struct insn<',', times> {
        static char const C = ',';
        static int const T = times;
        void operator () () const {
                for (int i = 0; i < times; i++) cin >> s.tape[s.head];
        }
};

template <int times>
struct insn<'[', times> {
        static_assert(times == 1, "No merged loops.");
        static char const C = '[';
        static int const T = times;
        void operator () () const {
        }
};

template <int times>
struct insn<']', times> {
        static_assert(times == 1, "No merged loops.");
        static char const C = ']';
        static int const T = times;
        void operator () () const {
        }
};

        insn<'<'> l;
        insn<'>'> r;
        insn<'+'> p;
        insn<'-'> m;
        insn<'.'> d;
        insn<','> c;
        insn<'['> b;
        insn<']'> e;
int main()
{
        auto prog = (BF
                        BFCODE
        );
        prog();
}


I used sepples C++1x:
g++ -std=c++0x -DBFCODE=`cat x.bf` bf.C -o x

This generates the BFCODE from .bf:
tr -d -c '<>+\-.,[]' | tr '<>+\-.,[]' lrpmdcbe | perl -pe 's/(.)/,$1/g'

Tested with this:
[url]https://trac.parrot.org/languages/browser/bf/trunk/bench.bf[/url]. It takes a little time to compile, but it runs under a second.

Name: Anonymous 2009-11-15 19:32

>>73
Goodness!!  It sure is good to know that what I can do in 88 lines of C can be done in a slim 159 lines of C++

Praise Sepples!

Name: Anonymous 2009-11-15 19:35

Also, I never really did get around to writing a decent Brainfuck benchmarker.

Anyone up to the task?

Name: Anonymous 2009-11-15 20:11

>>75
alias brainfuck_benchmarker=time

Name: Anonymous 2009-11-15 21:21

>>73
I LOVE YOU! I LOVE YOUR POST! I READ IT 5 TIMES! KEEP POSTING!

Name: Anonymous 2009-11-15 21:32

Next challenge: implement a Brainfuck processor in hardware.

Name: Anonymous 2009-11-15 22:11

>>73
This is actually really impressive.

Name: Haxus the Error Report 2009-11-15 22:23

>>73
C:\Dev-Cpp\projects\bfpp.cpp:35: error: a function call cannot appear in a constant-expression

C:\Dev-Cpp\projects\bfpp.cpp:36: error: missing `>' to terminate the template argument list

C:\Dev-Cpp\projects\bfpp.cpp:36: error: missing `>' to terminate the template argument list

C:\Dev-Cpp\projects\bfpp.cpp:36: error: template argument 2 is invalid

C:\Dev-Cpp\projects\bfpp.cpp:36: error: expected unqualified-id before '{' token

C:\Dev-Cpp\projects\bfpp.cpp:39: error: `>>' should be `> >' within a nested template argument list

C:\Dev-Cpp\projects\bfpp.cpp: In member function `block<block<B, I>, insn<c, 1> > block<B, I>::operator,(const insn<c, 1>&)':
C:\Dev-Cpp\projects\bfpp.cpp:40: error: `>>' should be `> >' within a nested template argument list

C:\Dev-Cpp\projects\bfpp.cpp: At global scope:

C:\Dev-Cpp\projects\bfpp.cpp:50: error: `>>' should be `> >' within a nested template argument list

C:\Dev-Cpp\projects\bfpp.cpp: In member function `block<block<void, void>, insn<c, 1> > block<void, void>::operator,(const insn<c, 1>&)':
C:\Dev-Cpp\projects\bfpp.cpp:50: error: `>>' should be `> >' within a nested template argument list

C:\Dev-Cpp\projects\bfpp.cpp: At global scope:

C:\Dev-Cpp\projects\bfpp.cpp:59: error: missing `>' to terminate the template argument list

C:\Dev-Cpp\projects\bfpp.cpp:59: error: template argument 1 is invalid

C:\Dev-Cpp\projects\bfpp.cpp:59: error: missing `>' to terminate the template argument list

C:\Dev-Cpp\projects\bfpp.cpp:59: error: template argument 2 is invalid

C:\Dev-Cpp\projects\bfpp.cpp:75: error: missing `>' to terminate the template argument list

C:\Dev-Cpp\projects\bfpp.cpp:75: error: template argument 1 is invalid

C:\Dev-Cpp\projects\bfpp.cpp:75: error: missing `>' to terminate the template argument list

C:\Dev-Cpp\projects\bfpp.cpp:75: error: template argument 2 is invalid

C:\Dev-Cpp\projects\bfpp.cpp:161: error: ISO C++ forbids declaration of `static_assert' with no type

C:\Dev-Cpp\projects\bfpp.cpp:161: error: expected `;' before '(' token

C:\Dev-Cpp\projects\bfpp.cpp:170: error: ISO C++ forbids declaration of `static_assert' with no type

C:\Dev-Cpp\projects\bfpp.cpp:170: error: expected `;' before '(' token

C:\Dev-Cpp\projects\bfpp.cpp: In function `int main()':
C:\Dev-Cpp\projects\bfpp.cpp:187: error: ISO C++ forbids declaration of `prog' with no type

C:\Dev-Cpp\projects\bfpp.cpp:188: error: expected `)' before "BFCODE"

C:\Dev-Cpp\projects\bfpp.cpp:189: error: cannot convert `block<void, void>' to `int' in initialization

C:\Dev-Cpp\projects\bfpp.cpp:190: error: `prog' cannot be used as a function

Name: Anonymous 2009-11-15 22:41

Dev-Cpp
Compiling Sepples0x with a Sepples2003 compiler
( ≖‿≖)

Name: The Amazing Anus 2009-11-15 22:42

Ok, I am using the bench.bf provided by >>73 (thx btw)

I compile each one with gcc -s -Os.
This is how they match up with the "real" provided by time:

bf         13.291 seconds (My own, as in >>29 )
qdbf        4.774 seconds (QDBF, forget where I found it)
bfanon34    6.287 seconds (Provided by >>34 )
bfanon38   12.527 seconds (Provided by >>38 )


I can't bench >>73 because I still can't get it to compile.

Name: Anonymous 2009-11-15 22:43

>>81
Yeah, I know.  What do you recommend?  Is gcc 4.4.2 (or whatever the newest stable build is) capable of building it?

Name: Anonymous 2009-11-16 17:32

>>77 Why thank you, Dear! I'm very fond of you too.

Here's a version that should compile w/o any trickery.

#include <iostream>

using std::cin;
using std::cout;
using std::cerr;
using std::endl;
#define MS (65536)
struct state {
        unsigned char * tape;
        size_t head;
        static state s;
private:
        state() : tape(new unsigned char[MS]), head() {}
};
state state::s;
state & s = state::s;

template <char c, int times = 1>
struct insn {
        enum { C = c };
        enum { T = 0 };
        void operator () () const {}
};

template <typename B, typename I>
struct block : B {
        typedef B base;
        typedef I insn_;

        block() {}
        block(B const &, I const &) {}

        void operator () () const { B::operator () (); I()(); }

        block<B, insn<I::C, I::T + 1> > operator , (insn<I::C, 1> const &)
        { return block<B, insn<I::C, I::T + 1> >(); }

        template <char c>
        block<block<B, I>, insn<c> > operator , (insn<c> const & i2)
        { return block<block<B, I>, insn<c> >(*this, i2); }
};

template <>
struct block<void, void> {
        typedef void insn_;

        void operator () () const { }

        template <char c>
        block<block, insn<c> > operator , (insn<c> const & i) { return block<block, insn<c> >(*this, i); }
        static block BF;
        block(block const &) {}
        block() {}
};
block<void, void> block<void, void>::BF;
block<void, void> & BF = block<void, void>::BF;

template <typename B>
struct block<B, insn<'['> > : block<void, void> {
        typedef insn<'['> insn_;

        typedef B prev_block;

        block() {}
        block(B const &, insn<'['> const &) {}

        void operator () () const { }

        template <char c>
        block<block<B, insn<'['> >, insn<c> > operator , (insn<c> const & i2)
        { return block<block<B, insn<'['> >, insn<c> >(*this, i2); }
};

template <typename B>
struct block<B, insn<']'> > : B::prev_block {
        typedef insn<']'> insn_;

        block() {}
        block(B const &, insn<']'> const &) {}

        void operator () () const {
                B::prev_block::operator () ();
                while (s.tape[s.head])
                { B()(); }
        }

        template <char c>
        block<block<B, insn<']'> >, insn<c> > operator , (insn<c> const & i2)
        { return block<block<B, insn<']'> >, insn<c> >(*this, i2); }
};

template <int times>
struct insn<'<', times> {
        enum { C = '<' };
        enum { T = times };
        void operator () () const {
                if (s.head >= times) s.head -= times;
                else s.head = 0;
        }
};

template <int times>
struct insn<'>', times> {
        enum { C = '>' };
        enum { T = times };
        void operator () () const {
                if (s.head + times < MS) s.head += times;
                else s.head = MS - 1;
        }
};

template <int times>
struct insn<'-', times> {
        enum { C = '-' };
        enum { T = times };
        void operator () () const {
                s.tape[s.head] -= times;
        }
};

template <int times>
struct insn<'+', times> {
        enum { C = '+' };
        enum { T = times };
        void operator () () const {
                s.tape[s.head] += times;
        }
};

template <int times>
struct insn<'.', times> {
        enum { C = '.' };
        enum { T = times };
void dump(unsigned char c) const
{
        static int dotc = 155;

        if (dotc-- == 0) { cerr << "too much output" << endl; *((int*)0)=1; }

        if (c == ' ' || c == '\n' || (c >= 'A' && c <= 'z')) cout << c;
        //else cout << "ip: " << ip << " head: " << head << " depth: " << depth << ' ' << (int)c << endl;
        else cout << (int)c;
}

        void operator () () const {
                for (int i = 0; i < times; i++) dump(s.tape[s.head]);
        }
};

template <int times>
struct insn<',', times> {
        enum { C = ',' };
        enum { T = times };
        void operator () () const {
                for (int i = 0; i < times; i++) cin >> s.tape[s.head];
        }
};

template <int times>
struct insn<'[', times> {
        enum { C = '[' };
        enum { T = times };
        void operator () () const {
        }
};

template <int times>
struct insn<']', times> {
        enum { C = ']' };
        enum { T = times };
        void operator () () const {
        }
};

        insn<'<'> l;
        insn<'>'> r;
        insn<'+'> p;
        insn<'-'> m;
        insn<'.'> d;
        insn<','> c;
        insn<'['> b;
        insn<']'> e;
int main()
{
        (BF
                        BFCODE
        )();
}


Compile w/ this to get the benchmark previously mentioned:
g++ -O2 -DBFCODE=,r,p,p,b,l,p,p,p,p,p,p,p,p,p,p,p,p,p,r,m,e,l,b,b,r,p,r,p,l,l,m,e,r,b,l,p,r,m,e,p,p,p,p,p,p,p,p,b,r,p,p,p,p,p,p,p,p,l,m,e,r,d,b,m,e,l,l,r,p,p,p,p,p,p,p,p,p,p,b,r,p,p,p,p,p,p,p,p,p,p,b,r,p,p,p,p,p,p,p,p,p,p,b,r,p,p,p,p,p,p,p,p,p,p,b,r,p,p,p,p,p,p,p,p,p,p,b,r,p,p,p,p,p,p,p,p,p,p,b,r,p,p,p,p,p,p,p,p,p,p,b,m,e,l,m,e,l,m,e,l,m,e,l,m,e,l,m,e,l,m,e,l,m,e,p,p,p,p,p,p,p,p,p,p,d

I reckon there's a bug hiding somewhere in there, as it emits a different/wrong result when compiled with cl.exe, than it does when compiled with g++. (I used the 20091112 snapshot of g++-4.5.)

Name: Anonymous 2009-11-16 17:36

what is that -DBFCODE bullshit for?

Name: The Amazing Anus 2009-11-16 17:44

>>84
I don't know why this one doesn't even take a file as input but it runs in 1.560 seconds.

Name: Anonymous 2009-11-16 17:50

>>86
You're an anus! *grabs brick*

Name: The Amazing Anus 2009-11-16 18:02

Now let's see who can write the fastest Brainfuck interpreter.  I want a harder benchmark program, and I want >>84 to take a file as input before I accept it into the contest.

>>87
I big anus that can talk, and feel

but I am not as great as sir ribs T_T

Name: Anonymous 2009-11-16 18:15

Can someone please post a test .bf file which we can use for benchmarking?

Name: Anonymous 2009-11-16 18:21

>>85 Thats the brainfuck program that will be in the executable.

>>86 Because it is not an interpreter. I beleive it's called domain specific language. Domain being in this case the brainfuck language.

>>88 Cf. the previous reply.

Name: Anonymous 2009-11-16 21:24

>>88
*grabs gas*

Name: Anonymous 2009-11-16 23:15

Lazy mode;
$ cat bfcc.pl
#!/usr/bin/perl

$pre=<<EOF;
#include <stdio.h>

char mem[30000];

int main() {
    char * restrict ptr = mem;
EOF

$post=<<EOF;
    return 0;
}
EOF

%inst = (
    '>' => '++ptr;',
    '<' => '--ptr;',
    '+' => '++*ptr;',
    '-' => '--*ptr;',
    '.' => 'putchar(*ptr);',
    ',' => '*ptr=getchar();',
    '[' => 'while (*ptr) {',
    ']' => '}',
);

sub compile {
    my $in=1; my $c;
    (my $x=shift) =~ s/(.)/$c=$inst{$1}and"\t"x('['eq$1?$in++:']'eq$1?--$in:$in)."$c\n"/gse;
    $pre . $x . $post
}

undef $/;
print compile <>;

$ ./bfcc.pl bench.bf | cc -O3 -o bf-bench -xc -std=gnu99 -
$ time ./bf-bench
ZYXWVUTSRQPONMLKJIHGFEDCBA

real    0m0.256s
user    0m0.250s
sys    0m0.003s
$

Name: The Amazing Anus 2009-11-16 23:25

>>92
Nice, but I bet your processor is also faster than the piece of shit I run on.  I will have to try this one out myself.

Name: Anonymous 2009-11-17 1:02

This thread makes me want to write a JIT brainfuck inpiler in Java.

Name: Anonymous 2009-11-17 1:20

A CL "compiler" for bf could be done using macros or just COMPILE, add some declarations and it might even produce some decent code on some implementations.

Name: Anonymous 2009-11-17 1:32

... but I doubt it would exceed the Perl to C compiler's performance, if at all. A better solution might be to go platform specific and generate machine code (or assembly) directly, which might just be faster, especially if one makes it an optimizing compiler...

Name: Anonymous 2009-11-17 3:16

>>94
inpiler
... what?

Name: Anonymous 2009-11-17 3:22

>>97
it's the opposite of enpiler

Name: Anonymous 2009-11-17 3:47

>>98
I'd rather say, outpiler

Name: Anonymous 2009-11-17 14:03

http://esoteric.sange.fi/brainfuck/impl/compilers/bf2c.hs
MIND=BLOWN

It's FAST too:

>>92
~ % perl bfcc.pl bench.bf|gcc -O3 -ffast-math -xc -std=gnu99 -xc -o bf1 -
~ % time ./bf1
ZYXWVUTSRQPONMLKJIHGFEDCBA
./bf1  0.04s user 0.00s system 98% cpu 0.039 total


~ % runghc bf2c.hs <bench.bf |gcc -O3 -ffast-math -xc -std=gnu99 -xc -o bf2 -
~ % time ./bf2
ZYXWVUTSRQPONMLKJIHGFEDCBA
./bf2  0.01s user 0.00s system 97% cpu 0.013 total

Name: Anonymous 2009-11-17 19:42

I HATE women. I never had a girlfriend and never will. The only times I got laid was when I paid a woman or promised her something. I'm never going to hold hands with a chick, kiss a girl intimately because we're in love, or any of the other shit that human beings were made to do. I guess that I'm suppose to be happy masturbating every fucking night. I'm a man with sexual urges and can't get with a female. I'm suppose to be alright with that? THERE IS A FUCKING CURSE ON MY LIFE. A CURSE THAT PREVENTS ANY FEMALE FROM LIKING ME. Oh I forgot, I do get interest from fat chicks and I'm not attracted to fat chicks.
I don't give a fuck anymore. I'm going to become the biggest asshole in the world. I tried the whole being considerate thing and it got me nowhere. If people can't handle my newfound harshness, then bring it on. BECAUSE I DON'T GIVE A FUCK. I DON'T GIVE A FUCK. I DON'T GIVE A FUCK.
I get happy when I hear about some college slut getting murdered or injured in a hit and run. "oh she was a beautiful and talented girl, how could this happen." I don't know but I'm glad it did.

Name: Anonymous 2009-11-17 20:29

>>10
What if you include the compilation time?

Name: Anonymous 2009-11-17 20:45

>>102
~ % time (./bf2c <bench.bf|clang -march=nocona -O3 -o bf2 -xc - && ./bf2)          
ZYXWVUTSRQPONMLKJIHGFEDCBA
(; ./bf2c < bench.bf | clang -march=nocona -O3 -o bf2 -xc - && ./bf2; )  0.07s user 0.03s system 100% cpu 0.103 total


(./bf2c is bf2c.hs compiled with ghc)

Name: Anonymous 2009-11-17 20:48

>>102
I really just wanted interpreters, not compilers

Name: Anonymous 2009-11-17 21:25

>>104
well, you get what you pay for

Name: Anonymous 2009-11-18 11:16

>>105
But I paid my anus for this!

Name: Anonymous 2010-02-06 11:28

mailto:sage

Name: Anonymous 2010-02-06 20:14

>>107
You never answer my emails >:(

Name: Anonymous 2010-02-06 20:23

BRAINFUCK MY ANUS

Name: Anonymous 2010-02-06 20:24

BRAINFUCK MY ANUS

Name: Anonymous 2010-02-06 20:29

ANUSFUCK MY BRAIN

Name: Anonymous 2010-02-07 0:52

FUCK MY BRAINUS

Name: Anonymous 2010-02-07 2:46



    FUCK MY BRAINUS

Name: Anonymous 2010-02-07 4:14

BRAINUS: the wonder of modern genetics.

Name: Anonymous 2010-04-26 10:27

I was bored as fuck so I decided to implement an ``ed'' interpreter in C.

#include <stdio.h>

int main(int argc, char* argv) {
  while (1) {
    char* c;
    scanf("%s", c);
    printf("?");
  }
  return 1;
}

Name: Anonymous 2010-04-26 17:11


$ed
#include <stdio.h>

int main(int argc, char* argv) {
  while (1) {
    char* c;
    scanf("%s", c);
    printf("?");
  }
  return 1;
} ?
?
?
?
?
?
?
?
?

Name: Anonymous 2010-04-26 21:37

Here's my shot at it..


void compile(char *code) {
    int     *memory                = (int *) malloc(MEMORY_SIZE * sizeof(int));
    int     *memory_ptr            = memory;
    int     nested_loop_level   = 0;

    while(memory_ptr <= memory + MEMORY_SIZE)
        *memory_ptr++ = 0;
    memory_ptr = memory;
   
    while(*code != '\0') {
        switch(*code) {
            case '+' :
                (*memory_ptr)++;
                break;
               
            case '-':
                (*memory_ptr)--;
                break;
               
            case '>':
                memory_ptr++;
                if(memory_ptr > memory + MEMORY_SIZE)
                    memory_ptr = memory;
                break;
               
            case '<':
                memory_ptr--;
                if(memory_ptr < memory)
                    memory_ptr = memory + MEMORY_SIZE;
                break;
               
            case '.':
                putchar(*memory_ptr);
                break;
               
            case ',':
                *memory_ptr    = getchar();
                break;
               
            case '[':
                if(*memory_ptr == 0) {
                    code++;
                    while(nested_loop_level > 0 || *code != ']' ) {
                        if(*code == '[')
                            nested_loop_level++;
                        if(*code == ']')
                            nested_loop_level--;
                        code++;
                    }
                }
                break;
               
            case ']':
                code--;
                while(nested_loop_level > 0 || *code != '[') {
                    if(*code == ']')
                        nested_loop_level++;
                    if(*code == '[')
                        nested_loop_level--;
                    code--;
                }
                code--;
        }
        code++;
    }
}


So what do you think?

Name: Anonymous 2010-11-25 12:59

Name: Anonymous 2010-12-17 1:27

Are you GAY?
Are you a NIGGER?
Are you a GAY NIGGER?

If you answered "Yes" to all of the above questions, then GNAA (GAY NIGGER ASSOCIATION OF AMERICA) might be exactly what you've been looking for!

Don't change these.
Name: Email:
Entire Thread Thread List