noofakku 0.0.1 → 0.0.4
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.
- checksums.yaml +8 -8
- data/.gitignore +2 -0
- data/.travis.yml +6 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +57 -0
- data/README.md +9 -0
- data/Rakefile +9 -0
- data/lib/noofakku/instruction/closed_bracket.rb +28 -0
- data/lib/noofakku/instruction/dec.rb +13 -0
- data/lib/noofakku/instruction/inc.rb +13 -0
- data/lib/noofakku/instruction/input.rb +14 -0
- data/lib/noofakku/instruction/next.rb +12 -0
- data/lib/noofakku/instruction/noop.rb +11 -0
- data/lib/noofakku/instruction/open_bracket.rb +28 -0
- data/lib/noofakku/instruction/output.rb +14 -0
- data/lib/noofakku/instruction/prev.rb +12 -0
- data/lib/noofakku/processor.rb +27 -0
- data/lib/noofakku.rb +9 -9
- data/noofakku.gemspec +20 -0
- data/resources/icon.png +0 -0
- data/test/instruction/closed_bracket_test.rb +49 -0
- data/test/instruction/dec_test.rb +35 -0
- data/test/instruction/inc_test.rb +35 -0
- data/test/instruction/input_test.rb +40 -0
- data/test/instruction/next_test.rb +30 -0
- data/test/instruction/noop_test.rb +66 -0
- data/test/instruction/open_bracket_test.rb +49 -0
- data/test/instruction/output_test.rb +38 -0
- data/test/instruction/prev_test.rb +30 -0
- data/test/noofakku_smoke_test.rb +43 -0
- data/test/processor_test.rb +53 -0
- data/test/test_helper.rb +3 -0
- metadata +74 -2
checksums.yaml
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
!binary "U0hBMQ==":
|
|
3
3
|
metadata.gz: !binary |-
|
|
4
|
-
|
|
4
|
+
N2ZkOGJhOTI5MWJkMWU3NzhiYWYyZmU0NWVlNTQ5MGRjM2UyZDczNw==
|
|
5
5
|
data.tar.gz: !binary |-
|
|
6
|
-
|
|
6
|
+
NWYxNjQyNjk1ZmU2YTc3NTE2YzM3NjlmMTUyYzVmZTVkODg2MzY0NQ==
|
|
7
7
|
SHA512:
|
|
8
8
|
metadata.gz: !binary |-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
NWRiOTI4MTM0NmFmOTZkYmZmZjI4YjU0YjljMTMzMzdiMjIzZDU2MDJlZGQ1
|
|
10
|
+
MGUyN2U1NmNmZTNjMDI5ZmJlYjA0NTc3OGFhOGEzMGQ5NWY4ZmE0ZTczNDYz
|
|
11
|
+
NjczNmI1MGQwYjgxNDUzM2QzZTVkOWY0NDg4OWI0YWZhOWNlZGM=
|
|
12
12
|
data.tar.gz: !binary |-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
MjU4ZjMzZjc0NTQ0YTliMjJkOTEwNmEzNDFmOTZlY2RhZGFiNWE5MDBhMmNm
|
|
14
|
+
OGZhMTU2MmM3YjkzZTU1OWMwZWE5MGZiZmQ4ZmRkZjRlYjQ4MTYwOTBjMmQy
|
|
15
|
+
NzAzYmNlMTA0YzViNjZkNTFmZWI0ZGFlNzcyODZiOWJjNGMwNDQ=
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
noofakku (0.0.4)
|
|
5
|
+
|
|
6
|
+
GEM
|
|
7
|
+
remote: https://rubygems.org/
|
|
8
|
+
specs:
|
|
9
|
+
activesupport (4.0.2)
|
|
10
|
+
i18n (~> 0.6, >= 0.6.4)
|
|
11
|
+
minitest (~> 4.2)
|
|
12
|
+
multi_json (~> 1.3)
|
|
13
|
+
thread_safe (~> 0.1)
|
|
14
|
+
tzinfo (~> 0.3.37)
|
|
15
|
+
atomic (1.1.14)
|
|
16
|
+
coveralls (0.7.0)
|
|
17
|
+
multi_json (~> 1.3)
|
|
18
|
+
rest-client
|
|
19
|
+
simplecov (>= 0.7)
|
|
20
|
+
term-ansicolor
|
|
21
|
+
thor
|
|
22
|
+
docile (1.1.1)
|
|
23
|
+
i18n (0.6.9)
|
|
24
|
+
mime-types (2.0)
|
|
25
|
+
minitest (4.7.5)
|
|
26
|
+
multi_json (1.8.2)
|
|
27
|
+
rake (10.1.0)
|
|
28
|
+
rest-client (1.6.7)
|
|
29
|
+
mime-types (>= 1.16)
|
|
30
|
+
shoulda (3.5.0)
|
|
31
|
+
shoulda-context (~> 1.0, >= 1.0.1)
|
|
32
|
+
shoulda-matchers (>= 1.4.1, < 3.0)
|
|
33
|
+
shoulda-context (1.1.6)
|
|
34
|
+
shoulda-matchers (2.4.0)
|
|
35
|
+
activesupport (>= 3.0.0)
|
|
36
|
+
simplecov (0.8.2)
|
|
37
|
+
docile (~> 1.1.0)
|
|
38
|
+
multi_json
|
|
39
|
+
simplecov-html (~> 0.8.0)
|
|
40
|
+
simplecov-html (0.8.0)
|
|
41
|
+
term-ansicolor (1.2.2)
|
|
42
|
+
tins (~> 0.8)
|
|
43
|
+
thor (0.18.1)
|
|
44
|
+
thread_safe (0.1.3)
|
|
45
|
+
atomic
|
|
46
|
+
tins (0.13.1)
|
|
47
|
+
tzinfo (0.3.38)
|
|
48
|
+
|
|
49
|
+
PLATFORMS
|
|
50
|
+
ruby
|
|
51
|
+
x86-mingw32
|
|
52
|
+
|
|
53
|
+
DEPENDENCIES
|
|
54
|
+
coveralls
|
|
55
|
+
noofakku!
|
|
56
|
+
rake
|
|
57
|
+
shoulda
|
data/README.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
Noofakku
|
|
2
|
+
========
|
|
3
|
+
<a href="http://badge.fury.io/rb/noofakku"><img src="https://badge.fury.io/rb/noofakku@2x.png" alt="Gem Version" height='18'></a>
|
|
4
|
+
<br/>
|
|
5
|
+
<a href="https://travis-ci.org/mcodella/noofakku"><img src="https://travis-ci.org/mcodella/noofakku.png?branch=master" alt="Travis-CI Status" height='18'></a>
|
|
6
|
+
<br/>
|
|
7
|
+
<a href="https://codeclimate.com/github/mcodella/noofakku"><img src="https://codeclimate.com/github/mcodella/noofakku.png" height='18'/></a>
|
|
8
|
+
<br/>
|
|
9
|
+
<a href='https://coveralls.io/r/mcodella/noofakku'><img src='https://coveralls.io/repos/mcodella/noofakku/badge.png' alt='Coverage Status' height='18'/></a>
|
data/Rakefile
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module Noofakku
|
|
2
|
+
|
|
3
|
+
class ClosedBracket
|
|
4
|
+
|
|
5
|
+
def initialize(open, closed)
|
|
6
|
+
@open, @closed = open, closed
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def perform(processor, memory, program, input, output)
|
|
10
|
+
raise "processor cannot be nil" unless processor != nil
|
|
11
|
+
raise "memory cannot be nil" unless memory != nil
|
|
12
|
+
raise "program cannot be nil" unless program != nil
|
|
13
|
+
raise "instruction pointer must point to a '#{@closed}'" unless program[processor.instruction_pointer] == @closed
|
|
14
|
+
if memory[processor.data_pointer] == 0 then return end
|
|
15
|
+
unmatched_brackets = 1
|
|
16
|
+
pointer_to_current_instruction = processor.instruction_pointer
|
|
17
|
+
until unmatched_brackets == 0
|
|
18
|
+
processor.instruction_pointer -= 1
|
|
19
|
+
if processor.instruction_pointer == -1 then raise "no matching '#{@open}' for '#{@closed}' at #{pointer_to_current_instruction}"
|
|
20
|
+
elsif program[processor.instruction_pointer] == @closed then unmatched_brackets += 1
|
|
21
|
+
elsif program[processor.instruction_pointer] == @open then unmatched_brackets -= 1
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module Noofakku
|
|
2
|
+
class Dec
|
|
3
|
+
def hook
|
|
4
|
+
'-'
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def perform(processor, memory, program, input, output)
|
|
8
|
+
raise "processor cannot be nil" unless processor != nil
|
|
9
|
+
raise "memory cannot be nil" unless memory != nil
|
|
10
|
+
memory[processor.data_pointer] -= 1
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module Noofakku
|
|
2
|
+
|
|
3
|
+
class Inc
|
|
4
|
+
|
|
5
|
+
def perform(processor, memory, program, input, output)
|
|
6
|
+
raise "processor cannot be nil" unless processor != nil
|
|
7
|
+
raise "memory cannot be nil" unless memory != nil
|
|
8
|
+
memory[processor.data_pointer] += 1
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module Noofakku
|
|
2
|
+
|
|
3
|
+
class Input
|
|
4
|
+
|
|
5
|
+
def perform(processor, memory, program, input, output)
|
|
6
|
+
raise "processor cannot be nil" unless processor != nil
|
|
7
|
+
raise "memory cannot be nil" unless memory != nil
|
|
8
|
+
raise "input cannot be nil" unless input != nil
|
|
9
|
+
memory[processor.data_pointer] = input.call
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module Noofakku
|
|
2
|
+
|
|
3
|
+
class OpenBracket
|
|
4
|
+
|
|
5
|
+
def initialize(open, closed)
|
|
6
|
+
@open, @closed = open, closed
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def perform(processor, memory, program, input, output)
|
|
10
|
+
raise "processor cannot be nil" unless processor != nil
|
|
11
|
+
raise "memory cannot be nil" unless memory != nil
|
|
12
|
+
raise "program cannot be nil" unless program != nil
|
|
13
|
+
raise "instruction pointer must point to a '#{@open}'" unless program[processor.instruction_pointer] == @open
|
|
14
|
+
if memory[processor.data_pointer] != 0 then return end
|
|
15
|
+
unmatched_brackets = 1
|
|
16
|
+
pointer_to_current_instruction = processor.instruction_pointer
|
|
17
|
+
until unmatched_brackets == 0
|
|
18
|
+
processor.instruction_pointer += 1
|
|
19
|
+
if processor.instruction_pointer == program.length then raise "no matching '#{@closed}' for '#{@open}' at #{pointer_to_current_instruction}"
|
|
20
|
+
elsif program[processor.instruction_pointer] == @open then unmatched_brackets += 1
|
|
21
|
+
elsif program[processor.instruction_pointer] == @closed then unmatched_brackets -= 1
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module Noofakku
|
|
2
|
+
|
|
3
|
+
class Output
|
|
4
|
+
|
|
5
|
+
def perform(processor, memory, program, input, output)
|
|
6
|
+
raise "processor cannot be nil" unless processor != nil
|
|
7
|
+
raise "memory cannot be nil" unless memory != nil
|
|
8
|
+
raise "output cannot be nil" unless output != nil
|
|
9
|
+
output.call(memory[processor.data_pointer])
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module Noofakku
|
|
2
|
+
|
|
3
|
+
class Processor
|
|
4
|
+
|
|
5
|
+
attr_accessor :instruction_pointer, :data_pointer
|
|
6
|
+
|
|
7
|
+
def initialize(instruction_to_handler)
|
|
8
|
+
raise "instruction_to_handler cannot be nil" unless instruction_to_handler != nil
|
|
9
|
+
@instruction_to_handler = instruction_to_handler
|
|
10
|
+
@instruction_pointer = @data_pointer = 0
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def run(program, memory, input, output)
|
|
14
|
+
raise "program cannot be nil" unless program != nil
|
|
15
|
+
raise "memory cannot be nil" unless memory != nil
|
|
16
|
+
raise "input cannot be nil" unless input != nil
|
|
17
|
+
raise "output cannot be nil" unless output != nil
|
|
18
|
+
while (0...program.length).include? @instruction_pointer
|
|
19
|
+
instruction = @instruction_to_handler[program[@instruction_pointer]]
|
|
20
|
+
instruction.perform(self, memory, program, input, output)
|
|
21
|
+
@instruction_pointer += 1
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
end
|
data/lib/noofakku.rb
CHANGED
|
@@ -12,16 +12,16 @@ module Noofakku
|
|
|
12
12
|
class VM
|
|
13
13
|
def self.start(program, input, output)
|
|
14
14
|
processor = Processor.new(Hash.new(Noop.new).merge!({
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
15
|
+
'>' => Next.new,
|
|
16
|
+
'<' => Prev.new,
|
|
17
|
+
'+' => Inc.new,
|
|
18
|
+
'-' => Dec.new,
|
|
19
|
+
'.' => Output.new,
|
|
20
|
+
',' => Input.new,
|
|
21
|
+
'[' => OpenBracket.new('[', ']'),
|
|
22
|
+
']' => ClosedBracket.new('[', ']')
|
|
23
23
|
}))
|
|
24
24
|
processor.run(program.clone.freeze, Array.new(30_000, 0), input, output)
|
|
25
25
|
end
|
|
26
26
|
end
|
|
27
|
-
end
|
|
27
|
+
end
|
data/noofakku.gemspec
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Gem::Specification.new do |s|
|
|
2
|
+
s.name = 'noofakku'
|
|
3
|
+
s.version = `git describe --tags --abbrev=0`.split("\n")[0]
|
|
4
|
+
s.date = '2013-12-08'
|
|
5
|
+
s.summary = "Noofakku"
|
|
6
|
+
s.description = "A simple brainfuck implementation"
|
|
7
|
+
s.authors = ["Mauro Codella"]
|
|
8
|
+
s.email = 'mauro.codella@gmail.com'
|
|
9
|
+
s.homepage = 'http://github.com/mcodella/noofakku'
|
|
10
|
+
s.license = 'MIT'
|
|
11
|
+
|
|
12
|
+
s.files = `git ls-files`.split("\n")
|
|
13
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
14
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
|
15
|
+
s.require_paths = ["lib"]
|
|
16
|
+
|
|
17
|
+
s.add_development_dependency "rake"
|
|
18
|
+
s.add_development_dependency "shoulda"
|
|
19
|
+
s.add_development_dependency "coveralls"
|
|
20
|
+
end
|
data/resources/icon.png
ADDED
|
Binary file
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
require 'test/unit'
|
|
2
|
+
require 'noofakku/instruction/closed_bracket'
|
|
3
|
+
require 'shoulda'
|
|
4
|
+
require 'ostruct'
|
|
5
|
+
|
|
6
|
+
module Noofakku
|
|
7
|
+
|
|
8
|
+
class ClosedBracketTest < Test::Unit::TestCase
|
|
9
|
+
|
|
10
|
+
context "Execution" do
|
|
11
|
+
|
|
12
|
+
setup do
|
|
13
|
+
@instance = ClosedBracket.new("[", "]")
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
should "throw on nil processor" do
|
|
17
|
+
assert_raise (RuntimeError) { @instance.perform(nil, Object.new, Object.new, Object.new, Object.new) }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
should "throw on nil memory" do
|
|
21
|
+
assert_raise (RuntimeError) { @instance.perform(Object.new, nil, Object.new, Object.new, Object.new) }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
should "throw on nil program" do
|
|
25
|
+
assert_raise (RuntimeError) { @instance.perform(Object.new, Object.new, nil, Object.new, Object.new) }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
should "throw if instruction pointer is not pointing to an open bracket" do
|
|
29
|
+
spy_processor = OpenStruct.new(instruction_pointer: 0)
|
|
30
|
+
assert_raise (RuntimeError) { @instance.perform(spy_processor, Object.new, "_", nil, nil) }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
should "leave the instruction pointer as is if data pointer points to a cell which value is zero" do
|
|
34
|
+
spy_processor = OpenStruct.new(instruction_pointer: 2, data_pointer: 0)
|
|
35
|
+
@instance.perform(spy_processor, [0], "[_]_", nil, nil)
|
|
36
|
+
assert_equal 2, spy_processor.instruction_pointer
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
should "change the instruction pointer in order to point to the matching '[' if data pointer points to a cell which value is not zero" do
|
|
40
|
+
spy_processor = OpenStruct.new(instruction_pointer: 2, data_pointer: 0)
|
|
41
|
+
@instance.perform(spy_processor, [42], "[_]_", nil, nil)
|
|
42
|
+
assert_equal 0, spy_processor.instruction_pointer
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require 'test/unit'
|
|
2
|
+
require 'noofakku/instruction/dec'
|
|
3
|
+
require 'shoulda'
|
|
4
|
+
require 'ostruct'
|
|
5
|
+
|
|
6
|
+
module Noofakku
|
|
7
|
+
|
|
8
|
+
class DecTest < Test::Unit::TestCase
|
|
9
|
+
|
|
10
|
+
context "Execution" do
|
|
11
|
+
|
|
12
|
+
setup do
|
|
13
|
+
@instance = Dec.new
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
should "throw on nil processor" do
|
|
17
|
+
assert_raise (RuntimeError) { @instance.perform(nil, Object.new, Object.new, Object.new, Object.new) }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
should "throw on nil memory" do
|
|
21
|
+
assert_raise (RuntimeError) { @instance.perform(Object.new, nil, Object.new, Object.new, Object.new) }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
should "decrement memory cell addressed by the data pointer" do
|
|
25
|
+
spy_processor = OpenStruct.new(data_pointer: 0)
|
|
26
|
+
spy_memory = [0]
|
|
27
|
+
@instance.perform(spy_processor, spy_memory, nil, nil, nil)
|
|
28
|
+
assert_equal -1, spy_memory[spy_processor.data_pointer]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require 'test/unit'
|
|
2
|
+
require 'noofakku/instruction/inc'
|
|
3
|
+
require 'shoulda'
|
|
4
|
+
require 'ostruct'
|
|
5
|
+
|
|
6
|
+
module Noofakku
|
|
7
|
+
|
|
8
|
+
class IncTest < Test::Unit::TestCase
|
|
9
|
+
|
|
10
|
+
context "Execution" do
|
|
11
|
+
|
|
12
|
+
setup do
|
|
13
|
+
@instance = Inc.new
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
should "throw on nil processor" do
|
|
17
|
+
assert_raise (RuntimeError) { @instance.perform(nil, Object.new, Object.new, Object.new, Object.new) }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
should "throw on nil memory" do
|
|
21
|
+
assert_raise (RuntimeError) { @instance.perform(Object.new, nil, Object.new, Object.new, Object.new) }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
should "increment memory cell addressed by the data pointer" do
|
|
25
|
+
spy_processor = OpenStruct.new(data_pointer: 0)
|
|
26
|
+
spy_memory = [0]
|
|
27
|
+
@instance.perform(spy_processor, spy_memory, nil, nil, nil)
|
|
28
|
+
assert_equal 1, spy_memory[spy_processor.data_pointer]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require 'test/unit'
|
|
2
|
+
require 'noofakku/instruction/input'
|
|
3
|
+
require 'shoulda'
|
|
4
|
+
require 'ostruct'
|
|
5
|
+
|
|
6
|
+
module Noofakku
|
|
7
|
+
|
|
8
|
+
class InputTest < Test::Unit::TestCase
|
|
9
|
+
|
|
10
|
+
context "Execution" do
|
|
11
|
+
|
|
12
|
+
setup do
|
|
13
|
+
@instance = Input.new
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
should "throw on nil processor" do
|
|
17
|
+
assert_raise (RuntimeError) { @instance.perform(nil, Object.new, Object.new, Object.new, Object.new) }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
should "throw on nil memory" do
|
|
21
|
+
assert_raise (RuntimeError) { @instance.perform(Object.new, nil, Object.new, Object.new, Object.new) }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
should "throw on nil input" do
|
|
25
|
+
assert_raise (RuntimeError) { @instance.perform(Object.new, Object.new, Object.new, nil, Object.new) }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
should "fill the memory cell addressed by the data pointer with the value of the yielded block" do
|
|
29
|
+
spy_processor = OpenStruct.new(data_pointer: 0)
|
|
30
|
+
spy_memory = [0]
|
|
31
|
+
input = lambda { 42 }
|
|
32
|
+
@instance.perform(spy_processor, spy_memory, nil, input, nil)
|
|
33
|
+
assert_equal 42, spy_memory[spy_processor.data_pointer]
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require 'test/unit'
|
|
2
|
+
require 'noofakku/instruction/next'
|
|
3
|
+
require 'shoulda'
|
|
4
|
+
require 'ostruct'
|
|
5
|
+
|
|
6
|
+
module Noofakku
|
|
7
|
+
|
|
8
|
+
class NextTest < Test::Unit::TestCase
|
|
9
|
+
|
|
10
|
+
context "Execution" do
|
|
11
|
+
|
|
12
|
+
setup do
|
|
13
|
+
@instance = Next.new
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
should "throw on nil processor" do
|
|
17
|
+
assert_raise (RuntimeError) { @instance.perform(nil, nil, Object.new, Object.new, Object.new) }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
should "increment memory data pointer" do
|
|
21
|
+
spy_processor = OpenStruct.new(data_pointer: 0)
|
|
22
|
+
@instance.perform(spy_processor, nil, nil, nil, nil)
|
|
23
|
+
assert_equal 1, spy_processor.data_pointer
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
require 'test/unit'
|
|
2
|
+
require 'noofakku/instruction/noop'
|
|
3
|
+
require 'shoulda'
|
|
4
|
+
require 'ostruct'
|
|
5
|
+
|
|
6
|
+
module Noofakku
|
|
7
|
+
|
|
8
|
+
class NoopTest < Test::Unit::TestCase
|
|
9
|
+
|
|
10
|
+
context "Execution" do
|
|
11
|
+
|
|
12
|
+
setup do
|
|
13
|
+
@instance = Noop.new
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
should "leave alone the data pointer" do
|
|
17
|
+
spy_processor = OpenStruct.new(data_pointer: 0)
|
|
18
|
+
@instance.perform(spy_processor, [], [], ->{0}, ->value{})
|
|
19
|
+
assert_equal 0, spy_processor.data_pointer
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
should "leave alone the instruction pointer" do
|
|
23
|
+
spy_processor = OpenStruct.new(instruction_pointer: 0)
|
|
24
|
+
@instance.perform(spy_processor, [], [], ->{0}, ->value{})
|
|
25
|
+
assert_equal 0, spy_processor.instruction_pointer
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
should "leave alone the memory" do
|
|
29
|
+
touched = false
|
|
30
|
+
not_to_be_touched = [].freeze
|
|
31
|
+
begin
|
|
32
|
+
@instance.perform(Object.new, not_to_be_touched, [], ->{0}, ->value{})
|
|
33
|
+
rescue
|
|
34
|
+
touched = true
|
|
35
|
+
end
|
|
36
|
+
assert (not touched)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
should "leave alone the program" do
|
|
40
|
+
touched = false
|
|
41
|
+
not_to_be_touched = [].freeze
|
|
42
|
+
begin
|
|
43
|
+
@instance.perform(Object.new, [], not_to_be_touched, ->{0}, ->value{})
|
|
44
|
+
rescue
|
|
45
|
+
touched = true
|
|
46
|
+
end
|
|
47
|
+
assert (not touched)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
should "leave alone the input lambda" do
|
|
51
|
+
invoked = false
|
|
52
|
+
@instance.perform(Object.new, [], [], ->{ invoked = true }, ->value{})
|
|
53
|
+
assert (not invoked)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
should "leave alone the output lambda" do
|
|
57
|
+
invoked = false
|
|
58
|
+
@instance.perform(Object.new, [], [], ->{}, ->value{ invoked = true })
|
|
59
|
+
assert (not invoked)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
require 'test/unit'
|
|
2
|
+
require 'noofakku/instruction/open_bracket'
|
|
3
|
+
require 'shoulda'
|
|
4
|
+
require 'ostruct'
|
|
5
|
+
|
|
6
|
+
module Noofakku
|
|
7
|
+
|
|
8
|
+
class OpenBracketTest < Test::Unit::TestCase
|
|
9
|
+
|
|
10
|
+
context "Execution" do
|
|
11
|
+
|
|
12
|
+
setup do
|
|
13
|
+
@instance = OpenBracket.new("[", "]")
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
should "throw on nil processor" do
|
|
17
|
+
assert_raise (RuntimeError) { @instance.perform(nil, Object.new, Object.new, Object.new, Object.new) }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
should "throw on nil memory" do
|
|
21
|
+
assert_raise (RuntimeError) { @instance.perform(Object.new, nil, Object.new, Object.new, Object.new) }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
should "throw on nil program" do
|
|
25
|
+
assert_raise (RuntimeError) { @instance.perform(Object.new, Object.new, nil, Object.new, Object.new) }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
should "throw if instruction pointer is not pointing to an open bracket" do
|
|
29
|
+
spy_processor = OpenStruct.new(instruction_pointer: 0)
|
|
30
|
+
assert_raise (RuntimeError) { @instance.perform(spy_processor, Object.new, "_", nil, nil) }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
should "leave the instruction pointer as is if data pointer points to a cell which value is not zero" do
|
|
34
|
+
spy_processor = OpenStruct.new(instruction_pointer: 0, data_pointer: 0)
|
|
35
|
+
@instance.perform(spy_processor, [42], "[_]_", nil, nil)
|
|
36
|
+
assert_equal 0, spy_processor.instruction_pointer
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
should "change the instruction pointer in order to point to the matching ']' if data pointer points to a cell which value is zero" do
|
|
40
|
+
spy_processor = OpenStruct.new(instruction_pointer: 0, data_pointer: 0)
|
|
41
|
+
@instance.perform(spy_processor, [0], "[_]_", nil, nil)
|
|
42
|
+
assert_equal 2, spy_processor.instruction_pointer
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
require 'test/unit'
|
|
2
|
+
require 'noofakku/instruction/output'
|
|
3
|
+
require 'shoulda'
|
|
4
|
+
require 'ostruct'
|
|
5
|
+
|
|
6
|
+
module Noofakku
|
|
7
|
+
|
|
8
|
+
class OutputTest < Test::Unit::TestCase
|
|
9
|
+
|
|
10
|
+
context "Execution" do
|
|
11
|
+
|
|
12
|
+
setup do
|
|
13
|
+
@instance = Output.new
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
should "throw on nil processor" do
|
|
17
|
+
assert_raise (RuntimeError) { @instance.perform(nil, Object.new, Object.new, Object.new, Object.new) }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
should "throw on nil memory" do
|
|
21
|
+
assert_raise (RuntimeError) { @instance.perform(Object.new, nil, Object.new, Object.new, Object.new) }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
should "throw on nil output" do
|
|
25
|
+
assert_raise (RuntimeError) { @instance.perform(Object.new, Object.new, Object.new, Object.new, nil) }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
should "yield the value of the memory cell addressed by the data pointer" do
|
|
29
|
+
spy_processor = OpenStruct.new(data_pointer: 0)
|
|
30
|
+
output = ->value { assert_equal 42, value }
|
|
31
|
+
@instance.perform(spy_processor, [42], nil, nil, output)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require 'test/unit'
|
|
2
|
+
require 'noofakku/instruction/prev'
|
|
3
|
+
require 'shoulda'
|
|
4
|
+
require 'ostruct'
|
|
5
|
+
|
|
6
|
+
module Noofakku
|
|
7
|
+
|
|
8
|
+
class PrevTest < Test::Unit::TestCase
|
|
9
|
+
|
|
10
|
+
context "Execution" do
|
|
11
|
+
|
|
12
|
+
setup do
|
|
13
|
+
@instance = Prev.new
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
should "throw on nil processor" do
|
|
17
|
+
assert_raise (RuntimeError) { @instance.perform(nil, nil, Object.new, Object.new, Object.new) }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
should "decrement memory data pointer" do
|
|
21
|
+
spy_processor = OpenStruct.new(data_pointer: 0)
|
|
22
|
+
@instance.perform(spy_processor, nil, nil, nil, nil)
|
|
23
|
+
assert_equal -1, spy_processor.data_pointer
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
require 'test/unit'
|
|
2
|
+
require 'noofakku'
|
|
3
|
+
require 'shoulda'
|
|
4
|
+
|
|
5
|
+
module Noofakku
|
|
6
|
+
|
|
7
|
+
class VMTest < Test::Unit::TestCase
|
|
8
|
+
|
|
9
|
+
context 'Execution' do
|
|
10
|
+
|
|
11
|
+
should 'produce "Hello World" in output' do
|
|
12
|
+
input = -> { 0 }
|
|
13
|
+
produced = ''
|
|
14
|
+
output = ->value { produced << value }
|
|
15
|
+
program = '++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.'
|
|
16
|
+
Noofakku::VM.start(program, input, output)
|
|
17
|
+
assert_equal "Hello World!\n", produced
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
should 'produce Fibonacci numbers in output' do
|
|
21
|
+
program = '+.>+.>>>++++++++++[<<<[->>+<<]>>[-<+<+>>]<<<[->+<]>>[-<<+>>]<.>>>-]'
|
|
22
|
+
input = -> { 0 }
|
|
23
|
+
produced = []
|
|
24
|
+
output = ->value { produced << value }
|
|
25
|
+
Noofakku::VM.start(program, input, output)
|
|
26
|
+
assert_equal [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144], produced
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
should 'order numbers in input' do
|
|
30
|
+
program = '>>,[>>,]<< [[-<+<]>[>[>>]<[.[-]<[[>>+<<-]<]>>]>]<<]'
|
|
31
|
+
to_be_sorted = [5, 3, 2, 6, 0].each
|
|
32
|
+
input = -> { to_be_sorted.next }
|
|
33
|
+
produced = []
|
|
34
|
+
output = ->value { produced << value }
|
|
35
|
+
Noofakku::VM.start(program, input, output)
|
|
36
|
+
assert_equal [2, 3, 5, 6], produced
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
require 'test/unit'
|
|
2
|
+
require 'noofakku/processor'
|
|
3
|
+
require 'shoulda'
|
|
4
|
+
require 'ostruct'
|
|
5
|
+
|
|
6
|
+
module Noofakku
|
|
7
|
+
|
|
8
|
+
class ProcessorTest < Test::Unit::TestCase
|
|
9
|
+
|
|
10
|
+
context "Execution" do
|
|
11
|
+
|
|
12
|
+
setup do
|
|
13
|
+
@spy_instruction = SpyInstruction.new
|
|
14
|
+
@instance = Processor.new({"x" => @spy_instruction})
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
should "throw on nil instruction" do
|
|
18
|
+
assert_raise (RuntimeError) { Processor.new(nil) }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
should "throw on nil program" do
|
|
22
|
+
assert_raise (RuntimeError) { @instance.run(nil, Object.new, Object.new, Object.new) }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
should "throw on nil memory" do
|
|
26
|
+
assert_raise (RuntimeError) { @instance.run(Object.new, nil, Object.new, Object.new) }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
should "throw on nil input" do
|
|
30
|
+
assert_raise (RuntimeError) { @instance.run(Object.new, Object.new, nil, Object.new) }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
should "throw on nil output" do
|
|
34
|
+
assert_raise (RuntimeError) { @instance.run(Object.new, Object.new, Object.new, nil) }
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
should "invoke instructions" do
|
|
38
|
+
input = -> {}
|
|
39
|
+
output = ->value {}
|
|
40
|
+
@instance.run('x', [], input, output)
|
|
41
|
+
assert @spy_instruction.invoked
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
class SpyInstruction
|
|
49
|
+
attr_reader :invoked
|
|
50
|
+
def perform(processor, memory, program, input, output); @invoked = true; end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: noofakku
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Mauro Codella
|
|
@@ -9,14 +9,86 @@ autorequire:
|
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
11
|
date: 2013-12-08 00:00:00.000000000 Z
|
|
12
|
-
dependencies:
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: rake
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ! '>='
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '0'
|
|
20
|
+
type: :development
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ! '>='
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: shoulda
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ! '>='
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ! '>='
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: coveralls
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ! '>='
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ! '>='
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0'
|
|
13
55
|
description: A simple brainfuck implementation
|
|
14
56
|
email: mauro.codella@gmail.com
|
|
15
57
|
executables: []
|
|
16
58
|
extensions: []
|
|
17
59
|
extra_rdoc_files: []
|
|
18
60
|
files:
|
|
61
|
+
- .gitignore
|
|
62
|
+
- .travis.yml
|
|
63
|
+
- Gemfile
|
|
64
|
+
- Gemfile.lock
|
|
65
|
+
- README.md
|
|
66
|
+
- Rakefile
|
|
19
67
|
- lib/noofakku.rb
|
|
68
|
+
- lib/noofakku/instruction/closed_bracket.rb
|
|
69
|
+
- lib/noofakku/instruction/dec.rb
|
|
70
|
+
- lib/noofakku/instruction/inc.rb
|
|
71
|
+
- lib/noofakku/instruction/input.rb
|
|
72
|
+
- lib/noofakku/instruction/next.rb
|
|
73
|
+
- lib/noofakku/instruction/noop.rb
|
|
74
|
+
- lib/noofakku/instruction/open_bracket.rb
|
|
75
|
+
- lib/noofakku/instruction/output.rb
|
|
76
|
+
- lib/noofakku/instruction/prev.rb
|
|
77
|
+
- lib/noofakku/processor.rb
|
|
78
|
+
- noofakku.gemspec
|
|
79
|
+
- resources/icon.png
|
|
80
|
+
- test/instruction/closed_bracket_test.rb
|
|
81
|
+
- test/instruction/dec_test.rb
|
|
82
|
+
- test/instruction/inc_test.rb
|
|
83
|
+
- test/instruction/input_test.rb
|
|
84
|
+
- test/instruction/next_test.rb
|
|
85
|
+
- test/instruction/noop_test.rb
|
|
86
|
+
- test/instruction/open_bracket_test.rb
|
|
87
|
+
- test/instruction/output_test.rb
|
|
88
|
+
- test/instruction/prev_test.rb
|
|
89
|
+
- test/noofakku_smoke_test.rb
|
|
90
|
+
- test/processor_test.rb
|
|
91
|
+
- test/test_helper.rb
|
|
20
92
|
homepage: http://github.com/mcodella/noofakku
|
|
21
93
|
licenses:
|
|
22
94
|
- MIT
|