2009-03-30

polyglot: ain't your brain fucked yet?

reminder: this article is part of a serie.

it's becoming harder and harder to follow. your brain may start to melt, so let's be proactive, and play with brainfuck! :-)

brainfuck is yet another esoteric language. it is a minimalist programming, language, where each character is an instruction (same as befunge). it contains only 8 instructions yet is turing complete. and anyone who tried to program with it definitely knows why this name was chosen. we're going to use aidbf for our tests.

since esoteric languages are hard to program with, we'll start once again by writing the brainfuck version without messing with our polyglot program. here's my version:


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


interesting, uh? :-) that took me quite some time to write it... (you're welcome to come up with your own version if you want to) so, now let's insert this gem in our polyglot program. but where? well, brainfuck has this interesting property of ignoring all the unknown instructions. so let's try to insert it somewhere... the end of the file is our place of choice for this:


[...]
end
* ++++++++++>[-]++++++++++>+>+<<[->[>>+>+>+<<<<-]>[<+>>>>+<<<-]>>>[<<<+>>>-]<>++
* +++++++<[>>>+<<[>+>[-]<<-]>[<+>-]>[<<++++++++++>>>+<-]<<-<-]>>>>[<<<<+>>>>-]<<
* <<>[-]<[++++++++++++++++++++++++++++++++++++++++++++++++.---------------------
* ---------------------------[<---------->-]]<++++++++++++++++++++++++++++++++++
* ++++++++++++++.------------------------------------------------<<<<.>>>>[-]<<<]
[...]


however, this does not work since some brainfuck instructions are used before, and therefore mess up the data pointer and the value under the data pointer. sigh. and we cannot cheat regarding this, since the characters used by brainfuck are quite common. so, should we abandon? no, we won't let that affect us! let's use a brainfuck while, which will skip the whole program till the actual brainfuck program. in brainfuck, the while is noted [ ... ] (that is, square brackets). it will repeat everything between the square brackets till the value pointed by the data pointer is not null. since the values pointed by the data pointer are initially null, the while loop will be skipped directly. so, let's just add a [ at the beginning of our program, and a ] just before our brainfuck program. but in order not to disturb befunge, we insert it before the caret - and we don't forget to line up the bottom of the file:


(*foo /*bar#[^
[...]
* ]++++++++++>[-]++++++++++>+>+<<[->[>>+>+>+<<<<-]>[<+>>>>+<<<-]>>>[<<<+>>>-]<>++
* +++++++<[>>>+<<[>+>[-]<<-]>[<+>-]>[<<++++++++++>>>+<-]<<-<-]>>>>[<<<<+>>>>-]<<
* <<>[-]<[++++++++++++++++++++++++++++++++++++++++++++++++.---------------------
* ---------------------------[<---------->-]]<++++++++++++++++++++++++++++++++++
* ++++++++++++++.------------------------------------------------<<<<.>>>>[-]<<<]
[...]
*n 1:86*+,a,86*+,a,11884pv >
[...]
*/
#define fubar *)



note the [ at the end of the first line, and the ] just before our brainfuck program. and this time, the fibonacci numbers are appearing... but the program never stops! why? well, once again there are some brainfuck instructions trailing after the brainfuck program. but we now know the recipe, and just skip them with a while loop happily skipped:


[...]
* ]++++++++++>[-]++++++++++>+>+<<[->[>>+>+>+<<<<-]>[<+>>>>+<<<-]>>>[<<<+>>>-]<>++
* +++++++<[>>>+<<[>+>[-]<<-]>[<+>-]>[<<++++++++++>>>+<-]<<-<-]>>>>[<<<<+>>>>-]<<
* <<>[-]<[++++++++++++++++++++++++++++++++++++++++++++++++.---------------------
* ---------------------------[<---------->-]]<++++++++++++++++++++++++++++++++++
* ++++++++++++++.------------------------------------------------<<<<.>>>>[-]<<<][
[...]
*/
#define fubar ]*)


and our tests are now all passing:


$ prove -l t
t/bash.........ok
t/befunge......ok
t/brainfuck....ok
t/c............fibonacci.c:1: warning: data definition has no type or storage class
t/c............ok
t/fortran......ok
t/pascal.......ok
t/perl.........ok
All tests successful.
Files=7, Tests=7, 0 wallclock secs ( 0.03 usr 0.01 sys + 0.44 cusr 0.08 csys = 0.56 CPU)
Result: PASS


that was easy, finally. and since we're at it, let's just insert a new language derived from brainfuck: ook! (named after terry pratchett's discworld librarian) ook is bijective with brainfuck: each brainfuck instruction is translated as a ook! ook! instruction. of course, unknown instruction are skipped too... so let's
just create our test file (using Language::Ook interpreter), translate our brainfuck program, and insert it. our program now looks like:

                                                                                                                                                                                    
(*foo /*bar^#[
*1337#) 2>/dev/null;i=0; a=1; b=1;echo $a;while test $i -lt 9;do c=$((a+b));a=$b;b=$c;echo $a;i=$((i+1));done;exit
*0) if 0; sub C () {} # */ );

#include <stdio.h>
#include <stdlib.h>
#define C
#define $ /*
C ; "*/
C ; main () { /*"; { # */
C ; int $ i;
C ; int $ n1;
C ; int $ n2;
C ; int $ n3;
C ; $ i = 0;
C ; $ n1 = 1;
C ; $ n2 = 1;
C ; printf( "%d\n", $ n1 );
C ; while ( $ i < 9 ) {
C ; $ n3 = $ n1 + $ n2;
C ; $ n1 = $ n2;
C ; $ n2 = $ n3;
C ; printf( "%d\n", $ n1 );
C ; $ i++;
C ; }
C ; }

#define foo /*
C ; __END__
*) program foo; (*
*) var i, n1, n2, n3 : integer; (*
*) begin i := 0; n1 := 1; n2 := 1; writeln(n1); while i < 9 do begin (*
*) n3 := n1 + n2; n1 := n2; n2 := n3; writeln(n1); i := i + 1; end; end.(*

integer i, n1, n2, n3
n1 = 1
n2 = 1
print '(I0)', n1
do 10 i = 1, 9
n3 = n1 + n2
n1 = n2
n2 = n3
print '(I0)', n1
10 continue
end
* ]++++++++++>[-]++++++++++>+>+<<[->[>>+>+>+<<<<-]>[<+>>>>+<<<-]>>>[<<<+>>>-]<>++
* +++++++<[>>>+<<[>+>[-]<<-]>[<+>-]>[<<++++++++++>>>+<-]<<-<-]>>>>[<<<<+>>>>-]<<
* <<>[-]<[++++++++++++++++++++++++++++++++++++++++++++++++.---------------------
* ---------------------------[<---------->-]]<++++++++++++++++++++++++++++++++++
* ++++++++++++++.------------------------------------------------<<<<.>>>>[-]<<<][
* Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.
* Ook. Ook. Ook. Ook? Ook! Ook? Ook! Ook! Ook? Ook! Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.
* Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook. Ook. Ook. Ook?
* Ook. Ook. Ook? Ook. Ook? Ook. Ook! Ook? Ook! Ook! Ook. Ook? Ook! Ook? Ook. Ook? Ook. Ook?
* Ook. Ook. Ook. Ook? Ook. Ook. Ook. Ook? Ook. Ook. Ook? Ook. Ook? Ook. Ook? Ook. Ook? Ook.
* Ook! Ook! Ook? Ook! Ook. Ook? Ook! Ook? Ook? Ook. Ook. Ook. Ook. Ook? Ook. Ook? Ook. Ook?
* Ook. Ook? Ook. Ook. Ook? Ook. Ook? Ook. Ook? Ook. Ook! Ook! Ook? Ook! Ook. Ook? Ook. Ook?
* Ook. Ook? Ook! Ook? Ook? Ook. Ook? Ook. Ook? Ook. Ook. Ook. Ook. Ook? Ook. Ook? Ook. Ook?
* Ook! Ook! Ook? Ook! Ook? Ook. Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.
* Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook. Ook! Ook? Ook. Ook? Ook. Ook? Ook. Ook?
* Ook. Ook. Ook? Ook. Ook? Ook. Ook! Ook? Ook. Ook? Ook. Ook. Ook. Ook? Ook! Ook? Ook! Ook!
* Ook? Ook! Ook? Ook. Ook? Ook. Ook! Ook! Ook? Ook! Ook. Ook? Ook! Ook? Ook? Ook. Ook. Ook.
* Ook. Ook? Ook! Ook! Ook? Ook! Ook. Ook? Ook! Ook? Ook? Ook. Ook? Ook. Ook. Ook. Ook. Ook.
* Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook?
* Ook. Ook? Ook. Ook? Ook. Ook. Ook? Ook. Ook! Ook! Ook? Ook! Ook? Ook. Ook? Ook. Ook! Ook!
* Ook? Ook. Ook! Ook! Ook? Ook! Ook. Ook? Ook. Ook? Ook. Ook? Ook. Ook? Ook! Ook? Ook? Ook.
* Ook? Ook. Ook? Ook. Ook? Ook. Ook. Ook. Ook. Ook? Ook. Ook? Ook. Ook? Ook. Ook? Ook! Ook!
* Ook? Ook! Ook? Ook. Ook? Ook. Ook? Ook. Ook? Ook. Ook. Ook? Ook! Ook? Ook! Ook! Ook? Ook!
* Ook? Ook. Ook! Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.
* Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.
* Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.
* Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.
* Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.
* Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook. Ook! Ook! Ook! Ook! Ook! Ook!
* Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook!
* Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook!
* Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook!
* Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook!
* Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook!
* Ook! Ook? Ook? Ook. Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook!
* Ook! Ook! Ook! Ook! Ook! Ook! Ook. Ook? Ook! Ook! Ook? Ook! Ook? Ook! Ook? Ook. Ook. Ook.
* Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.
* Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.
* Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.
* Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.
* Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.
* Ook. Ook. Ook. Ook. Ook! Ook. Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook!
* Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook!
* Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook!
* Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook!
* Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook!
* Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook? Ook. Ook? Ook. Ook? Ook.
* Ook? Ook. Ook! Ook. Ook. Ook? Ook. Ook? Ook. Ook? Ook. Ook? Ook! Ook? Ook! Ook! Ook? Ook!
* Ook? Ook. Ook? Ook. Ook? Ook. Ook? Ook!
*n 1:86*+,a,86*+,a,11884pv >
*$ +,>a,94g\84g1-:84p!#@_>:94p+:a`#v_:'0 ::
* ^ ,+*68-*+55/+55::,+*+338/+55:<
*/
#define fubar ]*)


and everything is running smoothly:


$ prove -l t
t/bash.........ok
t/befunge......ok
t/brainfuck....ok
t/c............fibonacci.c:1: warning: data definition has no type or storage class
t/c............ok
t/fortran......ok
t/ook..........ok
t/pascal.......ok
t/perl.........ok
All tests successful.
Files=8, Tests=8, 0 wallclock secs ( 0.04 usr 0.01 sys + 0.49 cusr 0.10 csys = 0.64 CPU)
Result: PASS


that is, 8 different languages... ok, 3 of them are esoteric, but that's quite an achievement nevertheless! now is the time to get back to more mainstream languages... but this will be in another post...

1 comment:

  1. Well, I must say your article was interesting but way beyond my current knowledge level. I'll save it and try to figure it out. I'm new at this.

    ReplyDelete