/* Optimizing brainfuck implementation of dialect based on Daniel's dbfi (see "A very short self-interpreter") This interpreter has only one input: program and input to the program have to be separated with ! e.g. ",.!a" prints 'a' To use it in interactive mode paste your program as input. This program can be compiled with NOLNR macro defined. NOLNR disables optimization of linear loops (where '<>' balanced), e.g. [->+>++<<]. Linear loop is then executed in one step. Oleg Mazonka 4 Dec 2006 http://mazonka.com/ */ #include #include #include typedef struct _op { int shift, off; int * d, sz; struct _op * go; int c; int igo, linear; int * db, dbsz; } op; void printop(op *z) { int j; printf("op='"); if( !strchr("<>+-",z->c) ) printf("%c",(char)z->c); for( j=0; jdbsz; j++ ) printf("%c",(char)z->db[j]); printf("' shift=%d off=%d go=%d { " ,z->shift, z->off, z->igo ); for( j=0; jsz; j++ ) printf("%d ",z->d[j]); printf("}\n"); } void * zalloc(void *p, int sz, int osz) { p = realloc(p,sz); memset((char*)p+osz,0,sz-osz); return p; } #define zalloci(p,sz,osz) zalloc(p,(sz)*sizeof(int),(osz)*sizeof(int)); int getbf() { int a; next: a = getchar(); if( a==-1 ) return -1; if( !strchr(",.[]+-<>!",a) ) goto next; return a; } int consume(op *o) { int mp=0,i; int a = o->c; if( strchr("[]",a) ) a=getbf(); o->sz = 1; o->d = zalloci(0,1,0); o->off = 0; o->dbsz=0; o->db=0; for(;;a=getbf()) { if( a==-1 || a=='!' ) break; if( strchr(",.[]",a) ) break; o->db = zalloci(o->db,o->dbsz+1,o->dbsz); o->db[o->dbsz++] = a; if( a=='+' ) o->d[mp]++; if( a=='-' ) o->d[mp]--; if( a=='>' ) { mp++; if( mp>=o->sz ) { o->d = zalloci(o->d,o->sz+1,o->sz); o->sz++; } } if( a=='<' ) { if( mp>0 ) mp--; else { o->off--; o->d = zalloci(o->d,o->sz+1,o->sz); for( i=o->sz; i>0; i-- ) o->d[i] = o->d[i-1]; o->d[0] = 0; o->sz++; } } } o->shift = mp + o->off; /* cut corners */ while( o->sz && o->d[o->sz-1] == 0 ) o->sz--; while( o->sz && o->d[0] == 0 ) { o->sz--; for( i=0; isz; i++ ) o->d[i] = o->d[i+1]; o->off++; } return a; } int main() { op * o=0, *z, *zend; int sz=0, i, *m, mp, msz; int a = getbf(); for(;;sz++) { o = zalloc(o,(sz+1)*sizeof(op),sz*sizeof(op)); if( a==-1 || a=='!' ) break; o[sz].c = a; if( strchr(",.",a) ){ a=getbf(); continue; } if( a==']' ) { int l=1, i=sz; while(l&&i>=0) if(i--) l+=(o[i].c==']')-(o[i].c=='['); if( i<0 ){ printf("unbalanced ']'\n"); exit(1); } o[i].igo = sz; o[sz].igo = i; } a = consume(o+sz); } for( i=0;ic == ']' ) { if( m[mp] ) z=z->go; } else if( z->c == '[' ) { if( !m[mp] ) z=z->go; } else if( z->c == ',' ){ m[mp] = getchar(); continue; } else if( z->c == '.' ){ putchar(m[mp]); continue; } /* apply */ if( z->sz ) { int nmsz = mp+z->sz+z->off; if( nmsz > msz ) { m = zalloci(m,nmsz,msz); msz = nmsz; } #ifndef NOLNR if( z->linear ) { int del = m[mp]/z->linear; for( i=0; isz; i++ ) m[mp+z->off+i]+=del*z->d[i]; }else #endif for( i=0; isz; i++ ) m[mp+z->off+i]+=z->d[i]; } if( z->shift>0 ) { int nmsz = mp+z->shift+1; if( nmsz > msz ) { m = zalloci(m,nmsz,msz); msz = nmsz; } } mp += z->shift; #ifdef DBG for( i=0; i