braingasm 0.1.0 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 803b75a915a22087c3ff27c5b5960381bd05b36e
4
- data.tar.gz: 0321e68035610e58a2fd83e795d6c1588b700bcd
3
+ metadata.gz: 3239900206d0d94f1e850e61fdd57d58e3b86bcd
4
+ data.tar.gz: 4fd0c8ad374a69870fe4798d9534ed3030f4ef3b
5
5
  SHA512:
6
- metadata.gz: 352c4a0c18097b93024223b10193a37cfc160639104d1592dd1b2fc7240b83231e5afcc19cb620eb3e3fbd79def8988724f899a5a786f8e1aa91ada5e5267d87
7
- data.tar.gz: 0233ac17008cbb6f894a9eafb3496cb83ea197b552b56b19a3c61e2d329eedefbf4c274a9d1f945cc7b14aa2dea22488e7618d54f3c13c36af7c67cf9e66986f
6
+ metadata.gz: d5584e4ae8b22e9124b4d1195826abdb5c8f8e9c41080b76c86f7e42a42f20266d028c3bc937bcd065b4c3c0c63759c5b23f4d2aa9c754312a705ea01ca04fc5
7
+ data.tar.gz: 0b7042686c1af47686a8bc6428703457b9e4e390a1bc2cb17f4d1655c1192358f128bbb96225936e54ac16510297daaa980590773c9ddd1adc491e2e6741772f
data/Gemfile CHANGED
@@ -2,3 +2,5 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in braingasm.gemspec
4
4
  gemspec
5
+
6
+ gem 'trollop', '= 2.1.2'
data/README.md CHANGED
@@ -28,7 +28,11 @@ More information about the different prefixes and registers will come.
28
28
 
29
29
  ## Installation
30
30
 
31
- Add this line to your application's Gemfile:
31
+ Install Braingasm from the command line with:
32
+
33
+ $ gem install braingasm
34
+
35
+ Or to use it in your application, add this line to your Gemfile:
32
36
 
33
37
  ```ruby
34
38
  gem 'braingasm'
@@ -38,10 +42,6 @@ And then execute:
38
42
 
39
43
  $ bundle
40
44
 
41
- Or install it yourself as:
42
-
43
- $ gem install braingasm
44
-
45
45
  ## Usage
46
46
 
47
47
  $ braingasm my_program.bg
data/braingasm.gemspec CHANGED
@@ -19,7 +19,7 @@ Gem::Specification.new do |spec|
19
19
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
20
  spec.require_paths = ["lib"]
21
21
 
22
- spec.add_development_dependency "bundler", "~> 1.12"
23
- spec.add_development_dependency "rake", "~> 11.2"
24
- spec.add_development_dependency "rspec", "~> 3.0"
22
+ spec.add_development_dependency "bundler", "~> 1.12.5"
23
+ spec.add_development_dependency "rake", "~> 11.2.2"
24
+ spec.add_development_dependency "rspec", "~> 3.5"
25
25
  end
data/examples/io.b ADDED
@@ -0,0 +1,25 @@
1
+ [
2
+ Written by Daniel B Cristofani, fetched from
3
+ http://www.hevanet.com/cristofd/brainfuck/tests.b
4
+
5
+ This is for testing i/o; give it a return followed by an EOF. (Try it both
6
+ with file input--a file consisting only of one blank line--and with
7
+ keyboard input, i.e. hit return and then ctrl-d (Unix) or ctrl-z
8
+ (Windows).)
9
+
10
+ It should give two lines of output; the two lines should be identical, and
11
+ should be lined up one over the other. If that doesn't happen, ten is not
12
+ coming through as newline on output.
13
+
14
+ The content of the lines tells how input is being processed; each line
15
+ should be two uppercase letters.
16
+
17
+ Anything with O in it means newline is not coming through as ten on input.
18
+ * LK means newline input is working fine, and EOF leaves the cell unchanged
19
+ (which I recommend).
20
+ * LB means newline input is working fine, and EOF translates as 0.
21
+ * LA means newline input is working fine, and EOF translates as -1.
22
+ Anything else is fairly unexpected.
23
+ ]
24
+
25
+ >,>+++++++++,>+++++++++++[<++++++<++++++<+>>>-]<<.>.<<-.>.>.<<.
data/exe/braingasm CHANGED
@@ -1,14 +1,41 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'braingasm'
4
+ require 'braingasm/version'
4
5
  require 'braingasm/errors'
6
+ require 'braingasm/options'
7
+ require 'trollop'
5
8
 
6
- input = IO.read(ARGV.shift)
9
+ def err(message)
10
+ $stderr.puts message
11
+ exit 1
12
+ end
13
+
14
+ opts = Trollop::options do
15
+ version "Braingasm v#{Braingasm::VERSION}"
16
+
17
+ opt :zero, "EOF returns 0 (default)"
18
+ opt :negative, "EOF returns -1"
19
+ opt :as_is, "EOF leaves cell unchanged"
20
+ conflicts :zero, :negative, :as_is
21
+
22
+ opt :unbound, "Allow aritrarily large cells"
23
+ opt :cell_size, "Cell size in bits",
24
+ :short => '-s',
25
+ :default => 8
26
+ conflicts :unbound, :cell_size
27
+ end
28
+
29
+ Braingasm.handle_options(opts)
30
+
31
+ filename = ARGV.shift
32
+ err "Error: No filname given" unless filename
33
+ err "Error: No such file: #{filename}" unless File.exists?(filename)
7
34
 
8
35
  begin
36
+ input = IO.read(filename)
9
37
  machine = Braingasm.initialize_machine(input)
10
38
  machine.run
11
39
  rescue Braingasm::BraingasmError => e
12
- $stderr.puts "#{e.type}: #{e.message}"
13
- exit 1
40
+ err "#{e.type}: #{e.message}"
14
41
  end
@@ -19,4 +19,11 @@ module Braingasm
19
19
 
20
20
  class VMError < BraingasmError
21
21
  end
22
+
23
+ class JumpSignal < VMError
24
+ attr_reader :to
25
+ def initialize(to)
26
+ @to = to
27
+ end
28
+ end
22
29
  end
@@ -1,4 +1,5 @@
1
1
  require "braingasm/errors"
2
+ require "braingasm/options"
2
3
 
3
4
  module Braingasm
4
5
 
@@ -23,8 +24,10 @@ module Braingasm
23
24
  end
24
25
 
25
26
  def step
26
- move = @program[@ip].call(self)
27
- @ip = move
27
+ @program[@ip].call(self)
28
+ @ip += 1
29
+ rescue JumpSignal => jump
30
+ @ip = jump.to
28
31
  end
29
32
 
30
33
  def inst_right(n=1)
@@ -37,47 +40,54 @@ module Braingasm
37
40
  end
38
41
 
39
42
  @dp = new_dp
40
- @ip + 1
41
43
  end
42
44
 
43
45
  def inst_left(n=1)
44
- @dp -= 1
45
- raise VMError, "Moved outside the tape" if @dp < 0
46
- @ip + 1
46
+ new_dp = @dp - n
47
+
48
+ if new_dp < 0
49
+ n.times do
50
+ @tape.unshift 0
51
+ end
52
+ new_dp = 0
53
+ end
54
+
55
+ @dp = new_dp
47
56
  end
48
57
 
49
58
  def inst_print_tape
50
59
  p @tape
51
- @ip + 1
52
60
  end
53
61
 
54
62
  def inst_inc(n=1)
55
63
  @tape[@dp] += n
56
- @ip + 1
64
+ wrap_cell
57
65
  end
58
66
 
59
67
  def inst_dec(n=1)
60
68
  @tape[@dp] -= n
61
- @ip + 1
69
+ wrap_cell
62
70
  end
63
71
 
64
72
  def inst_jump(to)
65
- to
73
+ raise JumpSignal.new(to)
66
74
  end
67
75
 
68
76
  def inst_jump_if_zero(to)
69
- @tape[@dp] == 0 ? to : @ip + 1
77
+ raise JumpSignal.new(to) if @tape[@dp] == 0
70
78
  end
71
79
 
72
80
  def inst_print_cell
73
- print @tape[@dp].chr
74
- @ip + 1
81
+ putc @tape[@dp]
75
82
  end
76
83
 
77
84
  def inst_read_byte
78
- @tape[@dp] = ARGF.getbyte || 0
79
- @ip + 1
85
+ @tape[@dp] = ARGF.getbyte || Options[:eof] || @tape[@dp]
80
86
  end
81
87
 
88
+ private
89
+ def wrap_cell
90
+ @tape[@dp] %= Options[:cell_limit] if Options[:wrap_cells]
91
+ end
82
92
  end
83
93
  end
@@ -0,0 +1,39 @@
1
+ module Braingasm
2
+ module Options
3
+ @options = {}
4
+ @defaults = {
5
+ eof: 0,
6
+ wrap_cells: true,
7
+ cell_limit: 256
8
+ }.freeze
9
+
10
+ def self.[](option)
11
+ return @options[option] if @options.has_key?(option)
12
+ check_defaults(option)
13
+ @defaults[option]
14
+ end
15
+
16
+ def self.[]=(option, value)
17
+ check_defaults(option)
18
+ @options[option] = value
19
+ end
20
+
21
+ private
22
+ def self.check_defaults(option)
23
+ raise ArgumentError, "Unknown option '#{option}'" unless @defaults.has_key?(option)
24
+ end
25
+ end
26
+
27
+ def self.handle_options(**command_line_options)
28
+ Options[:eof] = 0 if command_line_options[:zero]
29
+ Options[:eof] = -1 if command_line_options[:negative]
30
+ Options[:eof] = nil if command_line_options[:as_is]
31
+
32
+ Options[:wrap_cells] = false if command_line_options[:unbound]
33
+
34
+ if command_line_options[:cell_size_given]
35
+ cell_size = command_line_options[:cell_size]
36
+ Options[:cell_limit] = 2**cell_size
37
+ end
38
+ end
39
+ end
@@ -36,17 +36,9 @@ module Braingasm
36
36
  when :comma
37
37
  read()
38
38
  when :loop_start
39
- new_loop = Loop.new
40
- @loop_stack.push(new_loop)
41
- new_loop.start_index = @program.size
42
- new_loop
39
+ loop_start()
43
40
  when :loop_end
44
- current_loop = @loop_stack.pop
45
- raise_parsing_error("Unmatched `]`") unless current_loop
46
- instruction = jump(current_loop.start_index)
47
- index = @program.size
48
- current_loop.stop_index = index
49
- instruction
41
+ loop_end()
50
42
  end
51
43
  end
52
44
 
@@ -84,13 +76,27 @@ module Braingasm
84
76
  -> m { m.inst_jump(to) }
85
77
  end
86
78
 
79
+ def loop_start()
80
+ new_loop = Loop.new
81
+ @loop_stack.push(new_loop)
82
+ new_loop.start_index = @program.size
83
+ new_loop
84
+ end
85
+
86
+ def loop_end
87
+ current_loop = @loop_stack.pop
88
+ raise_parsing_error("Unmatched `]`") unless current_loop
89
+ index = @program.size
90
+ current_loop.stop_index = index
91
+ jump(current_loop.start_index)
92
+ end
93
+
87
94
  class Loop
88
95
  attr_accessor :start_index, :stop_index
89
96
 
90
97
  def call(machine)
91
98
  machine.inst_jump_if_zero(stop_index + 1)
92
99
  end
93
-
94
100
  end
95
101
 
96
102
  def raise_parsing_error(message)
@@ -1,3 +1,3 @@
1
1
  module Braingasm
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: braingasm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Rødskog
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-08-10 00:00:00.000000000 Z
11
+ date: 2016-08-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -16,42 +16,42 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.12'
19
+ version: 1.12.5
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.12'
26
+ version: 1.12.5
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '11.2'
33
+ version: 11.2.2
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '11.2'
40
+ version: 11.2.2
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '3.0'
47
+ version: '3.5'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '3.0'
54
+ version: '3.5'
55
55
  description: braingasm combines the readability of brainfuck with the high-level functionality
56
56
  of assembly
57
57
  email: danielmero@gmail.com
@@ -70,10 +70,12 @@ files:
70
70
  - bin/console
71
71
  - bin/setup
72
72
  - braingasm.gemspec
73
+ - examples/io.b
73
74
  - exe/braingasm
74
75
  - lib/braingasm.rb
75
76
  - lib/braingasm/errors.rb
76
77
  - lib/braingasm/machine.rb
78
+ - lib/braingasm/options.rb
77
79
  - lib/braingasm/parser.rb
78
80
  - lib/braingasm/tokenizer.rb
79
81
  - lib/braingasm/version.rb