brainfuck 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +2 -0
- data/Gemfile.lock +8 -23
- data/Rakefile +12 -10
- data/Readme.md +17 -11
- data/bin/brainfuck +1 -1
- data/brainfuck.gemspec +5 -6
- data/lib/brainfuck.rb +5 -18
- data/lib/brainfuck/ast.rb +126 -18
- data/lib/brainfuck/code_loader.rb +31 -0
- data/lib/brainfuck/compiler.rb +81 -0
- data/lib/brainfuck/lexer.rb +32 -0
- data/lib/brainfuck/main.rb +99 -0
- data/lib/brainfuck/parser.rb +9 -24
- data/lib/brainfuck/stages.rb +170 -0
- data/lib/brainfuck/version.rb +1 -1
- data/test/acceptance/acceptance_test.rb +75 -0
- data/test/brainfuck/ast_test.rb +7 -0
- data/test/brainfuck/lexer_test.rb +21 -0
- data/test/brainfuck/parser_test.rb +16 -0
- data/test/test_helper.rb +10 -0
- metadata +32 -53
- data/lib/brainfuck/interpreter.rb +0 -20
- data/lib/brainfuck/stack.rb +0 -51
- data/spec/acceptance/acceptance_spec.rb +0 -105
- data/spec/brainfuck/ast_spec.rb +0 -36
- data/spec/brainfuck/interpreter_spec.rb +0 -25
- data/spec/brainfuck/parser_spec.rb +0 -27
- data/spec/brainfuck/stack_spec.rb +0 -81
- data/spec/brainfuck_spec.rb +0 -23
- data/spec/spec_helper.rb +0 -18
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Brainfuck
|
4
|
+
class ParserTest < MiniTest::Unit::TestCase
|
5
|
+
|
6
|
+
%w{fwd bwd inc dec puts gets iteration exp}.each do |rule|
|
7
|
+
define_method "test_implements_a_#{rule}_rule" do
|
8
|
+
rules = Parser.rules.map(&:first).map do |pattern|
|
9
|
+
pattern.instance_variable_get(:@pattern)
|
10
|
+
end.map(&:keys).flatten
|
11
|
+
assert_includes rules, rule.to_sym
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: brainfuck
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 23
|
5
|
+
prerelease:
|
5
6
|
segments:
|
6
7
|
- 0
|
7
|
-
- 1
|
8
8
|
- 2
|
9
|
-
|
9
|
+
- 0
|
10
|
+
version: 0.2.0
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- Josep M. Bach
|
@@ -14,75 +15,52 @@ autorequire:
|
|
14
15
|
bindir: bin
|
15
16
|
cert_chain: []
|
16
17
|
|
17
|
-
date: 2011-
|
18
|
+
date: 2011-05-16 00:00:00 +02:00
|
18
19
|
default_executable:
|
19
20
|
dependencies:
|
20
21
|
- !ruby/object:Gem::Dependency
|
21
|
-
name:
|
22
|
+
name: parslet
|
22
23
|
prerelease: false
|
23
24
|
requirement: &id001 !ruby/object:Gem::Requirement
|
24
25
|
none: false
|
25
26
|
requirements:
|
26
27
|
- - ">="
|
27
28
|
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
28
30
|
segments:
|
29
31
|
- 0
|
30
32
|
version: "0"
|
31
33
|
type: :runtime
|
32
34
|
version_requirements: *id001
|
33
35
|
- !ruby/object:Gem::Dependency
|
34
|
-
name:
|
36
|
+
name: minitest
|
35
37
|
prerelease: false
|
36
38
|
requirement: &id002 !ruby/object:Gem::Requirement
|
37
39
|
none: false
|
38
40
|
requirements:
|
39
41
|
- - ">="
|
40
42
|
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
41
44
|
segments:
|
42
45
|
- 0
|
43
46
|
version: "0"
|
44
|
-
type: :
|
47
|
+
type: :development
|
45
48
|
version_requirements: *id002
|
46
49
|
- !ruby/object:Gem::Dependency
|
47
|
-
name:
|
50
|
+
name: mocha
|
48
51
|
prerelease: false
|
49
52
|
requirement: &id003 !ruby/object:Gem::Requirement
|
50
53
|
none: false
|
51
54
|
requirements:
|
52
55
|
- - ">="
|
53
56
|
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
54
58
|
segments:
|
55
59
|
- 0
|
56
60
|
version: "0"
|
57
61
|
type: :development
|
58
62
|
version_requirements: *id003
|
59
|
-
|
60
|
-
name: bundler
|
61
|
-
prerelease: false
|
62
|
-
requirement: &id004 !ruby/object:Gem::Requirement
|
63
|
-
none: false
|
64
|
-
requirements:
|
65
|
-
- - ">="
|
66
|
-
- !ruby/object:Gem::Version
|
67
|
-
segments:
|
68
|
-
- 0
|
69
|
-
version: "0"
|
70
|
-
type: :development
|
71
|
-
version_requirements: *id004
|
72
|
-
- !ruby/object:Gem::Dependency
|
73
|
-
name: simplecov
|
74
|
-
prerelease: false
|
75
|
-
requirement: &id005 !ruby/object:Gem::Requirement
|
76
|
-
none: false
|
77
|
-
requirements:
|
78
|
-
- - ">="
|
79
|
-
- !ruby/object:Gem::Version
|
80
|
-
segments:
|
81
|
-
- 0
|
82
|
-
version: "0"
|
83
|
-
type: :development
|
84
|
-
version_requirements: *id005
|
85
|
-
description: Another Brainfuck interpreter in Ruby
|
63
|
+
description: An implementation of Brainfuck on the Rubinius VM.
|
86
64
|
email:
|
87
65
|
- josep.m.bach@gmail.com
|
88
66
|
executables:
|
@@ -104,17 +82,18 @@ files:
|
|
104
82
|
- examples/hello_world.bf
|
105
83
|
- lib/brainfuck.rb
|
106
84
|
- lib/brainfuck/ast.rb
|
107
|
-
- lib/brainfuck/
|
85
|
+
- lib/brainfuck/code_loader.rb
|
86
|
+
- lib/brainfuck/compiler.rb
|
87
|
+
- lib/brainfuck/lexer.rb
|
88
|
+
- lib/brainfuck/main.rb
|
108
89
|
- lib/brainfuck/parser.rb
|
109
|
-
- lib/brainfuck/
|
90
|
+
- lib/brainfuck/stages.rb
|
110
91
|
- lib/brainfuck/version.rb
|
111
|
-
-
|
112
|
-
-
|
113
|
-
-
|
114
|
-
-
|
115
|
-
-
|
116
|
-
- spec/brainfuck_spec.rb
|
117
|
-
- spec/spec_helper.rb
|
92
|
+
- test/acceptance/acceptance_test.rb
|
93
|
+
- test/brainfuck/ast_test.rb
|
94
|
+
- test/brainfuck/lexer_test.rb
|
95
|
+
- test/brainfuck/parser_test.rb
|
96
|
+
- test/test_helper.rb
|
118
97
|
has_rdoc: true
|
119
98
|
homepage: http://github.com/txus/brainfuck
|
120
99
|
licenses: []
|
@@ -129,6 +108,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
129
108
|
requirements:
|
130
109
|
- - ">="
|
131
110
|
- !ruby/object:Gem::Version
|
111
|
+
hash: 3
|
132
112
|
segments:
|
133
113
|
- 0
|
134
114
|
version: "0"
|
@@ -137,21 +117,20 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
137
117
|
requirements:
|
138
118
|
- - ">="
|
139
119
|
- !ruby/object:Gem::Version
|
120
|
+
hash: 3
|
140
121
|
segments:
|
141
122
|
- 0
|
142
123
|
version: "0"
|
143
124
|
requirements: []
|
144
125
|
|
145
126
|
rubyforge_project: brainfuck
|
146
|
-
rubygems_version: 1.
|
127
|
+
rubygems_version: 1.5.2
|
147
128
|
signing_key:
|
148
129
|
specification_version: 3
|
149
|
-
summary:
|
130
|
+
summary: An implementation of Brainfuck on the Rubinius VM.
|
150
131
|
test_files:
|
151
|
-
-
|
152
|
-
-
|
153
|
-
-
|
154
|
-
-
|
155
|
-
-
|
156
|
-
- spec/brainfuck_spec.rb
|
157
|
-
- spec/spec_helper.rb
|
132
|
+
- test/acceptance/acceptance_test.rb
|
133
|
+
- test/brainfuck/ast_test.rb
|
134
|
+
- test/brainfuck/lexer_test.rb
|
135
|
+
- test/brainfuck/parser_test.rb
|
136
|
+
- test/test_helper.rb
|
@@ -1,20 +0,0 @@
|
|
1
|
-
module Brainfuck
|
2
|
-
class Interpreter < Parslet::Transform
|
3
|
-
def self.stack
|
4
|
-
@@stack ||= Stack.new
|
5
|
-
end
|
6
|
-
|
7
|
-
rule(:fwd => simple(:fwd)) { AST::FwdNode.new(Interpreter.stack) }
|
8
|
-
rule(:bwd => simple(:bwd)) { AST::BwdNode.new(Interpreter.stack) }
|
9
|
-
|
10
|
-
rule(:inc => simple(:inc)) { AST::IncNode.new(Interpreter.stack) }
|
11
|
-
rule(:dec => simple(:dec)) { AST::DecNode.new(Interpreter.stack) }
|
12
|
-
|
13
|
-
rule(:puts => simple(:puts)) { AST::PutsNode.new(Interpreter.stack) }
|
14
|
-
rule(:gets => simple(:gets)) { AST::GetsNode.new(Interpreter.stack) }
|
15
|
-
|
16
|
-
rule(:iteration => subtree(:iteration)) { AST::IterationNode.new(Interpreter.stack, iteration) }
|
17
|
-
|
18
|
-
rule(:exp => subtree(:exp)) { exp }
|
19
|
-
end
|
20
|
-
end
|
data/lib/brainfuck/stack.rb
DELETED
@@ -1,51 +0,0 @@
|
|
1
|
-
module Brainfuck
|
2
|
-
class Stack
|
3
|
-
include HighLine::SystemExtensions
|
4
|
-
|
5
|
-
attr_reader :current
|
6
|
-
def initialize
|
7
|
-
@pointer = 0
|
8
|
-
@stack = [0]
|
9
|
-
end
|
10
|
-
def current
|
11
|
-
@stack[@pointer]
|
12
|
-
end
|
13
|
-
def fwd
|
14
|
-
@pointer += 1
|
15
|
-
initialize_cell_if_nil
|
16
|
-
end
|
17
|
-
def bwd
|
18
|
-
@pointer -= 1
|
19
|
-
ensure_pointer_is_above_zero
|
20
|
-
initialize_cell_if_nil
|
21
|
-
end
|
22
|
-
def inc
|
23
|
-
@stack[@pointer] = (current + 1) % 255
|
24
|
-
end
|
25
|
-
def dec
|
26
|
-
@stack[@pointer] = (current - 1) % 255
|
27
|
-
end
|
28
|
-
def puts
|
29
|
-
$stdout.print current.chr
|
30
|
-
end
|
31
|
-
def gets
|
32
|
-
@stack[@pointer] = (get_character % 255) rescue 0
|
33
|
-
end
|
34
|
-
|
35
|
-
def to_a
|
36
|
-
@stack
|
37
|
-
end
|
38
|
-
|
39
|
-
def clear
|
40
|
-
initialize
|
41
|
-
end
|
42
|
-
|
43
|
-
private
|
44
|
-
def initialize_cell_if_nil
|
45
|
-
@stack[@pointer] ||= 0
|
46
|
-
end
|
47
|
-
def ensure_pointer_is_above_zero
|
48
|
-
raise "Tried to access cell #{@pointer}." if @pointer < 0
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
@@ -1,105 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module Brainfuck
|
4
|
-
describe "Acceptance specs" do
|
5
|
-
|
6
|
-
subject { Brainfuck }
|
7
|
-
|
8
|
-
describe "without loops nor user input" do
|
9
|
-
let(:code) do
|
10
|
-
<<-EOS
|
11
|
-
++++>++++---.<--.
|
12
|
-
EOS
|
13
|
-
end
|
14
|
-
it "sets two cells to 2 and 1" do
|
15
|
-
subject.run(code).should == [2,1]
|
16
|
-
end
|
17
|
-
it "prints 2 and 1" do
|
18
|
-
$stdout.should_receive(:print).twice
|
19
|
-
subject.run code
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
describe "with user input" do
|
24
|
-
let(:code) do
|
25
|
-
<<-EOS
|
26
|
-
,++++
|
27
|
-
EOS
|
28
|
-
end
|
29
|
-
it "sets the first cell to a + 4" do
|
30
|
-
stack = Stack.new
|
31
|
-
Interpreter.stub(:stack).and_return stack
|
32
|
-
|
33
|
-
stack.should_receive(:get_character).once.and_return 97
|
34
|
-
|
35
|
-
subject.run(code).should == [101]
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
describe "with loops" do
|
40
|
-
let(:code) do
|
41
|
-
<<-EOS
|
42
|
-
++++[-]+-+
|
43
|
-
EOS
|
44
|
-
end
|
45
|
-
it "runs the loop 4 times" do
|
46
|
-
subject.run(code).should == [1]
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
describe "cell hopping examples" do
|
51
|
-
|
52
|
-
it "transfers the content from one cell to another" do
|
53
|
-
subject.run("++++++++++ [>+<-]").should == [0,10]
|
54
|
-
end
|
55
|
-
|
56
|
-
it "transfers the content from one cell to the third" do
|
57
|
-
subject.run("++++++++++ [>+<-]>[>+<-]").should == [0,0,10]
|
58
|
-
end
|
59
|
-
|
60
|
-
it "transfers the content from one cell to the third and back to the second" do
|
61
|
-
subject.run("++++++++++ [>+<-]>[>+<-]>[<+>-]").should == [0,10,0]
|
62
|
-
end
|
63
|
-
|
64
|
-
end
|
65
|
-
|
66
|
-
describe "nested loop examples" do
|
67
|
-
|
68
|
-
it "work flawlessly" do
|
69
|
-
subject.run("[++++++++++[-]+-+-]").should == [0]
|
70
|
-
end
|
71
|
-
|
72
|
-
end
|
73
|
-
|
74
|
-
describe "hello world" do
|
75
|
-
|
76
|
-
it "displays hello world" do
|
77
|
-
subject.run <<-EOS
|
78
|
-
+++++ +++++
|
79
|
-
[
|
80
|
-
> +++++ ++
|
81
|
-
> +++++ +++++
|
82
|
-
> +++
|
83
|
-
> +
|
84
|
-
<<<< -
|
85
|
-
]
|
86
|
-
> ++ .
|
87
|
-
> + .
|
88
|
-
+++++ ++ .
|
89
|
-
.
|
90
|
-
+++ .
|
91
|
-
> ++ .
|
92
|
-
<< +++++ +++++ +++++ .
|
93
|
-
> .
|
94
|
-
+++ .
|
95
|
-
----- - .
|
96
|
-
----- --- .
|
97
|
-
> + .
|
98
|
-
> .
|
99
|
-
EOS
|
100
|
-
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
end
|
105
|
-
end
|
data/spec/brainfuck/ast_spec.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module Brainfuck
|
4
|
-
describe AST do
|
5
|
-
let(:stack) { double('stack') }
|
6
|
-
|
7
|
-
%w{fwd bwd inc dec puts gets}.each do |node|
|
8
|
-
describe "AST::#{node.capitalize}Node" do
|
9
|
-
subject { eval("AST::#{node.capitalize}Node").new stack }
|
10
|
-
describe "#eval" do
|
11
|
-
it "calls stack##{node}" do
|
12
|
-
subject.stack.should_receive(node)
|
13
|
-
subject.eval
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
describe AST::IterationNode do
|
20
|
-
let(:nodes) do
|
21
|
-
[ double('node'), double('node2') ]
|
22
|
-
end
|
23
|
-
subject { AST::IterationNode.new stack, nodes }
|
24
|
-
describe "#eval" do
|
25
|
-
it 'evaluates the expression until the stack cell is 0' do
|
26
|
-
subject.stack.stub(:current).and_return 3, 2, 1, 0
|
27
|
-
nodes.each do |node|
|
28
|
-
node.should_receive(:eval).exactly(3).times
|
29
|
-
end
|
30
|
-
subject.eval
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
end
|
36
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module Brainfuck
|
4
|
-
describe Interpreter do
|
5
|
-
|
6
|
-
describe ".stack" do
|
7
|
-
it 'returns a new or cached Stack' do
|
8
|
-
stack = Interpreter.stack
|
9
|
-
stack.should be_kind_of(Stack)
|
10
|
-
Interpreter.stack.should === stack
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
describe "rules" do
|
15
|
-
%w{fwd bwd inc dec puts gets iteration exp}.each do |rule|
|
16
|
-
it "implements a rule for :#{rule} node" do
|
17
|
-
subject.rules.map(&:first).map do |pattern|
|
18
|
-
pattern.instance_variable_get(:@pattern)
|
19
|
-
end.map(&:keys).flatten.should include(:"#{rule}")
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
end
|
25
|
-
end
|
@@ -1,27 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module Brainfuck
|
4
|
-
describe Parser do
|
5
|
-
|
6
|
-
describe "INSTRUCTIONS constant" do
|
7
|
-
it 'returns valid symbols' do
|
8
|
-
Parser::INSTRUCTIONS.should == %w{> < + - [ ] . ,}
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
describe ".clean" do
|
13
|
-
it 'cleans all non-valid symbols from a string' do
|
14
|
-
Parser.clean(">3< 223+fn - ()()[r23-] .bdn*& ,").should == '><+-[-].,'
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
describe "rules" do
|
19
|
-
%w{lparen rparen space space? fwd bwd inc dec puts gets iteration expression}.each do |rule|
|
20
|
-
it "implements a rule for :#{rule} node" do
|
21
|
-
subject.should respond_to(:"#{rule}")
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
end
|
27
|
-
end
|