Skip to content

Commit

Permalink
First working version
Browse files Browse the repository at this point in the history
  • Loading branch information
zoffixznet committed Jan 24, 2016
1 parent 6c448e2 commit 4e7a673
Show file tree
Hide file tree
Showing 11 changed files with 167 additions and 100 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
lib/.precomp
test.p6
3 changes: 2 additions & 1 deletion META.info → META6.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"name" : "Inline::Brainfuck",
"version" : "1.001001",
"description" : "Use Brainfuck language in your Perl 6 programs",
"test-depends" : [ "Test" ],
"depends" : [ "Term::termios" ],
"test-depends" : [ "Test", "Test::Output" ],
"provides" : {
"Inline::Brainfuck" : "lib/Inline/Brainfuck.pm6"
},
Expand Down
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,29 @@ Inline::Brainfuck - Use Brainfuck language in your Perl 6 programs
# SYNOPSIS

```perl6
use lib 'lib';
use Inline::Brainfuck;

brainfuck '++++++++++ ++++++++++ ++++++++++ +++.'; # prints "!"
```

# DESCRIPTION

This module provides a subroutine that takes a string with
[Brainfuck code](https://en.wikipedia.org/wiki/Brainfuck) and executes it.

# EXPORTED SUBROUTINES

## `brainfuck`

```perl6
brainfuck '++++++++++ ++++++++++ ++++++++++ +++.'; # prints "!"
```

Takes an `Str` with Brainfuck code to execute. Input will be read
from STDIN. The terminal will be switched to non-buffered mode, so any input
will be processed immediatelly, per-character. Output will be sent to STDOUT.

----

# REPOSITORY
Expand Down
2 changes: 2 additions & 0 deletions examples/brainfuckit.p6
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@

use lib 'lib';
use Inline::Brainfuck;

brainfuck 't/bf-programs/hello-world.bf'.IO.slurp;
62 changes: 58 additions & 4 deletions lib/Inline/Brainfuck.pm6
Original file line number Diff line number Diff line change
@@ -1,7 +1,61 @@
unit class Inline::Brainfuck;
unit module Inline::Brainfuck:ver<1.001001>;
use Term::termios;

has $!state = Inline::Brainfuck::State.new;
sub brainfuck (Str:D $code) is export {
check-matching-loop $code;
my $saved-term;
try {
$saved-term = Term::termios.new(:1fd).getattr;
given Term::termios.new(:1fd).getattr {
.makeraw;
.setattr(:DRAIN);
}
};
LEAVE { try $saved-term.setattr(:DRAIN) }

method run (Str:D $code) {
$code.subst-mutate: /<-[-<>+.,[\]]>/, '', :g;
my @code = $code.comb: /<[-<\>+.,[\]]>/;
my $ = 0;
my $cursor = 0;
my $stack = Buf[uint8].new: 0;
loop {
given @code[$cursor] {
when '>' { $stack.append: 0 if $stack.elems == ++$; }
when '<' { $--; fail "Negative cell pointer\n" if $ < 0; }
when '+' { $stack[$]++; }
when '-' { $stack[$]--; }
when '.' { $stack[$].chr.print; }
when ',' { $stack[$] = $*IN.getc.ord; }
when '[' {
$cursor++; next if $stack[$];
loop {
state $level = 1;
$level++ if @code[$cursor] eq '[';
$level-- if @code[$cursor] eq ']';
last unless $level;
$cursor++;
}
}
when ']' {
unless $stack[$] { $cursor++; next }
loop {
state $level = 1;
$cursor--;
$level-- if @code[$cursor] eq '[';
$level++ if @code[$cursor] eq ']';
last unless $level;
}
}
}
last if ++$cursor > @code.elems;
}
}

sub check-matching-loop ($code) {
my $level = 0;
for $code.comb {
$level++ if $_ eq '[';
$level-- if $_ eq ']';
fail qq{Closing "]" found without matching "["\n} if $level < 0;
LAST { fail 'Unmatched [ ]' if $level > 0 }
}
}
94 changes: 0 additions & 94 deletions lib/Inline/Brainfuck/Grammar.pm6

This file was deleted.

1 change: 0 additions & 1 deletion lib/Inline/Brainfuck/State.pm6

This file was deleted.

18 changes: 18 additions & 0 deletions t/01-output.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!perl6

use lib 'lib';
use Test;
use Test::Output;
use Inline::Brainfuck;

output-is {
brainfuck '++++++++++ ++++++++++ ++++++++++ ++++++++++'
~ '++++++++++ ++++++++++ ++++++++++ ++.';
}, "H", 'Output letter "H"';

output-is {
brainfuck 't/bf-programs/hello-world.bf'.IO.slurp;
}, "Hello World!\n", 'Hello world! program works';


done-testing;
21 changes: 21 additions & 0 deletions t/02-input-test.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!perl6

use lib 'lib';
use Test;
use Test::Output;
use Inline::Brainfuck;

unless %*ENV<INTERACTIVE_TESTING> {
diag "INTERACTIVE_TESTING env var not set. Skipping this test";
done-testing;
exit;
}

diag 'Type word "test" (press ENTER if nothing happens right after you type it)';

output-is {
brainfuck 't/bf-programs/input1.bf'.IO.slurp;
}, "test", 'input -> output program works';


done-testing;
43 changes: 43 additions & 0 deletions t/bf-programs/hello-world.bf
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
[ This program prints "Hello World!" and a newline to the screen, its
length is 106 active command characters. [It is not the shortest.]
This loop is a "comment loop", a simple way of adding a comment
to a BF program such that you don't have to worry about any command
characters. Any ".", ",", "+", "-", "<" and ">" characters are simply
ignored, the "[" and "]" characters just have to be balanced. This
loop and the commands it contains are ignored because the current cell
defaults to a value of 0; the 0 value causes this loop to be skipped.
]
+++++ +++ Set Cell #0 to 8
[
>++++ Add 4 to Cell #1; this will always set Cell #1 to 4
[ as the cell will be cleared by the loop
>++ Add 2 to Cell #2
>+++ Add 3 to Cell #3
>+++ Add 3 to Cell #4
>+ Add 1 to Cell #5
<<<<- Decrement the loop counter in Cell #1
] Loop till Cell #1 is zero; number of iterations is 4
>+ Add 1 to Cell #2
>+ Add 1 to Cell #3
>- Subtract 1 from Cell #4
>>+ Add 1 to Cell #6
[<] Move back to the first zero cell you find; this will
be Cell #1 which was cleared by the previous loop
<- Decrement the loop Counter in Cell #0
] Loop till Cell #0 is zero; number of iterations is 8
The result of this is:
Cell No : 0 1 2 3 4 5 6
Contents: 0 0 72 104 88 32 8
Pointer : ^
>>. Cell #2 has value 72 which is 'H'
>---. Subtract 3 from Cell #3 to get 101 which is 'e'
+++++++..+++. Likewise for 'llo' from Cell #3
>>. Cell #5 is 32 for the space
<-. Subtract 1 from Cell #4 for 87 to give a 'W'
<. Cell #3 was set to 'o' from the end of 'Hello'
+++.------.--------. Cell #3 for 'rl' and 'd'
>>+. Add 1 to Cell #5 gives us an exclamation point
>++. And finally a newline from Cell #6
3 changes: 3 additions & 0 deletions t/bf-programs/input1.bf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
,>,>,>, # Read in word "test"
<<< # Rewind back to start
.>.>.>. # Print word test back

0 comments on commit 4e7a673

Please sign in to comment.