yarbf 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.
Files changed (4) hide show
  1. checksums.yaml +4 -0
  2. data/bin/yarbf +6 -0
  3. data/lib/yarbf.rb +165 -0
  4. metadata +60 -0
@@ -0,0 +1,4 @@
1
+ ---
2
+ SHA512:
3
+ metadata.gz: 22f7d3768f1b31130f5fa1452d52dc98b0a3236b95c4f1e072c10ec8be3f2f9ec194ec195bdb837bec66e1335336e00e692eedcea4233847f327a33576ffd4e6
4
+ data.tar.gz: cc4df3daa804a1ee6f9e555b04d6f1d550d66b782ae02173652e8990a0114904b1115c30b2e5be2d8a1d1c786ac3506b6271116c08594a805135e8f1ebf3a33e
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'yarbf'
4
+
5
+ interpreter = BfInterpreter.new
6
+ interpreter.run(ARGV[0])
@@ -0,0 +1,165 @@
1
+ require 'io/console'
2
+
3
+ class BfInterpreter
4
+ # private constants
5
+ KEY_DEBUG = 'debug'
6
+ KEY_WRAP = 'wrap_around'
7
+ KEY_CELL = 'cell_size'
8
+ private_constant :KEY_DEBUG, :KEY_WRAP, :KEY_CELL
9
+
10
+ def initialize(debug = false, wrap_around = true, cell_size = 8)
11
+ @option = Hash.new
12
+ @option[KEY_DEBUG] = debug
13
+ @option[KEY_WRAP] = wrap_around
14
+ @option[KEY_CELL] = cell_size
15
+ end
16
+
17
+ def debug?
18
+ @option[KEY_DEBUG]
19
+ end
20
+
21
+ def debug=(debug)
22
+ @option[KEY_DEBUG] = debug
23
+ end
24
+
25
+ def wrap_around?
26
+ @option[KEY_WRAP]
27
+ end
28
+
29
+ def wrap_around=(wrap_around)
30
+ @option[KEY_WRAP] = wrap_around
31
+ end
32
+
33
+ def cell_size?
34
+ @option[KEY_CELL]
35
+ end
36
+
37
+ def cell_size=(cell_size)
38
+ @option[KEY_CELL] = cell_size
39
+ end
40
+
41
+ def run(src)
42
+ units = []
43
+
44
+ # construct units
45
+ File.open(src) do |file|
46
+ units = construct_program_units(file)
47
+ end
48
+
49
+ # match brackets
50
+ match_brackets(units)
51
+
52
+ # do interpret
53
+ tape = Array.new
54
+ position = 0
55
+ unit = units[0]
56
+ while unit != nil
57
+ tape[position] = BfCell.new(position) if tape[position] == nil
58
+
59
+ STDERR.printf('%s', unit.instruction) if debug?
60
+
61
+ case unit.instruction
62
+ when '+' then tape[position].increase(1, wrap_around?)
63
+ when '-' then tape[position].decrease(1, wrap_around?)
64
+ when '<' then
65
+ position -= 1
66
+ fail 'Cell position out of bound!' if position < 0
67
+ when '>' then position += 1
68
+ when ',' then
69
+ tape[position].value = STDIN.getch.ord
70
+ when '.' then STDOUT.putc tape[position].value
71
+ when '[' then
72
+ if tape[position].value == 0
73
+ unit = unit.match
74
+ next
75
+ end
76
+ when ']' then
77
+ if tape[position].value != 0
78
+ unit = unit.match
79
+ next
80
+ end
81
+ else fail "Illegal instruction '#{unit.instruction}'!"
82
+ end
83
+
84
+ unit = unit.next
85
+ end
86
+ end
87
+
88
+ def construct_program_units(file)
89
+ units = Array.new
90
+ position = 0
91
+
92
+ file.each_byte do |c|
93
+ case c.chr
94
+ when '+', '-', '<', '>', '[', ']', '.', ',' then
95
+ unit = BfProgramUnit.new(c.chr)
96
+ units[position - 1].next = unit if position > 0
97
+ units[position] = unit
98
+ position += 1
99
+ else
100
+ # other characters are considered as comments, do nothing
101
+ end
102
+ end
103
+
104
+ units
105
+ end
106
+
107
+ def match_brackets(units)
108
+ units.each_index do |i|
109
+ if units[i].instruction == '['
110
+ level = 0
111
+ units[i + 1 .. units.length - 1].each_index do |j|
112
+ j += i + 1
113
+ if units[j].instruction == '['
114
+ level += 1
115
+ elsif units[j].instruction == ']'
116
+ if level > 0
117
+ level -= 1
118
+ else
119
+ units[i].match = units[j]
120
+ units[j].match = units[i]
121
+ break
122
+ end
123
+ end
124
+ end
125
+ fail 'Unmatched brackets!' if level > 0
126
+ end
127
+ end
128
+ end
129
+
130
+ private :construct_program_units, :match_brackets
131
+
132
+ class BfCell
133
+ attr_accessor :position, :value
134
+
135
+ def initialize(position, value = 0)
136
+ @position = position
137
+ @value = value
138
+ end
139
+
140
+ def increase(increment = 1, wrap_around = true)
141
+ if !wrap_around && (@value + increment < 0 || @value + increment > 255)
142
+ fail 'Overflow or underflow happened while forbidden!'
143
+ else
144
+ @value = (@value + increment) % 256
145
+ end
146
+ end
147
+
148
+ def decrease(decrement = 1, wrap_around = true)
149
+ self.increase(-decrement, wrap_around)
150
+ end
151
+ end
152
+
153
+ class BfProgramUnit
154
+ attr_reader :instruction
155
+
156
+ attr_accessor :match
157
+ attr_accessor :next
158
+
159
+ def initialize(instruction)
160
+ @instruction = instruction
161
+ @match = nil
162
+ @next = nil
163
+ end
164
+ end
165
+ end
metadata ADDED
@@ -0,0 +1,60 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: yarbf
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Chaos Shen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-12-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: io-console
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.4'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.4'
27
+ description: yarbf, is a simple Brainfuck interpreter in Ruby.
28
+ email: chaosdefinition@hotmail.com
29
+ executables:
30
+ - yarbf
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - bin/yarbf
35
+ - lib/yarbf.rb
36
+ homepage: http://github.com/chaosdefinition/yarbf
37
+ licenses:
38
+ - MIT
39
+ metadata: {}
40
+ post_install_message:
41
+ rdoc_options: []
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ required_rubygems_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ requirements: []
55
+ rubyforge_project:
56
+ rubygems_version: 2.4.5.1
57
+ signing_key:
58
+ specification_version: 4
59
+ summary: Yet another Brainfuck interpreter in Ruby
60
+ test_files: []