Brainfuck Interpreter (Perl)
Author |
Message |
Degensquared
|
Posted: Thu Dec 18, 2008 10:33 pm Post subject: Brainfuck Interpreter (Perl) |
|
|
An interpreter for Brainfuck that I wrote in perl as a challenge to myself. I had trouble implementing this while I was using turing, but I found that the dynamic arrays and regex really helped out. I'm looking for some critique here. What could I have done differently, what did I do well? I'm very new to perl, so if I went about certain problems in a way that could be solved much easier using some feature of perl of which I'm not aware, I'd appreciate the information.
Usage: perl bfi.pl input.txt
code: | #!/usr/bin/perl -w
use strict;
use 5.010;
# ------------------------------------------------
# BrainFuck Intepreter -- By: Cody Veal (12/15/08)
# ------------------------------------------------
# OPEN INPUT FILE
die "use the following usage: perl bfi.pl code.txt" if (scalar(@ARGV) != 1);
open my $stream, $ARGV[0] or die "error opening file: $!";
# INITIALIZE POINTER, ARRAY, COUNTER, LOOP STACK
my $top = 5000;
my @array = (1..$top);
my $ptr = 0;
my $i = 0;
my @loops;
for my $i (0..scalar(@array)-1) {
$array[$i] = 0;
}
# SET UP INPUT
my $input = "";
# concatanates all data into a single line
while (<$stream>) {
chomp;
$input .= $_;
}
# substitutes any non-bf characters with nothing (removes all chars that are not bf commands)
$input =~ s/[^\+\-\.\[\],<>]//g;
# ERROR CHECK
my $rbracket = scalar(grep(/[\[]/, $input));
my $lbracket = scalar(grep(/[\]]/, $input));
die "bracket numbers don't match -- ([:$rbracket | ]:$lbracket)" if $rbracket != $lbracket;
# ENTER EXECUTION LOOP
while ($i < length($input)) {
my $c = substr($input,$i,1);
$i += 1;
# move pointer to left (wrap to top if ptr is at 0)
if ($c eq "<") {
$ptr = $top + 1 if ($ptr == 0);
$ptr -= 1;
}
# move pointer to right (wrap to 0 if ptr is at top)
elsif ($c eq ">") {
$ptr = -1 if ($ptr == $top);
$ptr += 1;
}
# increment value at ptr by 1 (wrap to 0 if value is 255)
elsif ($c eq "+"){
$array[$ptr] = -1 if ($array[$ptr] == 255);
$array[$ptr] += 1;
}
# decrement value at ptr by 1 (wrap to 255 if value is 0)
elsif ($c eq "-") {
$array[$ptr] = 256 if ($array[$ptr] == 0);
$array[$ptr] -= 1;
}
# print ascii char of value at ptr
elsif ($c eq ".") {
print chr($array[$ptr]);
}
# get ascii value of char from input and store in value at ptr
elsif ($c eq ",") {
my $in = <STDIN>;
$array[$ptr] = ord(substr($in,0,1));
}
# store the place after the [ symbol occurs on the top of stack
elsif ($c eq "[") {
push @loops, $i;
}
# if value at ptr is == 0, pop loop location from top of stack, else go to position after last [ was found.
elsif ($c eq "]") {
if ($array[$ptr] != 0) {
$i = $loops[scalar(@loops)-1];
}
else {
pop @loops;
}
}
} |
|
|
|
|
|
 |
Sponsor Sponsor

|
|
 |
wtd
|
Posted: Thu Dec 18, 2008 11:45 pm Post subject: RE:Brainfuck Interpreter (Perl) |
|
|
You could store operations as anonymous subroutine references in a hash, where indexes for the hash are the character.
Something like:
code: | use 5.010;
use strict;
my %ops = {
"+" => sub { say "+ op encountered" }
};
$a{"+"}->(); |
|
|
|
|
|
 |
Insectoid

|
Posted: Fri Dec 19, 2008 9:00 am Post subject: RE:Brainfuck Interpreter (Perl) |
|
|
Wow, just had a look at the brainfuck wiki. Looks like it could be fun to learn! though it would be a pain in the arse to debug... |
|
|
|
|
 |
Degensquared
|
Posted: Fri Dec 19, 2008 11:45 am Post subject: Re: Brainfuck Interpreter (Perl) |
|
|
wtd: That sounds interesting, could you explain the syntax a little bit? Where did $a come from? Perhaps that was supposed to be $ops, which would make sense. Why does it require the -> to the anonymous sub? I thought that changing the % to a $ made it a reference to the value of whatever is at that index? Or am I confused about what the meaning of that arrow is? I'd really appreciate the clarification.
insectoid: I'd suggest using the Brainfuck Machine (http://www.kacper.kwapisz.eu/index.php?i=19) if you want to do programming in Brainfuck. It has a step-through debugger and a table with the memory values. |
|
|
|
|
 |
Insectoid

|
Posted: Fri Dec 19, 2008 12:21 pm Post subject: RE:Brainfuck Interpreter (Perl) |
|
|
No, I don't want to learn it. I just said it could be fun. The language is too odd to learn now. I might get brainfucked. |
|
|
|
|
 |
wtd
|
Posted: Fri Dec 19, 2008 2:25 pm Post subject: RE:Brainfuck Interpreter (Perl) |
|
|
Oh, that was me mixing up decent naming with my experimentation.
code: | use 5.010;
use strict;
my %ops = {
"+" => sub { say "+ op encountered" }
};
$ops{"+"}->(); |
%ops is the name of the hash. The % sigil becomes $ when it's accessed. As for the -> well that dereferences the subroutine references and the () calls the subroutine. |
|
|
|
|
 |
|
|