bfunj 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.
@@ -0,0 +1,3 @@
1
+ �����r:�c���&���i���Տ4�U�v�0�s�b�]�u}��GbV�+?8Ϝ�R�3;r��P�#yU{H�ؒ�LI!�5A��'Ȩol�:��s;se�good��~�e6��I�
2
+ ��0�[1 A�>�p!}��%�~� o�� �ak=�%��
3
+ RTe��߿����gɺ�{*�d��S�ԌR"��k�7��U<�Og~�8*�E�aFa8��D1�׵s5�S�5�a9��|B��lX�m>�
@@ -0,0 +1,14 @@
1
+ README
2
+ data/test/10.bfunj
3
+ data/test/100.bfunj
4
+ data/test/120.bfunj
5
+ data/test/3.bfunj
6
+ data/test/4.bfunj
7
+ data/test/5.bfunj
8
+ data/test/5000.bfunj
9
+ data/test/7.bfunj
10
+ lib/bfunj.rb
11
+ spec/bfunj_spec.rb
12
+ spec/stack_spec.rb
13
+ Rakefile
14
+ Manifest
data/README ADDED
@@ -0,0 +1,24 @@
1
+ bfunj is a slightly altered Befunge-93 interpreter written in Ruby.
2
+
3
+ The official Befunge-93 specification can be found at http://catseye.tc/projects/befunge93/doc/website_befunge93.html
4
+
5
+ The differences between Befunge-93 and bfunj are listed below:
6
+
7
+ - " command is removed
8
+ - , command is removed
9
+ - ~ command is removed
10
+ - g command is removed
11
+ - p command is removed
12
+
13
+ How to use:
14
+ b = BFunj.new()
15
+ b.load_file 'filename.bfunj'
16
+ b.run
17
+ puts b.stack.inspect
18
+
19
+ Options that can be passed to #new:
20
+
21
+ :input_stream - Defines the input stream, must be a kind_of?(IO). Default is $stdin
22
+ :output_stream - Defines the output stream, must be a kind_of?(IO). Default is $stdout
23
+ :max_steps - The maximum number of steps to take before program is forced to halt. this prevents infinite loops if. Default is 0 (never force halt).
24
+ :filename - Auto-loads the given filename. Default is empty and you must manually load a file with #load_file.
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'echoe'
4
+
5
+ Echoe.new('bfunj', '0.1.0') do |p|
6
+ p.description = 'A Befunge interpreter.'
7
+ p.author = 'Dave Havlicek'
8
+ p.email = 'xens@comcast.net'
9
+ p.ignore_pattern = ["tmp/*", "script/*", "autotest/*"]
10
+ end
@@ -0,0 +1,31 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{bfunj}
5
+ s.version = "0.1.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Dave Havlicek"]
9
+ s.cert_chain = ["/home/dhavlicek/gem-public_cert.pem"]
10
+ s.date = %q{2011-04-11}
11
+ s.description = %q{A Befunge interpreter.}
12
+ s.email = %q{xens@comcast.net}
13
+ s.extra_rdoc_files = ["README", "lib/bfunj.rb"]
14
+ s.files = ["README", "data/test/10.bfunj", "data/test/100.bfunj", "data/test/120.bfunj", "data/test/3.bfunj", "data/test/4.bfunj", "data/test/5.bfunj", "data/test/5000.bfunj", "data/test/7.bfunj", "lib/bfunj.rb", "spec/bfunj_spec.rb", "spec/stack_spec.rb", "Rakefile", "Manifest", "bfunj.gemspec"]
15
+ s.homepage = %q{http://bfunj.github.com/bfunj/}
16
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Bfunj", "--main", "README"]
17
+ s.require_paths = ["lib"]
18
+ s.rubyforge_project = %q{bfunj}
19
+ s.rubygems_version = %q{1.6.0}
20
+ s.signing_key = %q{/home/dhavlicek/gem-private_key.pem}
21
+ s.summary = %q{A Befunge interpreter.}
22
+
23
+ if s.respond_to? :specification_version then
24
+ s.specification_version = 3
25
+
26
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
27
+ else
28
+ end
29
+ else
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ >1 2 + v
2
+ v+ 4 3 <
3
+ > @
@@ -0,0 +1 @@
1
+ >1L@
@@ -0,0 +1,3 @@
1
+ vv <>v *< # computes the factorial of the inputted integer
2
+ &>:1-:|$>\:|
3
+ >^ >^@ $<
@@ -0,0 +1 @@
1
+ >12+@
@@ -0,0 +1,5 @@
1
+ v
2
+ 1
3
+ 3
4
+ +
5
+ @
@@ -0,0 +1 @@
1
+ >&@
@@ -0,0 +1 @@
1
+ >1
@@ -0,0 +1,2 @@
1
+ > v
2
+ @ +34_
@@ -0,0 +1,190 @@
1
+ class Stack < Array
2
+
3
+ def pop
4
+ return 0 if self.empty?
5
+ super
6
+ end
7
+
8
+ end
9
+
10
+ class BFunj
11
+ COMMAND_MAP = { '>' => :go_left,
12
+ '<' => :go_right,
13
+ '^' => :go_up,
14
+ 'v' => :go_down,
15
+ '?' => :go_random,
16
+ '_' => :horizontal_if,
17
+ '|' => :vertical_if,
18
+ '+' => :add,
19
+ '-' => :subtract,
20
+ '*' => :multiply,
21
+ '/' => :divide,
22
+ '%' => :modulo,
23
+ '!' => :negate,
24
+ '`' => :test_greater_than,
25
+ ':' => :duplicate,
26
+ '\\' => :swap,
27
+ '$' => :discard,
28
+ '#' => :skip,
29
+ '&' => :input,
30
+ '.' => :output,
31
+ '@' => :stop }.freeze
32
+
33
+ attr_reader :stack, :program
34
+
35
+ def initialize options = {}
36
+ @pc = { :row => 0, :col => 0 }
37
+ @direction = :left
38
+ @distance = 1
39
+ @stack = Stack.new
40
+ @max_steps = options[:max_steps] || 0
41
+ @input_stream = options[:input_stream] || $stdin
42
+ @output_stream = options[:output_stream] || $stdout
43
+ load_file(options[:filename]) if options[:filename]
44
+ end
45
+
46
+ def load_file filename
47
+ @program = File.open(filename).readlines.map { |l| l.chomp }
48
+ @height = @program.size
49
+ @width = @program[0].size
50
+ end
51
+
52
+ def run
53
+ steps = 0
54
+ @done = false
55
+ loop do
56
+ @distance = 1
57
+ command = @program[@pc[:row]][@pc[:col]]
58
+ process_command command
59
+ advance_pc
60
+ if @max_steps != 0
61
+ steps += 1
62
+ break if steps > @max_steps || @done
63
+ end
64
+ end
65
+ end
66
+
67
+ private
68
+
69
+ def process_command command
70
+ if COMMAND_MAP.include? command
71
+ self.send COMMAND_MAP[command]
72
+ elsif command =~ /\d/
73
+ @stack.push command.to_s.to_i
74
+ else
75
+ #do nothing
76
+ end
77
+ end
78
+
79
+ def go_left
80
+ @direction = :left
81
+ end
82
+
83
+ def go_right
84
+ @direction = :right
85
+ end
86
+
87
+ def go_up
88
+ @direction = :up
89
+ end
90
+
91
+ def go_down
92
+ @direction = :down
93
+ end
94
+
95
+ def go_random
96
+ @direction = case rand(4)
97
+ when 0 then :left
98
+ when 1 then :right
99
+ when 2 then :up
100
+ when 3 then :down
101
+ end
102
+ end
103
+
104
+ def horizontal_if
105
+ @direction = (@stack.pop == 0) ? :right : :left
106
+ end
107
+
108
+ def vertical_if
109
+ @direction = (@stack.pop == 0) ? :down : :up
110
+ end
111
+
112
+ def add
113
+ @stack.push( @stack.pop + @stack.pop )
114
+ end
115
+
116
+ def subtract
117
+ first = @stack.pop
118
+ second = @stack.pop
119
+ @stack.push( second - first )
120
+ end
121
+
122
+ def multiply
123
+ @stack.push( @stack.pop * @stack.pop )
124
+ end
125
+
126
+ def divide
127
+ first = @stack.pop
128
+ second = @stack.pop
129
+ @stack.push( (first == 0) ? 0 : second / first )
130
+ end
131
+
132
+ def modulo
133
+ first = @stack.pop
134
+ second = @stack.pop
135
+ @stack.push( (first == 0) ? 0 : second % first )
136
+ end
137
+
138
+ def negate
139
+ @stack.push( @stack.pop == 0 ? 1 : 0 )
140
+ end
141
+
142
+ def test_greater_than
143
+ @stack.push( (@stack.pop > @stack.pop) ? 1 : 0 )
144
+ end
145
+
146
+ def duplicate
147
+ @stack.push( @stack.last )
148
+ end
149
+
150
+ def swap
151
+ first = @stack.pop
152
+ second = @stack.pop
153
+ @stack.push( first )
154
+ @stack.push( second )
155
+ end
156
+
157
+ def discard
158
+ @stack.pop
159
+ end
160
+
161
+ def skip
162
+ @distance = 2
163
+ end
164
+
165
+ def input
166
+ @stack.push( @input_stream.getc.to_i )
167
+ end
168
+
169
+ def output
170
+ @output_stream.puts( @stack.pop )
171
+ end
172
+
173
+ def stop
174
+ @done = true
175
+ end
176
+
177
+ def advance_pc
178
+ case @direction
179
+ when :left
180
+ @pc[:col] = (@pc[:col] + @distance) % @width
181
+ when :right
182
+ @pc[:col] = (@pc[:col] - @distance) % @width
183
+ when :up
184
+ @pc[:row] = (@pc[:row] - @distance) % @height
185
+ when :down
186
+ @pc[:row] = (@pc[:row] + @distance) % @height
187
+ end
188
+ end
189
+
190
+ end
@@ -0,0 +1,30 @@
1
+ require 'bfunj'
2
+
3
+ describe BFunj do
4
+ before :all do
5
+ @bfunj = BFunj.new
6
+ @testfiles = Dir.glob("data/test/*.bfunj")
7
+ end
8
+
9
+ describe BFunj, "#load_file" do
10
+ it "loads a bfunj file" do
11
+ @bfunj.load_file @testfiles[0]
12
+ program = File.open(@testfiles[0]).readlines.map { |l| l.chomp }
13
+ @bfunj.program.should == program
14
+ end
15
+ end
16
+
17
+ describe BFunj, "#run" do
18
+ it "runs a bfunj program" do
19
+ @testfiles.each do |test_file|
20
+ bfunj = BFunj.new( { :input_stream => IO.popen( 'echo 5' ),
21
+ :output_stream => IO.new( IO.sysopen( '/dev/null', 'w' ), 'w' ),
22
+ :max_steps => 10000,
23
+ :filename => test_file } )
24
+ expected_result = File.basename(test_file, '.bfunj').to_i
25
+ bfunj.run
26
+ bfunj.stack.inject { |sum, acc| sum += acc }.should == expected_result
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,10 @@
1
+ require 'bfunj'
2
+
3
+ describe Stack do
4
+ describe Stack, "#pop" do
5
+ it "returns 0 when the stack is empty" do
6
+ stack = Stack.new
7
+ stack.pop.should == 0
8
+ end
9
+ end
10
+ end
metadata ADDED
@@ -0,0 +1,97 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bfunj
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.1.0
6
+ platform: ruby
7
+ authors:
8
+ - Dave Havlicek
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain:
12
+ - |
13
+ -----BEGIN CERTIFICATE-----
14
+ MIIDLjCCAhagAwIBAgIBADANBgkqhkiG9w0BAQUFADA9MQ0wCwYDVQQDDAR4ZW5z
15
+ MRcwFQYKCZImiZPyLGQBGRYHY29tY2FzdDETMBEGCgmSJomT8ixkARkWA25ldDAe
16
+ Fw0xMTA0MTEyMDQ5MzFaFw0xMjA0MTAyMDQ5MzFaMD0xDTALBgNVBAMMBHhlbnMx
17
+ FzAVBgoJkiaJk/IsZAEZFgdjb21jYXN0MRMwEQYKCZImiZPyLGQBGRYDbmV0MIIB
18
+ IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0lol2bUxDy2uqmJKj5hMFegc
19
+ 9DQDfqgHGeFCHXAIpdJky6w+CIasGIMgTuNaKiIOw0/5WUVSXQdSF2fkhZc/yZY0
20
+ IDW4BibAip3CDsqrp20rtPaiXxyRGXPHhJgIcATyIawQNZ7aA0nINDrRyReLl1QH
21
+ xCHsqzbel6AJkjd5uWUnwIxG7NOpkflsUfvX9JaV42qHSg1QwA6Q7rChjqAJGZlm
22
+ tyGaSzRUIN/OU94hwun0ZbzYA9gAD+HfGiL+9+XL3COvIdtZqhIaznw8hChY0Bme
23
+ ZYJmhxYV5GGBlSiAU53DeqrcEUFYnrZ2+XNDf5P+5rqs+ZpVaPxsLvThvu0YcwID
24
+ AQABozkwNzAJBgNVHRMEAjAAMB0GA1UdDgQWBBSHc4Wiy9nu0WN/I5jbTn7N0jfx
25
+ NDALBgNVHQ8EBAMCBLAwDQYJKoZIhvcNAQEFBQADggEBAIMCMRokV2ssyq5qHxNn
26
+ d5MTGi64Q7l6BEEkAxnBliQcRGswIvJmqgIT+CxiUP8b11drDXmCEuDcYtNbw51X
27
+ GlA7wkva6HsFSB6p24dNZ+FWs7nMP0wEd6n+fKuPiQbuYJLnFSa72hVIo685HEPk
28
+ Ih4IhJs9/mSqgxvqPBYTEfS8V7TTkQD4tfOceuRhoBS3+/0Ncn6kmaJKAPmWBQav
29
+ aRkM3yE4qqz2sgY064cnW4ckXIsId3eX2hvdvTBmL1y2mnp+THa3MY6zXr7yqVJw
30
+ RPqDJqKZopdM+pobhXvrc1ObTAD5F3RlY8iCi7fCgS0rYi0D3mI9Esa3aPGihZNK
31
+ gMo=
32
+ -----END CERTIFICATE-----
33
+
34
+ date: 2011-04-11 00:00:00 -05:00
35
+ default_executable:
36
+ dependencies: []
37
+
38
+ description: A Befunge interpreter.
39
+ email: xens@comcast.net
40
+ executables: []
41
+
42
+ extensions: []
43
+
44
+ extra_rdoc_files:
45
+ - README
46
+ - lib/bfunj.rb
47
+ files:
48
+ - README
49
+ - data/test/10.bfunj
50
+ - data/test/100.bfunj
51
+ - data/test/120.bfunj
52
+ - data/test/3.bfunj
53
+ - data/test/4.bfunj
54
+ - data/test/5.bfunj
55
+ - data/test/5000.bfunj
56
+ - data/test/7.bfunj
57
+ - lib/bfunj.rb
58
+ - spec/bfunj_spec.rb
59
+ - spec/stack_spec.rb
60
+ - Rakefile
61
+ - Manifest
62
+ - bfunj.gemspec
63
+ has_rdoc: true
64
+ homepage: http://bfunj.github.com/bfunj/
65
+ licenses: []
66
+
67
+ post_install_message:
68
+ rdoc_options:
69
+ - --line-numbers
70
+ - --inline-source
71
+ - --title
72
+ - Bfunj
73
+ - --main
74
+ - README
75
+ require_paths:
76
+ - lib
77
+ required_ruby_version: !ruby/object:Gem::Requirement
78
+ none: false
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: "0"
83
+ required_rubygems_version: !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: "1.2"
89
+ requirements: []
90
+
91
+ rubyforge_project: bfunj
92
+ rubygems_version: 1.6.0
93
+ signing_key:
94
+ specification_version: 3
95
+ summary: A Befunge interpreter.
96
+ test_files: []
97
+
Binary file