remian 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: []