Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Inline::Brainfck

by jaldhar (Vicar)
on Aug 29, 2002 at 12:26 UTC ( [id://193742]=CUFP: print w/replies, xml ) Need Help??

Changed: Yes there should be a u between the c and k. Changed to protect those reading at work etc.

Changed(2): Doh I mean between the f and c.

(We don't have a "perverted and insane uses for Perl" section so I thought I'd post this here.)

I was pleasently surprised to discover I had recently made friar. With such exalted status comes a certain sense of responsibility to help further the advance of Perl. Looking over the situation, I found two things wrong with the current state of the language:

  • It is not obfuscated enough. I have heard that some people can read and even understand perl scripts. How are we to defend our precious Intellectual Property against unsavory hacker types?
  • There is not enough punctuation. In fact some parts of your average perl script are not punctuation at all!!!!!

In order to remedy these glaring flaws may I present to you, Inline::Brainfck.

# # See POD documentation below for description, copyright and licensing + info. # package Inline::Brainfck; use Filter::Simple; use strict; use warnings; #remember to change this in the POD too. our $VERSION = '0.9.0'; # The memory pointer and memory cells of our Turing machine. our $p = 0; our @m = (); # The basic Brainfck instructions. Extras will be added in import(). our $ops = '+-<>,.[]'; # Whether or not we accept extra instructions. our $verbose = 0; # print out filtered text? our $debug = 0; sub import() { shift; foreach (@_) { if (/^verbose$/) { $ops .= '~#'; $verbose = 1; } if (/^debug$/) { $debug = 1; } } } FILTER_ONLY code => sub { my $ret = $_; while ($ret =~ /\s ([\Q$ops\E]+) \s/gsx) { my $code = $1; my $len = length($1); my $at = pos($ret) - ($len + 1); $code =~ s/^/do { /g; $code =~ s/$/P; }; /g; $code =~ s/\+/P++; /g; $code =~ s/\-/P--; /g; $code =~ s/</\$Inline::Brainfck::p--; /g; $code =~ s/>/\$Inline::Brainfck::p++; /g; $code =~ s/\./print chr P; /g; $code =~ s/,/P = ord getc;/g; $code =~ s/\[/while(P){/g; $code =~ s/\]/}; /g; if ($verbose) { $code =~ s/~/\$Inline::Brainfck::p = 0;\@Inline::Brainfck::m = (); /g; $code =~ s/\#/print STDERR sprintf\('\$p = %d \$m[\$p]= %d', \$Inline:: +Brainfck::p, P\), "\\n"; /g; } $code =~ s/P/\$Inline::Brainfck::m\[\$Inline::Brainfck::p\]/g; substr($ret, $at, $len, $code); } $_ = $ret; print $_ if $debug; }; 1; __END__ =pod =head1 NAME Inline::Brainfck - Embed Brainfck in your perl code =head1 SYNOPSIS #!/usr/bin/env perl use Inline::Brainfck; print 'Hello world!', chr ++++++++++. ; =head1 ABSTRACT Brainfck is about the tiniest Turing-complete programming language you + can get. A language is Turing-complete if it can model the operations of +a Turing machine--an abstract model of a computer defined by the British mathem +atician Alan Turing in 1936. A Turing machine consists only of an endless seq +uence of memory cells and a pointer to one particular memory cell. Yet it is theoretically capable of performing any computation. This module will + allow you to mix Brainfck with your perl code. =head1 DESCRIPTION =head2 Instructions With this module, you can embed Brainfck instructions delimited by whitespace into your perl code. It will be translated into Perl as parsed. Brainfck has just just 8 instructions (well more in this implementation, see L</"Extensions to ANSI Brainfck"> below.) which ar +e as follows =over 4 =item + Increment Increase the value of the current memory cell by one. =item - Decrement Decrease the value of the current memory cell by one. =item > Forward Move the pointer to the next memory cell. =item < Back Move the pointer to the previous memory cell. =item , Input Read a byte from Standard Input and store it in the current memory cel +l. =item . Output Write the value of the current memory cell to standard output. =item [ Loop If the value of the current memory cell is 0, continue to the cell aft +er the next ']'. =item ] Next Go back to the last previous '['. =back =head2 Extensions to ANSI Brainfck This implementation has extra instructions available. In order to avo +id such terrible bloat, they are only available if you use the I<verbose> prag +ma like so: use Inline::Brainfck qw/verbose/; The extra instructions are: =over 4 =item ~ Reset Resets the pointer to the first memory cell and clear all memory cells +. =item # Peek Prints the values of the memory pointer and the current memory cell to + STDERR. See also L</"Debugging"> below. =back =head2 Debugging By using the I<debug> pragma like this: use Inline::Brainfck qw/debug/; you can dump out the generated perl code. (Caution: it is not pretty. +) The key to understanding it is that the memory pointer is represented +by I<$p>, and the memory array by I<@m> Therefore the value of the curr +ent memory cell is I<$m[$p]>. =head1 RETURN VALUE Each sequence of Brainfck instructions becomes a Perl block and return +s the value of the current memory cell. =head1 EXAMPLES =head2 JABH #!/usr/bin/env perl use Inline::Brainfck; print "Just another "; ++++++[>++++++++++++++++<-]> ++.-- >+++[<++++++>-]<.>[-]+++[<------>-]< +.- +++++++++.--------- ++++++++++++++.-------------- ++++++.------ >+++[<+++++++>-]<.>[-]+++[<------->-]< +++.--- +++++++++++.----------- print " hacker.\n"; =head2 Countdown #!/usr/bin/env perl use strict; use Inline::Brainfck qw/verbose/; print "Countdown commencing...\n"; ++++++++++[>+>+<<-] >>+++++++++++++++++++++++++++++++++++++++++++++++<< ++++++++++[>>.-<.<-] print "We have liftoff!\n"; =head2 Reverse #!/usr/bin/env perl use Inline::Brainfck qw/verbose/; while(1) { print "Say something to Backwards Man and then press enter: "; +[->,----------]< print 'Backwards Man says, "'; [+++++++++++.<]< print "\" to you too.\n"; ~ } =head2 Math #!/usr/bin/env perl use Inline::Brainfck; use strict; use warnings; my $answer = +++[>++++++<-]> ; print "3 * 6 = $answer \n"; =head1 VERSION 0.9.0 Aug 29, 2002 =head1 AUTHOR Jaldhar H. Vyas E<lt>jaldhar@braincells.comE<gt> =head1 THANKS Urban Mueller - The inventor of Brainfck. Damian Conway - For twisting perl to hitherto unimaginable heights of weirdness. Marco Nippula E<lt>http://www.hut.fi/~mnippula/E<gt> - Some code in th +is module comes from his F<brainfck.pl> Mr. Rock - Who has a nice Brainfck tutorial at L<http://www.cydathria.com/bf/>. Some of the example code comes from +there. =head1 COPYRIGHT AND LICENSE Copyright (c) 2002, Consolidated Braincells Inc. Licensed with no warranties under the Crowley Public License: "Do what thou wilt shall be the whole of the license." =cut

--
જલધર

Replies are listed 'Best First'.
Re: Inline::Brainfck
by Abigail-II (Bishop) on Aug 29, 2002 at 14:09 UTC
    Hmmm. The nicety of other Inline:: modules is that you can put the source of the other language at either the use statement, or after a __Language__ tag. The you program normal Perl, and just call the routines like you would call any other Perl routine.

    Your module doesn't do that. Therefore I think it shouldn't be part of the Inline:: hierarchy; perhaps Acme::Brainfuck?

    Abigail

      Hmmm. The nicety of other Inline:: modules is that you can put the source of the other language at either the use statement, or after a __Language__ tag. The you program normal Perl, and just call the routines like you would call any other Perl routine.
      Your module doesn't do that. Therefore I think it shouldn't be part of the Inline:: hierarchy; perhaps Acme::Brainfuck?


      Acme is certainly a fine namespace. Any module would be proud to be in it but I would like to try adding the features you mentioned. __Brainfck__ I could probable manage if I squint at the Filter::Simple man page long enough but how would I go about implementing the other thing?

      --
      જલધર

        You could start by studying the Inline-API man page.

        Abigail

      Also, making this a filter and having the ablity to mix perl and brainf*ck isn't really well-implemented -- using any of the BF keywords in the perl code will do unexpected things -- using the Inline API will fix that. (You could also require some sort of delimiter around the BF code, like ({{ }}) that are unlikely to occour in perl code, but that's a hack, IMHO, and not as cool as a real Inline module.)


      Confession: It does an Immortal Body good.

        Also, making this a filter and having the ablity to mix perl and brainf*ck isn't really well-implemented -- using any of the BF keywords in the perl code will do unexpected things -- using the Inline API will fix that. (You could also require some sort of delimiter around the BF code, like ({{ }}) that are unlikely to occour in perl code, but that's a hack, IMHO, and not as cool as a real Inline module.)


        How so? I do have delimiters—whitespace. So something like: ++$a = ++ ; will do the right thing. I agree the Inline modules are cool. Unfortunately using the API will need a huge rewrite so it will be Acme::Brainfck (plus the u.) I'm thinking of doing a proper Inline:: version after I'm done with this.


        --
        જલધર

Re: Inline::Brainfuck
by moxliukas (Curate) on Aug 29, 2002 at 13:33 UTC

    Nice work.

    I have been toying with Brainf*ck too and here are my comments about this particular interpretation:

    • I really don't like the '#' operator. It is against the Brainf*ck nature. Brainf*ck is supposed to be difficult to write and making the coding tools like '#' available is going to make Brainf*ck way too easy to program. Imagine all these 13-year-olds coding Brainf*ck straight after they have grasped Basic... definately something we do not want. Brainf*ck has been a language for those elite few who have enough stupidity and stubborness to spend about an hour to write a simple Hello, World!. Brainf*ck has been the language of die-hard brainfuckers like me since 1993 and the whole purpose of the language is that it should be difficult to write in. Dumping the memory array is for wimps. Next you will want a simple way to reset the whole memory array...oh wait... you HAVE done this with '~' operator... Where is the world coming to?
    • The '~' operator also is useless and just adds syntactic sugar and makes the language more complicated than it should be. I mean you can easily erase the contents of the memory cell by a simple [-] so there is no need to reinvent the wheel especially when tools in the Brainf*ck language are available itself and there is no need to add these new features. Again, it makes programming Brainf*ck way too easy...
    • No support for nested loops. This is a big one. As far as I can see there is no support for nested loops in your implementation (or am I wrong?). Nesting loops within loops and trying to remember where the loop counters are and *NOT* being able to print the memory array is the sort of thing that makes Brainf*ck the language fun for real programmers.

    OK, enough ranting. Good job! ;)

      • I really don't like the '#' operator. It is against the Brainf*ck nature. Brainf*ck is supposed to be difficult to write and making the coding tools like '#' available is going to make Brainf*ck way too easy to program. Imagine all these 13-year-olds coding Brainf*ck straight after they have grasped Basic... definately something we do not want. Brainf*ck has been a language for those elite few who have enough stupidity and stubborness to spend about an hour to write a simple Hello, World!. Brainf*ck has been the language of die-hard brainfuckers like me since 1993 and the whole purpose of the language is that it should be difficult to write in. Dumping the memory array is for wimps. Next you will want a simple way to reset the whole memory array...oh wait... you HAVE done this with '~' operator... Where is the world coming to?
      • The '~' operator also is useless and just adds syntactic sugar and makes the language more complicated than it should be. I mean you can easily erase the contents of the memory cell by a simple - so there is no need to reinvent the wheel especially when tools in the Brainf*ck language are available itself and there is no need to add these new features. Again, it makes programming Brainf*ck way too easy...

      • I hear what you're saying. That's why I made the extra instructions entirely optional and only switched on by a special pragma. # I've seen in other implementations. At least one web page says it is a "common" extension. As I wanted to try out implementing pragmas, it seemed like a good one. ~ I agree is just sugar. It was implemented for the same reasons as above. But like I said, its' all optional. Btw I'm also thinking about adding ` as an optional comment character (i.e ignore everything from there up to the end of the line.) How's that for blasphemy? :-)


        No support for nested loops. This is a big one. As far as I can see there is no support for nested loops in your implementation (or am I wrong?).


        Tell me more. How would you want that to work? Some sort of stack? Labels?

        --
        જલધર

        Nested Brainf*ck loops can be used like this:

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

        Which in this case is only a fancy way of writting

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

        Both of these should print "BF".

        On a closer look at your code I think nested loops are indeed supported however I am having trouble with installing Filter::Simple so I cannot check.

        Regarding comments and ` operator: to my understanding anything that is not a Brainf*ck operator (that is not in the []-+,.<> set) is automatically treated as a comment and is silently ignored (this lets you have Brainf*ck code span a couple lines rather than being on one long line). Of course the philosophy should say that Brainf*ck code should not be commented at all because if it was difficult to write it must be difficult to read ;)

Re: Inline::Brainfuck
by jaldhar (Vicar) on Aug 29, 2002 at 12:40 UTC

    Change: fixed incorrect code.

    Bah. I just discovered this thread which includes a Brainfuck interpreter and a link to another Inline::Brainfuck module. Mine isn't redundant however because it has more features and uses the cool source filtering abilities of recent versions of perl. (Now standard in 5.8.0) It also integrates better into perl IMHO as you can assign brainfuck code to a variable etc.

    I'm working this up into a proper CPAN module but before I do so, I need some advice. I would like to add some optimization i.e right now

    +++++
    becomes
    P++; P++; P++; P++; P++;
    when it should be
    P += 5;
    etc. What would be a good way of doing that with just regexes?

    --
    જલધર

      First, let me say you're a sick, sick being for thinking of this. Good work! :)

      Change the line that reads

      $code =~ s/\+/P++; /g;
      To read:
      $code =~ s/(\++)/"P+=".length($1).";" /eg;
      You can probably do the same for \-, I'd think:
      $code =~ s/(\-+)/"P-=".length($1).";" /eg;
      By the way, wouldn't + become P++, and not $Inline::Brainfuck::p++? Maybe I'm reading your filter wrong...

      I'm guessing the same technique would apply to the < and > filters, too.
      --
      Mike

      Edit: By the way, I frontpaged this thread, THEN he posted a question I could answer. Normally, I wouldn't front page a thread I'm going to participate in.
      Edit 2: Made node title more firewall friendly

        Change the line that reads

        $code =~ s/\+/P++; /g;
        To read:
        $code =~ s/(\++)/"P+=".length($1).";" /eg;


        Ah I think I forgot the e when I tried this before. Thanks.


        By the way, wouldn't + become P++, and not $Inline::Brainfuck::p++?


        Yes you're right.

        --
        જલધર

Re: Inline::Brainfck
by cybear (Monk) on Aug 29, 2002 at 14:15 UTC
    You have an interesting point. It seems that the most popular solutions, with management types, tend to be WAY complicated.

    - cybear

Re: Inline::Brainwarp
by tbone1 (Monsignor) on Aug 29, 2002 at 13:02 UTC
    Given that some of us read through corporate firewalls, might I request (though not demand) that you call this Brainwarp or Brainspasm instead? It is your call, of course, but I merely ask, politely, for consideration.

    --
    tbone1
    As God is my witness, I thought turkeys could fly.

      I thought about this. I'm against the gratuitous use of vulgarity myself however this is the actual name of the language and it is widely known as such. I didn't consider that people would be reading this from restricted environments though so to be acommodating, I've changed it here to Brainfck. The CPAN module will be named in all its' uncensored glory.

      --
      જલધર

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: CUFP [id://193742]
Front-paged by RMGir
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (3)
As of 2024-04-20 03:38 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found