remian 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.
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ .bundle
2
+ log/
3
+ tmp/
4
+ .sass-cache/
5
+ .DS_Store
data/.gitkeep ADDED
File without changes
data/AUTHORS.md ADDED
@@ -0,0 +1,2 @@
1
+ # Authors
2
+ * [Michael Mokrysz](https://46bit.com)
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in spotigit.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,18 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ remian (0.1.0)
5
+ term-ansicolor (~> 1.0.7)
6
+ thor (~> 0.16.0)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ term-ansicolor (1.0.7)
12
+ thor (0.16.0)
13
+
14
+ PLATFORMS
15
+ ruby
16
+
17
+ DEPENDENCIES
18
+ remian!
data/LICENSE.md ADDED
@@ -0,0 +1,24 @@
1
+ This is free and unencumbered software released into the public domain.
2
+
3
+ Anyone is free to copy, modify, publish, use, compile, sell, or
4
+ distribute this software, either in source code form or as a compiled
5
+ binary, for any purpose, commercial or non-commercial, and by any
6
+ means.
7
+
8
+ In jurisdictions that recognize copyright laws, the author or authors
9
+ of this software dedicate any and all copyright interest in the
10
+ software to the public domain. We make this dedication for the benefit
11
+ of the public at large and to the detriment of our heirs and
12
+ successors. We intend this dedication to be an overt act of
13
+ relinquishment in perpetuity of all present and future rights to this
14
+ software under copyright law.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ For more information, please refer to http://unlicense.org.
data/README.md ADDED
@@ -0,0 +1,5 @@
1
+ # Remian
2
+ A baby virtual machine built in Ruby. Designed to a Von Neumann architecture and a RISC mindset.
3
+
4
+ ## Why the name?
5
+ I decided to build Remian just after waking up, so it seemed apt to name it after a phase of sleeping. I picked [REM](http://en.wikipedia.org/wiki/Rapid_eye_movement_sleep) because `Non-REMian` or `Phase 3ian` would be a terrible name.
data/bin/.gitkeep ADDED
File without changes
data/bin/remian ADDED
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "thor"
4
+ require "remian"
5
+
6
+ module Remian
7
+ class Thorian < Thor
8
+ desc "execute FILEPATH", "Runs given .rem file."
9
+
10
+ method_option :clock_speed, default: 30, aliases: "-c", desc: "Machine clock speed in Hz (default 50)."
11
+ method_option :memory_size, default: 1024, aliases: "-m", desc: "Size of machine memory (default 1024)."
12
+
13
+ def execute filepath
14
+ if File.exist? filepath
15
+ data = File.read filepath
16
+ else
17
+ Remian.say "Provided file #{filepath} does not exist."
18
+ exit
19
+ end
20
+
21
+ control = Remian::Control.new data, {clock_speed: options[:clock_speed].to_i, memory_size: options[:memory_size].to_i}
22
+ control.start
23
+ end
24
+ end
25
+
26
+ Remian::Thorian.start
27
+ end
28
+ class ThorExample < Thor
29
+ desc "start", "start server"
30
+ method_option :environment,:default => "development", :aliases => "-e",
31
+ :desc => "which environment you want server run."
32
+ method_option :daemon, :type => :boolean, :default => false, :aliases => "-d",
33
+ :desc => "running on daemon mode?"
34
+ def start
35
+ puts "start #{options.inspect}"
36
+ end
37
+
38
+ desc "stop" ,"stop server"
39
+ method_option :delay, :default => 0, :aliases => "-w",
40
+ :desc => "wait server finish it's job"
41
+ def stop
42
+ puts "stop"
43
+ end
44
+ end
data/lib/.gitkeep ADDED
File without changes
data/lib/remian.rb ADDED
@@ -0,0 +1,12 @@
1
+ require "term/ansicolor"
2
+ require "./lib/remian/control"
3
+
4
+ module Remian
5
+ def self.say message, colour_hash
6
+ unless colour_hash.nil? || !Term::ANSIColor.respond_to?(colour_hash)
7
+ extend Term::ANSIColor
8
+ message = Term::ANSIColor.method(colour_hash.to_s).call(message)
9
+ end
10
+ puts message
11
+ end
12
+ end
File without changes
@@ -0,0 +1,14 @@
1
+ module Remian
2
+ class Clock
3
+ attr_accessor :speed, :delay
4
+
5
+ def initialize speed
6
+ @speed = speed.to_f
7
+ @delay = 1.0 / @speed
8
+ end
9
+
10
+ def tick_delay
11
+ sleep @delay
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,59 @@
1
+ # load initial instructions + data
2
+ # run initial instruction
3
+ # handle instruction register changes
4
+ # fetch + execute instruction register memory location
5
+
6
+ require "remian/clock"
7
+ require "remian/memory"
8
+ require "remian/decoder"
9
+ require "remian/instruction_set"
10
+
11
+ module Remian
12
+ class Control
13
+ attr_accessor :options
14
+ attr_accessor :clock
15
+ attr_accessor :memory
16
+ attr_accessor :decoder
17
+ attr_accessor :registers
18
+ attr_accessor :instruction_set
19
+
20
+ def initialize data, options = {}
21
+ @options = option_defaults.merge options
22
+
23
+ @registers = {address: nil}
24
+ @clock = Clock.new @options[:clock_speed]
25
+ @decoder = Decoder.new
26
+
27
+ @memory = Memory.new @options[:memory_size]
28
+ @memory.write_data data
29
+
30
+ @instruction_set = InstructionSet.new @memory, @registers
31
+ end
32
+
33
+ def start start_address = 1
34
+ @registers[:address] = start_address
35
+
36
+ while @clock.tick_delay
37
+ cycle
38
+ end
39
+ end
40
+
41
+ protected
42
+ def option_defaults
43
+ {clock_speed: 30, memory_size: 1024}
44
+ end
45
+
46
+ def cycle
47
+ address_contents = @memory.read @registers[:address]
48
+ @registers[:address] = @registers[:address] + 1
49
+
50
+ instruction = @decoder.parse address_contents
51
+ if not instruction[:opcode].nil? and @instruction_set.respond_to? instruction[:opcode]
52
+ Remian.say "> #{address_contents}", :green
53
+ @instruction_set.send(instruction[:opcode], instruction[:data])
54
+ else
55
+ Remian.say "Instruction '#{instruction[:opcode]}' is not defined.", :red
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,10 @@
1
+ class Decoder
2
+ def parse instruction
3
+ components = instruction.to_s.split " "
4
+
5
+ return {
6
+ opcode: components.shift,
7
+ data: components
8
+ }
9
+ end
10
+ end
@@ -0,0 +1,27 @@
1
+ # These solve problems with Ruby boolean types vs 1/0 integer booleans
2
+ class TrueClass
3
+ def to_i
4
+ 1
5
+ end
6
+ end
7
+ class FalseClass
8
+ def to_i
9
+ 0
10
+ end
11
+ end
12
+
13
+ module Remian
14
+ class InstructionSet
15
+ attr_accessor :memory
16
+ attr_accessor :registers
17
+
18
+ def initialize memory, registers
19
+ @memory = memory
20
+ @registers = registers
21
+ end
22
+ end
23
+ end
24
+
25
+ Dir["#{File.dirname(__FILE__)}/instruction_set/*.rb"].each do |file|
26
+ require "#{file[0..-4]}"
27
+ end
@@ -0,0 +1,9 @@
1
+ module Remian
2
+ class InstructionSet
3
+ def add_i addresses
4
+ operands = addresses.map {|address| @memory.read(address.to_i).to_i}
5
+ sum = operands.inject :+
6
+ @memory.write addresses[0].to_i, sum
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,8 @@
1
+ module Remian
2
+ class InstructionSet
3
+ def and addresses
4
+ operands = addresses.map {|address| @memory.read(address.to_i).to_i}
5
+ @memory.write(addresses[0].to_i, operands.inject(:*))
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,11 @@
1
+ module Remian
2
+ class InstructionSet
3
+ def branch addresses
4
+ if @memory.read(addresses[0].to_i).to_i != 0
5
+ destination = @memory.read(addresses[1].to_i).to_i
6
+ Remian.say "Branching to address #{destination}.", :magenta
7
+ @registers[:address] = destination
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ module Remian
2
+ class InstructionSet
3
+ def cp addresses
4
+ @memory.write(addresses[1].to_i, @memory.read(addresses[0].to_i))
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ module Remian
2
+ class InstructionSet
3
+ def exit addresses
4
+ Remian.say "Told to exit.", :magenta
5
+ Process.exit
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,9 @@
1
+ module Remian
2
+ class InstructionSet
3
+ def jump addresses
4
+ destination = @memory.read(addresses[0].to_i).to_i
5
+ Remian.say "Jumping to address #{destination}.", :magenta
6
+ @registers[:address] = destination
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,8 @@
1
+ module Remian
2
+ class InstructionSet
3
+ def mv addresses
4
+ @memory.write(addresses[1].to_i, @memory.read(addresses[0].to_i))
5
+ @memory.write(addresses[0].to_i, "")
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,7 @@
1
+ module Remian
2
+ class InstructionSet
3
+ def not addresses
4
+ @memory.write(addresses[0].to_i, @memory.read(addresses[0].to_i) == 0)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ module Remian
2
+ class InstructionSet
3
+ def or addresses
4
+ operands = addresses.map {|address| @memory.read(address.to_i).to_i}
5
+ @memory.write(addresses[0].to_i, operands.inject(:+) != 0)
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,7 @@
1
+ module Remian
2
+ class InstructionSet
3
+ def put data
4
+ puts data
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ module Remian
2
+ class InstructionSet
3
+ def put_a addresses
4
+ operands = addresses.map {|address| @memory.read(address.to_i)}
5
+ puts operands
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,7 @@
1
+ module Remian
2
+ class InstructionSet
3
+ def set addresses
4
+ @memory.write(operand[0], operand[1])
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ module Remian
2
+ class InstructionSet
3
+ def zero addresses
4
+ operands = addresses.map {|address| @memory.read(address.to_i).to_i}
5
+ @memory.write(addresses[0].to_i, operands[0].to_i == 0)
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,35 @@
1
+ # Addresses start at 1, despite underlying 0-based array implementation
2
+ # This makes assembly programming easier, since line numbers correspond to addresses.
3
+ module Remian
4
+ class Memory
5
+ attr_accessor :store, :size
6
+
7
+ def initialize size
8
+ @size = size
9
+ @store = Array.new @size, ""
10
+ end
11
+
12
+ def read address
13
+ memory_key = convert_address_to_memory_key address
14
+ @store[memory_key]
15
+ end
16
+
17
+ def write address, value
18
+ memory_key = convert_address_to_memory_key address
19
+ if memory_key >= 0 && memory_key < @store.length
20
+ @store[memory_key] = value
21
+ end
22
+ end
23
+
24
+ def write_data data
25
+ data.split("\n").each_with_index do |instruction, i|
26
+ write i + 1, instruction
27
+ end
28
+ end
29
+
30
+ protected
31
+ def convert_address_to_memory_key address
32
+ address - 1
33
+ end
34
+ end
35
+ end
metadata ADDED
@@ -0,0 +1,109 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: remian
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Michael Mokrysz
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-12-18 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: thor
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 0.16.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 0.16.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: term-ansicolor
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 1.0.7
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 1.0.7
46
+ description: A baby virtual machine built in Ruby.
47
+ email:
48
+ - hi@46bit.com
49
+ executables:
50
+ - remian
51
+ extensions: []
52
+ extra_rdoc_files: []
53
+ files:
54
+ - .gitignore
55
+ - .gitkeep
56
+ - AUTHORS.md
57
+ - Gemfile
58
+ - Gemfile.lock
59
+ - LICENSE.md
60
+ - README.md
61
+ - bin/.gitkeep
62
+ - bin/remian
63
+ - lib/.gitkeep
64
+ - lib/remian.rb
65
+ - lib/remian/.gitkeep
66
+ - lib/remian/clock.rb
67
+ - lib/remian/control.rb
68
+ - lib/remian/decoder.rb
69
+ - lib/remian/instruction_set.rb
70
+ - lib/remian/instruction_set/add_i.rb
71
+ - lib/remian/instruction_set/and.rb
72
+ - lib/remian/instruction_set/branch.rb
73
+ - lib/remian/instruction_set/cp.rb
74
+ - lib/remian/instruction_set/exit.rb
75
+ - lib/remian/instruction_set/jump.rb
76
+ - lib/remian/instruction_set/mv.rb
77
+ - lib/remian/instruction_set/not.rb
78
+ - lib/remian/instruction_set/or.rb
79
+ - lib/remian/instruction_set/put.rb
80
+ - lib/remian/instruction_set/put_a.rb
81
+ - lib/remian/instruction_set/set.rb
82
+ - lib/remian/instruction_set/zero.rb
83
+ - lib/remian/memory.rb
84
+ homepage: https://github.com/46Bit/remian
85
+ licenses: []
86
+ post_install_message:
87
+ rdoc_options: []
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ! '>='
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ requirements: []
103
+ rubyforge_project:
104
+ rubygems_version: 1.8.24
105
+ signing_key:
106
+ specification_version: 3
107
+ summary: Remian is a small virtual machine, designed to a Von Neumann architecture
108
+ with a RISC mindset.
109
+ test_files: []