brainfuck 0.0.1

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.
@@ -0,0 +1,3 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in brainfuck.gemspec
4
+ gemspec
@@ -0,0 +1,33 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ brainfuck (0.0.1)
5
+ highline
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ diff-lcs (1.1.2)
11
+ highline (1.6.1)
12
+ rspec (2.2.0)
13
+ rspec-core (~> 2.2)
14
+ rspec-expectations (~> 2.2)
15
+ rspec-mocks (~> 2.2)
16
+ rspec-core (2.2.1)
17
+ rspec-expectations (2.2.0)
18
+ diff-lcs (~> 1.1.2)
19
+ rspec-mocks (2.2.0)
20
+ simplecov (0.3.7)
21
+ simplecov-html (>= 0.3.7)
22
+ simplecov-html (0.3.9)
23
+
24
+ PLATFORMS
25
+ java
26
+ ruby
27
+
28
+ DEPENDENCIES
29
+ brainfuck!
30
+ bundler
31
+ highline
32
+ rspec
33
+ simplecov
@@ -0,0 +1,15 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'simplecov'
5
+ SimpleCov.start do
6
+ add_group "Lib", 'lib'
7
+ end
8
+
9
+ require 'rspec/core'
10
+ require 'rspec/core/rake_task'
11
+ RSpec::Core::RakeTask.new(:spec) do |spec|
12
+ spec.pattern = FileList['spec/**/*_spec.rb']
13
+ end
14
+
15
+ task :default => :spec
@@ -0,0 +1,49 @@
1
+ # brainfuck
2
+
3
+ Just another Brainfuck interpreter in Ruby!
4
+ (If you don't know what Brainfuck is, you definitely
5
+ [should][http://en.wikipedia.org/wiki/Brainfuck]).
6
+
7
+ This interpreter works with MRI 1.8.7, 1.9.2 and JRuby 1.5.5.
8
+
9
+ ## Known caveats (yes, before anything)
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! :)
17
+
18
+ ## Installation and usage
19
+
20
+ You just `gem install brainfuck`!
21
+
22
+ And then: `brainfuck my_file.bf`
23
+
24
+ You can also require the gem and use inline brainfuck in your ruby scripts like this:
25
+
26
+ require 'brainfuck'
27
+
28
+ interpreter = Brainfuck.new
29
+ interpreter.compile "+++>+++<---"
30
+
31
+ interpreter.cells
32
+ # => [0, 3]
33
+
34
+ It's very basic, and needs *a lot* of refactoring, but for now... there you go! ;)
35
+
36
+ ## Note on Patches/Pull Requests
37
+
38
+ * Fork the project.
39
+ * Make your feature addition or bug fix.
40
+ * Add specs for it. This is important so I don't break it in a
41
+ future version unintentionally.
42
+ * Commit, do not mess with rakefile, version, or history.
43
+ If you want to have your own version, that is fine but bump version
44
+ in a commit by itself I can ignore when I pull.
45
+ * Send me a pull request. Bonus points for topic branches.
46
+
47
+ ## Copyright
48
+
49
+ Copyright (c) 2010 Josep M. Bach. See LICENSE for details.
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require 'brainfuck'
3
+ Brainfuck::Interpreter.new.compile File.read(ARGV.first)
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "brainfuck/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "brainfuck"
7
+ s.version = Brainfuck::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Josep M. Bach"]
10
+ s.email = ["josep.m.bach@gmail.com"]
11
+ s.homepage = "http://github.com/txus/brainfuck"
12
+ s.summary = %q{Another Brainfuck interpreter in Ruby}
13
+ s.description = %q{Another Brainfuck interpreter in Ruby}
14
+
15
+ s.rubyforge_project = "brainfuck"
16
+
17
+ s.add_runtime_dependency "highline"
18
+ s.add_development_dependency "rspec"
19
+ s.add_development_dependency "bundler"
20
+ s.add_development_dependency "simplecov"
21
+
22
+ s.files = `git ls-files`.split("\n")
23
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
24
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
25
+ s.require_paths = ["lib"]
26
+ end
@@ -0,0 +1,21 @@
1
+ +++++ +++++ initialize counter (cell #0) to 10
2
+ [ use loop to set the next four cells to 70/100/30/10
3
+ > +++++ ++ add 7 to cell #1
4
+ > +++++ +++++ add 10 to cell #2
5
+ > +++ add 3 to cell #3
6
+ > + add 1 to cell #4
7
+ <<<< - decrement counter (cell #0)
8
+ ]
9
+ > ++ . print 'H'
10
+ > + . print 'e'
11
+ +++++ ++ . print 'l'
12
+ . print 'l'
13
+ +++ . print 'o'
14
+ > ++ . print ' '
15
+ << +++++ +++++ +++++ . print 'W'
16
+ > . print 'o'
17
+ +++ . print 'r'
18
+ ----- - . print 'l'
19
+ ----- --- . print 'd'
20
+ > + . print '!'
21
+ > . print '\n'
@@ -0,0 +1,102 @@
1
+ require 'highline/system_extensions'
2
+
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
25
+
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
46
+
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
96
+
97
+ def ensure_pointer_is_above_zero
98
+ raise "Tried to access cell #{@pointer}." if @pointer < 0
99
+ end
100
+
101
+ end
102
+ end
@@ -0,0 +1,3 @@
1
+ module Brainfuck
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,107 @@
1
+ require 'spec_helper'
2
+
3
+ module Brainfuck
4
+ describe Interpreter, "acceptance specs" do
5
+
6
+ describe "without loops nor user input" do
7
+ let(:code) do
8
+ <<-EOS
9
+ ++++>++++---.<--.
10
+ EOS
11
+ end
12
+ 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]
16
+ end
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)
24
+ end
25
+ end
26
+
27
+ describe "with user input" do
28
+ let(:code) do
29
+ <<-EOS
30
+ ,++++
31
+ EOS
32
+ end
33
+ it "sets the first cell to a + 4" do
34
+ input = double('input')
35
+ subject.should_receive(:get_character).once.and_return 97
36
+
37
+ subject.compile(code)
38
+ subject.current.should == 101
39
+ end
40
+ end
41
+
42
+ describe "with loops" do
43
+ let(:code) do
44
+ <<-EOS
45
+ ++++[-]+-+
46
+ EOS
47
+ end
48
+ it "runs the loop 4 times" do
49
+ subject.compile(code)
50
+ subject.current.should == 1
51
+ end
52
+ end
53
+
54
+ describe "cell hopping examples" do
55
+
56
+ it "transfers the content from one cell to another" do
57
+ subject.cells = [10]
58
+ subject.compile("[>+<-]")
59
+ subject.cells.should == [0,10]
60
+ end
61
+
62
+ 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]
66
+ end
67
+
68
+ 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]
72
+ end
73
+
74
+ end
75
+
76
+ describe "hello world" do
77
+
78
+ it "displays hello world" do
79
+ subject.compile <<-EOS
80
+ +++++ +++++
81
+ [
82
+ > +++++ ++
83
+ > +++++ +++++
84
+ > +++
85
+ > +
86
+ <<<< -
87
+ ]
88
+ > ++ .
89
+ > + .
90
+ +++++ ++ .
91
+ .
92
+ +++ .
93
+ > ++ .
94
+ << +++++ +++++ +++++ .
95
+ > .
96
+ +++ .
97
+ ----- - .
98
+ ----- --- .
99
+ > + .
100
+ > .
101
+ EOS
102
+
103
+ end
104
+ end
105
+
106
+ end
107
+ end
@@ -0,0 +1,65 @@
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
@@ -0,0 +1,18 @@
1
+ require 'bundler'
2
+ require 'simplecov'
3
+ SimpleCov.start do
4
+ add_group "Lib", "lib"
5
+ end
6
+
7
+ begin
8
+ Bundler.setup(:default, :development)
9
+ rescue Bundler::BundlerError => e
10
+ $stderr.puts e.message
11
+ $stderr.puts "Run `bundle install` to install missing gems"
12
+ exit e.status_code
13
+ end
14
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
15
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
16
+
17
+ require 'brainfuck'
18
+ require 'rspec'
metadata ADDED
@@ -0,0 +1,130 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: brainfuck
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Josep M. Bach
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-12-02 00:00:00 +01:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: highline
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ type: :runtime
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: rspec
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 0
43
+ version: "0"
44
+ type: :development
45
+ version_requirements: *id002
46
+ - !ruby/object:Gem::Dependency
47
+ name: bundler
48
+ prerelease: false
49
+ requirement: &id003 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ segments:
55
+ - 0
56
+ version: "0"
57
+ type: :development
58
+ version_requirements: *id003
59
+ - !ruby/object:Gem::Dependency
60
+ name: simplecov
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
+ description: Another Brainfuck interpreter in Ruby
73
+ email:
74
+ - josep.m.bach@gmail.com
75
+ executables:
76
+ - brainfuck
77
+ extensions: []
78
+
79
+ extra_rdoc_files: []
80
+
81
+ files:
82
+ - .gitignore
83
+ - Gemfile
84
+ - Gemfile.lock
85
+ - Rakefile
86
+ - Readme.md
87
+ - bin/brainfuck
88
+ - brainfuck.gemspec
89
+ - examples/hello_world.bf
90
+ - lib/brainfuck.rb
91
+ - lib/brainfuck/version.rb
92
+ - spec/acceptance_spec.rb
93
+ - spec/interpreter_spec.rb
94
+ - spec/spec_helper.rb
95
+ has_rdoc: true
96
+ homepage: http://github.com/txus/brainfuck
97
+ licenses: []
98
+
99
+ post_install_message:
100
+ rdoc_options: []
101
+
102
+ require_paths:
103
+ - lib
104
+ required_ruby_version: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ segments:
110
+ - 0
111
+ version: "0"
112
+ required_rubygems_version: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ segments:
118
+ - 0
119
+ version: "0"
120
+ requirements: []
121
+
122
+ rubyforge_project: brainfuck
123
+ rubygems_version: 1.3.7
124
+ signing_key:
125
+ specification_version: 3
126
+ summary: Another Brainfuck interpreter in Ruby
127
+ test_files:
128
+ - spec/acceptance_spec.rb
129
+ - spec/interpreter_spec.rb
130
+ - spec/spec_helper.rb