brainfuck 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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