brainfuck 0.0.1 → 0.1.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 CHANGED
@@ -1,3 +1,4 @@
1
1
  pkg/*
2
2
  *.gem
3
3
  .bundle
4
+ coverage
@@ -1,14 +1,18 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- brainfuck (0.0.1)
4
+ brainfuck (0.1.0)
5
5
  highline
6
+ parslet
6
7
 
7
8
  GEM
8
9
  remote: http://rubygems.org/
9
10
  specs:
11
+ blankslate (2.1.2.3)
10
12
  diff-lcs (1.1.2)
11
13
  highline (1.6.1)
14
+ parslet (1.0.0)
15
+ blankslate (~> 2.1.2.3)
12
16
  rspec (2.2.0)
13
17
  rspec-core (~> 2.2)
14
18
  rspec-expectations (~> 2.2)
@@ -29,5 +33,6 @@ DEPENDENCIES
29
33
  brainfuck!
30
34
  bundler
31
35
  highline
36
+ parslet
32
37
  rspec
33
38
  simplecov
data/Readme.md CHANGED
@@ -2,22 +2,20 @@
2
2
 
3
3
  Just another Brainfuck interpreter in Ruby!
4
4
  (If you don't know what Brainfuck is, you definitely
5
- [should][http://en.wikipedia.org/wiki/Brainfuck]).
5
+ [should](http://en.wikipedia.org/wiki/Brainfuck)).
6
6
 
7
7
  This interpreter works with MRI 1.8.7, 1.9.2 and JRuby 1.5.5.
8
8
 
9
- ## Known caveats (yes, before anything)
9
+ ## UPDATE: Known caveats solved since 0.1.0!
10
10
 
11
- Ok, I admit it. Nested loops don't work in an extremely reliable manner, so to
12
- speak. I suggest you NOT TO USE THIS IN PRODUCTION APPS. Yes, forget about
13
- using this interpreter for that high-security online payment system you wrote in Brainfuck.
14
-
15
- Oh and why are nested loops tricky with this interpreter? I was tired and Civilization 5
16
- was installed in my laptop and... You know, forks and pull requests are always welcome! :)
11
+ Thanks to a complete rewrite using Kaspar Schiess' `parslet` (which you should
12
+ definitely [check it out](http://github.com/kschiess/parslet)) nested loops
13
+ work flawlessly. So yes, you can now run that high-security online payment
14
+ system you wrote in Brainfuck :)
17
15
 
18
16
  ## Installation and usage
19
17
 
20
- You just `gem install brainfuck`!
18
+ You just `gem install brainfuck` (or `gem 'brainfuck'` in your Gemfile)!
21
19
 
22
20
  And then: `brainfuck my_file.bf`
23
21
 
@@ -25,14 +23,9 @@ You can also require the gem and use inline brainfuck in your ruby scripts like
25
23
 
26
24
  require 'brainfuck'
27
25
 
28
- interpreter = Brainfuck.new
29
- interpreter.compile "+++>+++<---"
30
-
31
- interpreter.cells
26
+ Brainfuck.run "+++>+++<---"
32
27
  # => [0, 3]
33
28
 
34
- It's very basic, and needs *a lot* of refactoring, but for now... there you go! ;)
35
-
36
29
  ## Note on Patches/Pull Requests
37
30
 
38
31
  * Fork the project.
@@ -46,4 +39,4 @@ It's very basic, and needs *a lot* of refactoring, but for now... there you go!
46
39
 
47
40
  ## Copyright
48
41
 
49
- Copyright (c) 2010 Josep M. Bach. See LICENSE for details.
42
+ Copyright (c) 2011 Josep M. Bach. See LICENSE for details.
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'brainfuck'
3
- Brainfuck::Interpreter.new.compile File.read(ARGV.first)
3
+ Brainfuck.run File.read(ARGV.first)
@@ -15,6 +15,7 @@ Gem::Specification.new do |s|
15
15
  s.rubyforge_project = "brainfuck"
16
16
 
17
17
  s.add_runtime_dependency "highline"
18
+ s.add_runtime_dependency "parslet"
18
19
  s.add_development_dependency "rspec"
19
20
  s.add_development_dependency "bundler"
20
21
  s.add_development_dependency "simplecov"
@@ -1,102 +1,22 @@
1
+ require 'parslet'
1
2
  require 'highline/system_extensions'
2
3
 
3
- module Brainfuck
4
- class Interpreter
5
- include HighLine::SystemExtensions
6
-
7
- INSTRUCTIONS = %w{> < + - [ ] . ,}
8
-
9
- attr_accessor :cells
10
- attr_reader :pointer
11
- attr_reader :code
12
-
13
- def initialize
14
- @cells = [0]
15
- @pointer = 0
16
- @code = nil
17
- end
18
-
19
- def current
20
- @cells[pointer] ||= 0
21
- end
22
- def current=(value)
23
- @cells[pointer] = (value % 255) rescue 0
24
- end
4
+ require 'brainfuck/stack'
5
+ require 'brainfuck/ast'
25
6
 
26
- def forward
27
- @pointer += 1
28
- initialize_cell_if_nil
29
- end
30
- def backward
31
- @pointer -= 1
32
- ensure_pointer_is_above_zero
33
- initialize_cell_if_nil
34
- end
35
- def increase
36
- @cells[pointer] = (@cells[pointer] + 1) % 255
37
- end
38
- def decrease
39
- @cells[pointer] = (@cells[pointer] - 1) % 255
40
- end
41
-
42
- def compile(code)
43
- @code = clean(code)
44
- run
45
- end
7
+ require 'brainfuck/parser'
8
+ require 'brainfuck/interpreter'
46
9
 
47
- def run(from = nil, to = nil)
48
- index = 0
49
- context = 0
50
-
51
- c = code.dup
52
-
53
- if from && to
54
- context = from
55
- c = c.slice(from...to)
56
- end
57
-
58
- c.each_char do |char|
59
- index += 1
60
- case char
61
- when '>'
62
- forward
63
- when '<'
64
- backward
65
- when '+'
66
- increase
67
- when '-'
68
- decrease
69
- when '.'
70
- stdout.print current.chr
71
- when ','
72
- self.current = get_character
73
- when '['
74
- @start = index
75
- when ']'
76
- @end = index unless @end && @start < @end
77
- run(@start, @end) unless current == 0
78
- @start = context || nil
79
- end
80
- end
81
- end
82
-
83
- private
84
-
85
- def clean(code)
86
- code.chars.select {|c| INSTRUCTIONS.include? c }.join
87
- end
88
-
89
- def stdout
90
- $stdout
91
- end
92
-
93
- def initialize_cell_if_nil
94
- @cells[pointer] ||= 0
95
- end
10
+ module Brainfuck
11
+ class << self
12
+ def run code
13
+ Interpreter.stack.clear
96
14
 
97
- def ensure_pointer_is_above_zero
98
- raise "Tried to access cell #{@pointer}." if @pointer < 0
15
+ code = Parser.clean code
16
+ parsed = Parser.new.parse code
17
+ ast = Interpreter.new.apply parsed
18
+ ast.each(&:eval)
19
+ Interpreter.stack.to_a
99
20
  end
100
-
101
21
  end
102
22
  end
@@ -0,0 +1,32 @@
1
+ module Brainfuck
2
+ module AST
3
+ class FwdNode < Struct.new(:stack)
4
+ def eval; stack.fwd ; end
5
+ end
6
+ class BwdNode < Struct.new(:stack)
7
+ def eval; stack.bwd ; end
8
+ end
9
+
10
+ class IncNode < Struct.new(:stack)
11
+ def eval; stack.inc ; end
12
+ end
13
+ class DecNode < Struct.new(:stack)
14
+ def eval; stack.dec ; end
15
+ end
16
+ class PutsNode < Struct.new(:stack)
17
+ def eval; stack.puts ; end
18
+ end
19
+ class GetsNode < Struct.new(:stack)
20
+ def eval; stack.gets ; end
21
+ end
22
+ class IterationNode < Struct.new(:stack, :exp)
23
+ def eval
24
+ until stack.current == 0
25
+ exp.each do |node|
26
+ node.eval
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,20 @@
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
@@ -0,0 +1,31 @@
1
+ module Brainfuck
2
+ class Parser < Parslet::Parser
3
+ INSTRUCTIONS = %w{> < + - [ ] . ,}
4
+
5
+ class << self
6
+ def clean code
7
+ code.chars.select {|c| INSTRUCTIONS.include? c }.join
8
+ end
9
+ end
10
+
11
+ rule(:lparen) { str('[') >> space? }
12
+ rule(:rparen) { str(']') >> space? }
13
+
14
+ rule(:space) { match('\s').repeat(1) }
15
+ rule(:space?) { space.maybe }
16
+
17
+ rule(:fwd) { str('>') >> space? }
18
+ rule(:bwd) { str('<') >> space? }
19
+
20
+ rule(:inc) { str('+') >> space? }
21
+ rule(:dec) { str('-') >> space? }
22
+
23
+ rule(:puts) { str('.') >> space? }
24
+ rule(:gets) { str(',') >> space? }
25
+
26
+ rule(:iteration) { lparen >> expression >> rparen }
27
+
28
+ rule(:expression) { (iteration.as(:iteration) | fwd.as(:fwd) | bwd.as(:bwd) | inc.as(:inc) | dec.as(:dec) | puts.as(:puts) | gets.as(:gets)).repeat.as(:exp) }
29
+ root :expression
30
+ end
31
+ end
@@ -0,0 +1,51 @@
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,3 +1,3 @@
1
1
  module Brainfuck
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -1,7 +1,9 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  module Brainfuck
4
- describe Interpreter, "acceptance specs" do
4
+ describe "Acceptance specs" do
5
+
6
+ subject { Brainfuck }
5
7
 
6
8
  describe "without loops nor user input" do
7
9
  let(:code) do
@@ -10,17 +12,11 @@ module Brainfuck
10
12
  EOS
11
13
  end
12
14
  it "sets two cells to 2 and 1" do
13
- subject.should_receive(:code).and_return code
14
- subject.compile(code)
15
- subject.cells.should == [2,1]
15
+ subject.run(code).should == [2,1]
16
16
  end
17
17
  it "prints 2 and 1" do
18
- output = double('output')
19
- subject.should_receive(:stdout).twice.and_return(output)
20
- output.should_receive(:print).with(1.chr).ordered
21
- output.should_receive(:print).with(2.chr).ordered
22
-
23
- subject.compile(code)
18
+ $stdout.should_receive(:print).twice
19
+ subject.run code
24
20
  end
25
21
  end
26
22
 
@@ -31,11 +27,12 @@ module Brainfuck
31
27
  EOS
32
28
  end
33
29
  it "sets the first cell to a + 4" do
34
- input = double('input')
35
- subject.should_receive(:get_character).once.and_return 97
30
+ stack = Stack.new
31
+ Interpreter.stub(:stack).and_return stack
36
32
 
37
- subject.compile(code)
38
- subject.current.should == 101
33
+ stack.should_receive(:get_character).once.and_return 97
34
+
35
+ subject.run(code).should == [101]
39
36
  end
40
37
  end
41
38
 
@@ -46,29 +43,30 @@ module Brainfuck
46
43
  EOS
47
44
  end
48
45
  it "runs the loop 4 times" do
49
- subject.compile(code)
50
- subject.current.should == 1
46
+ subject.run(code).should == [1]
51
47
  end
52
48
  end
53
49
 
54
50
  describe "cell hopping examples" do
55
51
 
56
52
  it "transfers the content from one cell to another" do
57
- subject.cells = [10]
58
- subject.compile("[>+<-]")
59
- subject.cells.should == [0,10]
53
+ subject.run("++++++++++ [>+<-]").should == [0,10]
60
54
  end
61
55
 
62
56
  it "transfers the content from one cell to the third" do
63
- subject.cells = [10]
64
- subject.compile("[>+<-]>[>+<-]")
65
- subject.cells.should == [0,0,10]
57
+ subject.run("++++++++++ [>+<-]>[>+<-]").should == [0,0,10]
66
58
  end
67
59
 
68
60
  it "transfers the content from one cell to the third and back to the second" do
69
- subject.cells = [10]
70
- subject.compile("[>+<-]>[>+<-]>[<+>-]")
71
- subject.cells.should == [0,10,0]
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]
72
70
  end
73
71
 
74
72
  end
@@ -76,7 +74,7 @@ module Brainfuck
76
74
  describe "hello world" do
77
75
 
78
76
  it "displays hello world" do
79
- subject.compile <<-EOS
77
+ subject.run <<-EOS
80
78
  +++++ +++++
81
79
  [
82
80
  > +++++ ++
@@ -0,0 +1,36 @@
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
@@ -0,0 +1,25 @@
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
@@ -0,0 +1,27 @@
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
@@ -0,0 +1,81 @@
1
+ require 'spec_helper'
2
+
3
+ module Brainfuck
4
+ describe Stack do
5
+
6
+ describe "#current" do
7
+ it 'returns the current value of the stack' do
8
+ subject.current.should == 0
9
+ end
10
+ end
11
+
12
+ describe "#fwd" do
13
+ it 'advanced the pointer' do
14
+ subject.fwd
15
+ subject.instance_variable_get(:@pointer).should == 1
16
+ end
17
+ end
18
+
19
+ describe "#bwd" do
20
+ it 'decreases the pointer' do
21
+ subject.instance_variable_set(:@pointer, 4)
22
+ subject.bwd
23
+ subject.instance_variable_get(:@pointer).should == 3
24
+ end
25
+ context "if the pointer is trying to get below zero" do
26
+ it 'raises' do
27
+ subject.instance_variable_set(:@pointer, 0)
28
+ expect {
29
+ subject.bwd
30
+ }.to raise_error(RuntimeError, "Tried to access cell -1.")
31
+ end
32
+ end
33
+ end
34
+
35
+ describe "#inc" do
36
+ it 'increases the current cell' do
37
+ subject.instance_variable_set(:@stack, [4])
38
+ subject.inc
39
+ subject.current.should == 5
40
+ end
41
+ end
42
+
43
+ describe "#dec" do
44
+ it 'decreases the current cell' do
45
+ subject.instance_variable_set(:@stack, [4])
46
+ subject.dec
47
+ subject.current.should == 3
48
+ end
49
+ end
50
+
51
+ describe "#puts" do
52
+ it 'prints the current character' do
53
+ subject.stub_chain('current.chr').and_return 'A'
54
+ $stdout.should_receive(:print).with 'A'
55
+ subject.puts
56
+ end
57
+ end
58
+
59
+ describe "#gets" do
60
+ it 'prints the current character' do
61
+ subject.should_receive(:get_character).and_return 97
62
+ subject.gets
63
+ subject.current.should == 97
64
+ end
65
+ end
66
+
67
+ describe "#to_a" do
68
+ it 'returns the stack array' do
69
+ subject.to_a.should == [0]
70
+ end
71
+ end
72
+
73
+ describe "#clear" do
74
+ it 'clears the stack' do
75
+ subject.should_receive(:initialize)
76
+ subject.clear
77
+ end
78
+ end
79
+
80
+ end
81
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe Brainfuck do
4
+
5
+ describe ".run" do
6
+ it 'runs the code and returns the stack' do
7
+ code = double('code')
8
+ parsed = double('parsed')
9
+ ast = [double('node'), double('node')]
10
+
11
+ Brainfuck::Interpreter.stack.should_receive(:clear)
12
+
13
+ Brainfuck::Parser.should_receive(:clean).with("code").and_return(code)
14
+ Brainfuck::Parser.stub_chain('new.parse').with(code).and_return parsed
15
+ Brainfuck::Interpreter.stub_chain('new.apply').with(parsed).and_return ast
16
+
17
+ ast.each { |n| n.should_receive(:eval) }
18
+
19
+ subject.run("code").should === Brainfuck::Interpreter.stack.to_a
20
+ end
21
+ end
22
+
23
+ end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 0
8
7
  - 1
9
- version: 0.0.1
8
+ - 0
9
+ version: 0.1.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Josep M. Bach
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-12-02 00:00:00 +01:00
17
+ date: 2011-01-12 00:00:00 +01:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -31,7 +31,7 @@ dependencies:
31
31
  type: :runtime
32
32
  version_requirements: *id001
33
33
  - !ruby/object:Gem::Dependency
34
- name: rspec
34
+ name: parslet
35
35
  prerelease: false
36
36
  requirement: &id002 !ruby/object:Gem::Requirement
37
37
  none: false
@@ -41,10 +41,10 @@ dependencies:
41
41
  segments:
42
42
  - 0
43
43
  version: "0"
44
- type: :development
44
+ type: :runtime
45
45
  version_requirements: *id002
46
46
  - !ruby/object:Gem::Dependency
47
- name: bundler
47
+ name: rspec
48
48
  prerelease: false
49
49
  requirement: &id003 !ruby/object:Gem::Requirement
50
50
  none: false
@@ -57,7 +57,7 @@ dependencies:
57
57
  type: :development
58
58
  version_requirements: *id003
59
59
  - !ruby/object:Gem::Dependency
60
- name: simplecov
60
+ name: bundler
61
61
  prerelease: false
62
62
  requirement: &id004 !ruby/object:Gem::Requirement
63
63
  none: false
@@ -69,6 +69,19 @@ dependencies:
69
69
  version: "0"
70
70
  type: :development
71
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
72
85
  description: Another Brainfuck interpreter in Ruby
73
86
  email:
74
87
  - josep.m.bach@gmail.com
@@ -88,9 +101,17 @@ files:
88
101
  - brainfuck.gemspec
89
102
  - examples/hello_world.bf
90
103
  - lib/brainfuck.rb
104
+ - lib/brainfuck/ast.rb
105
+ - lib/brainfuck/interpreter.rb
106
+ - lib/brainfuck/parser.rb
107
+ - lib/brainfuck/stack.rb
91
108
  - lib/brainfuck/version.rb
92
- - spec/acceptance_spec.rb
93
- - spec/interpreter_spec.rb
109
+ - spec/acceptance/acceptance_spec.rb
110
+ - spec/brainfuck/ast_spec.rb
111
+ - spec/brainfuck/interpreter_spec.rb
112
+ - spec/brainfuck/parser_spec.rb
113
+ - spec/brainfuck/stack_spec.rb
114
+ - spec/brainfuck_spec.rb
94
115
  - spec/spec_helper.rb
95
116
  has_rdoc: true
96
117
  homepage: http://github.com/txus/brainfuck
@@ -125,6 +146,10 @@ signing_key:
125
146
  specification_version: 3
126
147
  summary: Another Brainfuck interpreter in Ruby
127
148
  test_files:
128
- - spec/acceptance_spec.rb
129
- - spec/interpreter_spec.rb
149
+ - spec/acceptance/acceptance_spec.rb
150
+ - spec/brainfuck/ast_spec.rb
151
+ - spec/brainfuck/interpreter_spec.rb
152
+ - spec/brainfuck/parser_spec.rb
153
+ - spec/brainfuck/stack_spec.rb
154
+ - spec/brainfuck_spec.rb
130
155
  - spec/spec_helper.rb
@@ -1,65 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Brainfuck
4
- describe Interpreter do
5
- subject { Interpreter.new }
6
-
7
- it "initializes with an array of cells with a single 0 element" do
8
- subject.cells.should == [0]
9
- end
10
-
11
- describe "#clean" do
12
- it "cleans the code from comments and whitespace" do
13
- subject.send(:clean, " < > h - + ..,hb [lk]f").should == '<>-+..,[]'
14
- end
15
- end
16
-
17
- describe "#compile" do
18
- it "cleans the code first and runs it second" do
19
- code = double('code')
20
- subject.should_receive(:clean).once.with(code).ordered.and_return("")
21
- subject.should_receive(:run).once
22
-
23
- subject.compile(code)
24
- end
25
- end
26
-
27
- describe "#run" do
28
- it "converts > into forward" do
29
- subject.stub(:code).and_return ">"
30
- subject.should_receive(:forward).once
31
- subject.run
32
- end
33
- it "converts < into backward" do
34
- subject.stub(:code).and_return "<"
35
- subject.should_receive(:backward).once
36
- subject.run
37
- end
38
- it "converts + into increase" do
39
- subject.stub(:code).and_return "+"
40
- subject.should_receive(:increase).once
41
- subject.run
42
- end
43
- it "converts - into decrease" do
44
- subject.stub(:code).and_return "-"
45
- subject.should_receive(:decrease).once
46
- subject.run
47
- end
48
- it "converts , into get_character" do
49
- subject.stub(:code).and_return ","
50
- subject.should_receive(:get_character).once
51
- subject.run
52
- end
53
- it "converts . into stdout.print" do
54
- subject.stub(:code).and_return "."
55
- output = double('output')
56
- subject.should_receive(:stdout).once.and_return(output)
57
- subject.should_receive(:current).once.and_return(117)
58
- output.should_receive(:print).once
59
-
60
- subject.run
61
- end
62
- end
63
-
64
- end
65
- end