Brainbool interpreter
Jump to navigation
Jump to search
This is the reference Brainbool interpreter
#!/usr/bin/perl -w use Getopt::Long; use strict; use integer; Getopt::Long::Configure ("bundling"); my $help =<<EOH; brainbool.pl - Brainbool interpreter in perl usage: perl brainbool.pl [ opts ] program cat program | perl brainbool.pl [ opts ] options: -h --help This help -i --interpret The default mode of operation; interprete a brainbool program. When combined with --to-brainbool, will interpret the resultant program -c --to-brainbool --bb Convert a brainfuck program to brainbool Can be combined with --interpret -n --input Convert a stream of characters to a stream of '0's and '1's (inputs on STDIN & outputs on STDOUT) Can be combined with --to-brainbool if brainfuck source is in a file and input stream is on STDIN Can be combined with --interpret if brainbool source is in a file and input stream is on STDIN Brainfuck/Brainbool source can be on STDIN if --bang is used -o --output Convert a stream of '0's and '1's to a stream of characters (inputs on STDIN & outputs on STDOUT) '0' and '1' characters may each be on their own line -b --bang Read program on STDIN and stop at the first "!" character. Everything following the first "!" is input to the program. In --to-brainbool mode, append a "!" after the brainbool program. --nl Separate each character by a newline Valid in all modes of operation see http://esolangs.org/wiki/Brainbool for more information on Brainbool license: Public Domain EOH my $bang; my $brainbool; my $output; my $input; my $nl; my $debug; my $source = ""; GetOptions ('help|h' => sub { print "$help"; exit 0; }, 'bang|b' => \$bang, 'to-brainbool|bb|c' => \$brainbool, 'output|o' => \$output, 'input|i' => \$input, 'nl' => \$nl, 'debug|d' => \$debug); if ($brainbool) { $source = join(, <>); $source =~ s/[^-+\[\]<>,\.]//gs; $source =~ s/-/A/g; $source =~ s/\+/B/g; $source =~ s/\[/C/g; $source =~ s/\]/D/g; $source =~ s/</E/g; $source =~ s/>/F/g; $source =~ s/,/G/g; $source =~ s/\./H/g; while ($source =~ s/AB//g || $source =~ s/BA//g || $source =~ s/EF//g || $source =~ s/FE//g || $source =~ s/AA/IA/g || $source =~ s/AI/IA/g || $source =~ s/BB/JB/g || $source =~ s/BJ/JB/g) { } $source =~ s/A/>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+]<<<<<<<<</g; $source =~ s/B/>[>]+<[+<]>>>>>>>>>[+]<<<<<<<<</g; $source =~ s/C/>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>[+<<<<<<<<[>]+<[+<]/g; $source =~ s/D/>>>>>>>>>+<<<<<<<<+[>+]<[<]>>>>>>>>>]<[+<]/g; $source =~ s/E/<<<<<<<<</g; $source =~ s/F/>>>>>>>>>/g; $source =~ s/G/>,>,>,>,>,>,>,>,<<<<<<<</g; $source =~ s/H/>.>.>.>.>.>.>.>.<<<<<<<</g; $source =~ s/I/>>>>>>>>>+<<<<<<<<+[>+]<[<]/g; $source =~ s/J/>[>]+<[+<]/g; while ($source =~ s/><//g || $source =~ s/<>//g) { } $source .= $bang ? "!" : ""; if ($input) { my $ch; while (defined($ch = getc())) { $source .= reverse(sprintf('%08b', ord($ch))); } } print join(($nl ? "\n" : ""), split(//, $source), ""); exit 0; } elsif ($output) { my $bits = ""; while (<>) { s/\n//gs; $bits .= $_; while (length($bits) >= 8) { print chr(eval("0b" . reverse(substr($bits, 0, 8, "")))); } } exit 0 } elsif ($input) { my $sep = $nl ? "\n" : ""; while (<>) { while (length($_) >= 1) { print join($sep, split(//, reverse(sprintf('%08b', ord(substr($_, 0, 1, ""))))), ""); } } exit 0 } if ($bang) { my $ch; while (($ch = getc()) ne "!") { die "no \"!\" ever found on STDIN\n" unless defined $ch; $source .= $ch; } } else { $source = join(, <>); } my @bracket; my @tape = (0); my $t_ptr = 0; my @prog; while (length($source)) { my $ch = substr($source, 0, 1, ""); if ($ch eq ">") { push @prog, sub { $t_ptr++; $tape[$t_ptr] = 0 if $t_ptr > $#tape; }; } elsif ($ch eq "<") { push @prog, sub { $t_ptr--; }; } elsif ($ch eq "+") { push @prog, sub { $tape[$t_ptr] = !$tape[$t_ptr]; }; } elsif ($ch eq ",") { push @prog, sub { my $ch = getc(); $tape[$t_ptr] = defined($ch) ? $ch + 0 : 0; }; } elsif ($ch eq ".") { push @prog, $debug ? sub { print($tape[$t_ptr] ? "1\n" : "0\n"); } : sub { print($tape[$t_ptr] ? "1" : "0"); }; } elsif ($ch eq "[") { push @bracket, $#prog+1; } elsif ($ch eq "]") { do { my @p2 = splice @prog, pop(@bracket); push @prog, sub { @prog = (@p2, shift, @prog) if $tape[$t_ptr] }; }; } } while (scalar @prog) { print join(" ", map { $_ ? 1 : 0 } @tape[0 .. $t_ptr]), "@", join(" ", map { $_ ? 1 : 0 } @tape[$t_ptr+1 .. $#tape]), "\n" if $debug; my $i = shift @prog; $i->($i); }