carban 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.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in carban.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 patrick
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
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
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,26 @@
1
+ # Carban
2
+
3
+ TODO: A Rubygem that implements the Carban Instruction Set as a Virtual Machine.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'carban'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install carban
18
+
19
+
20
+ ## Contributing
21
+
22
+ 1. Fork it
23
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
24
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
25
+ 4. Push to the branch (`git push origin my-new-feature`)
26
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/carban.gemspec ADDED
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'carban/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "carban"
8
+ gem.version = Carban::VERSION
9
+ gem.authors = ["patrick"]
10
+ gem.email = ["patrick@patrickjones.ca"]
11
+ gem.description = %q{A Virtual Machine implemented as Abstract Stack Machine and Abstract Register Machine}
12
+ gem.summary = %q{Virtual Machine implementations of the Carban Instruction Set}
13
+ gem.homepage = ""
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+ end
@@ -0,0 +1,230 @@
1
+ module Carban
2
+ module InstructionSet
3
+ include OpCodes
4
+
5
+ def self.load
6
+ compiled_set = {}
7
+ OpCodes.constants.each do |code|
8
+ numerical = OpCodes.const_get code
9
+ compiled_set[numerical] = send(code.to_s.downcase.to_sym)
10
+ end
11
+ return compiled_set
12
+ end
13
+
14
+ def self.add
15
+ Proc.new do |vm|
16
+ left = @data_stack.pop
17
+ right = @data_stack.pop
18
+ @data_stack.push(left + right)
19
+ @ip += 1
20
+ end
21
+ end
22
+
23
+ def self.sub
24
+ Proc.new do |vm|
25
+ right = @data_stack.pop
26
+ left = @data_stack.pop
27
+ @data_stack.push (left - right)
28
+ @ip += 1
29
+ end
30
+ end
31
+
32
+ def self.mul
33
+ Proc.new do |vm|
34
+ left = @data_stack.pop
35
+ right = @data_stack.pop
36
+ @data_stack.push left * right
37
+ @ip += 1
38
+ end
39
+ end
40
+
41
+ def self.div
42
+ Proc.new do |vm|
43
+ left = @data_stack.pop
44
+ right = @data_stack.pop
45
+ @data_stack.push left / right
46
+ @ip += 1
47
+ end
48
+ end
49
+
50
+ def self.pop
51
+ Proc.new do |vm|
52
+ ret = @data_stack.pop
53
+ @ip += 1
54
+ ret
55
+ end
56
+ end
57
+
58
+ def self.push
59
+ Proc.new do |vm|
60
+ operand = @opcodes[@ip + 1]
61
+ @data_stack.push operand
62
+ @ip += 2
63
+ end
64
+ end
65
+
66
+ def self.equal
67
+ Proc.new do |vm|
68
+ left = @data_stack.pop
69
+ right = @data_stack.pop
70
+ result = left == right
71
+ @data_stack.push (result).to_s.upcase.to_sym
72
+ @ip += 1
73
+ end
74
+ end
75
+
76
+ def self.greater_than
77
+ Proc.new do |vm|
78
+ left = @data_stack.pop
79
+ right = @data_stack.pop
80
+ result = left > right
81
+ @data_stack.push (result).to_s.upcase.to_sym
82
+ @ip += 1
83
+ end
84
+ end
85
+
86
+ def self.less_than
87
+ Proc.new do |vm|
88
+ left = @data_stack.pop
89
+ right = @data_stack.pop
90
+ result = left < right
91
+ @data_stack.push (result).to_s.upcase.to_sym
92
+ @ip += 1
93
+ end
94
+ end
95
+
96
+ def self.invert
97
+ Proc.new do |vm|
98
+ value = @data_stack.pop
99
+ @data_stack.push (!value).to_s.upcase.to_sym
100
+ @ip += 1
101
+ end
102
+ end
103
+
104
+ def self.exit
105
+ Proc.new do |vm|
106
+ @ip = @opcodes.length
107
+ end
108
+ end
109
+
110
+ def self.no_op
111
+ Proc.new do |vm|
112
+ @ip += 1
113
+ end
114
+ end
115
+
116
+ def self.jump
117
+ Proc.new do |vm|
118
+ @ip = @data_stack.pop
119
+ end
120
+ end
121
+
122
+ def self.jump_if
123
+ Proc.new do |vm|
124
+ dest = @data_stack.pop
125
+ left = @data_stack.pop
126
+ right = @data_stack.pop
127
+ left == right ? @ip = dest : @ip += 1
128
+ end
129
+ end
130
+
131
+ def self.jump_unless
132
+ Proc.new do |vm|
133
+ dest = @data_stack.pop
134
+ left = @data_stack.pop
135
+ right = @data_stack.pop
136
+ left != right ? @ip = dest : @ip += 1
137
+ end
138
+ end
139
+
140
+ def self.to_string
141
+ Proc.new do |vm|
142
+ value = @data_stack.pop
143
+ @data_stack.push value.to_s
144
+ @ip += 1
145
+ end
146
+ end
147
+
148
+ def self.put_string
149
+ Proc.new do |vm|
150
+ operand = @opcodes[@ip + 1]
151
+ @data_stack.push operand
152
+ @ip += 2
153
+ end
154
+ end
155
+
156
+ def self.dup
157
+ Proc.new do |vm|
158
+ @data_stack.push @data_stack.first
159
+ @ip += 1
160
+ end
161
+ end
162
+
163
+ def self.swap
164
+ Proc.new do |vm|
165
+ left = @data_stack.pop
166
+ right = @data_stack.pop
167
+ [left, right].each { |a| @data_stack.push a }
168
+ @ip += 1
169
+ end
170
+ end
171
+
172
+ def self.over
173
+ Proc.new do |vm|
174
+ left = @data_stack.pop
175
+ right = @data_stack.pop
176
+ [left, right, left].each { |a| @data_stack.push a }
177
+ @ip += 1
178
+ end
179
+ end
180
+
181
+ def self.rot
182
+ Proc.new do |vm|
183
+ one = @data_stack.pop
184
+ two = @data_stack.pop
185
+ three = @data_stack.pop
186
+ [two, three, one].each { |a| @data_stack.push a }
187
+ @ip += 1
188
+ end
189
+ end
190
+
191
+ def self.print
192
+ Proc.new do |vm|
193
+ puts @data_stack.pop
194
+ end
195
+ end
196
+
197
+ def self.store_global
198
+ Proc.new do |vm|
199
+ name = @opcodes[@ip + 1]
200
+ val = @opcodes[@ip + 2]
201
+ @globals[name] = val
202
+ @ip += 3
203
+ end
204
+ end
205
+
206
+
207
+ def self.store_local
208
+ Proc.new do |vm|
209
+ name = @opcodes[@ip + 1]
210
+ val = @opcodes[@ip + 2]
211
+ @locals[name] = val
212
+ @ip += 3
213
+ end
214
+ end
215
+
216
+ def self.code_call
217
+ Proc.new do |vm|
218
+ @call_stack.push(@ip)
219
+ @ip = @opcodes[@ip + 1]
220
+ end
221
+ end
222
+
223
+ def self.code_return
224
+ Proc.new do |vm|
225
+ @ip = @call_stack.pop
226
+ @ip += 1
227
+ end
228
+ end
229
+ end
230
+ end
@@ -0,0 +1,40 @@
1
+ module Carban
2
+ module OpCodes
3
+
4
+ ADD = 00
5
+ SUB = 01
6
+ MUL = 02
7
+ DIV = 03
8
+
9
+ POP = 14
10
+ PUSH = 15
11
+
12
+ EQUAL = 26
13
+ GREATER_THAN = 27
14
+ LESS_THAN = 28
15
+ INVERT = 29
16
+
17
+ EXIT = 40
18
+ NO_OP = 41
19
+
20
+ JUMP = 50
21
+ JUMP_IF = 51
22
+ JUMP_UNLESS = 52
23
+
24
+ PUT_STRING = 60
25
+ TO_STRING = 61
26
+
27
+ DUP = 70
28
+ SWAP = 71
29
+ OVER = 72
30
+ ROT = 73
31
+
32
+ PRINT = 80
33
+
34
+ STORE_GLOBAL = 90
35
+ STORE_LOCAL = 100
36
+
37
+ CODE_CALL = 110
38
+ CODE_RETURN = 111
39
+ end
40
+ end
@@ -0,0 +1,47 @@
1
+
2
+ module Carban
3
+ class StackMachine
4
+ attr_accessor :opcodes, :call_stack, :data_stack, :instructions, :ip, :globals, :locals
5
+ extend InstructionSet
6
+
7
+ def initialize
8
+ @globals = {}
9
+ @locals = {}
10
+ @opcodes = []
11
+ @data_stack = []
12
+ @call_stack = []
13
+ @instructions = InstructionSet.load
14
+ @ip = 0
15
+ end
16
+
17
+ def run
18
+ @ip = 0
19
+ while(@ip < @opcodes.length) do
20
+ self.instance_eval &@instructions[ @opcodes[@ip] ]
21
+ end
22
+ end
23
+
24
+ def dump
25
+ {
26
+ :opcodes => @opcodes,
27
+ :data_stack => @data_stack,
28
+ :instructions => @instructions,
29
+ :instruction_pointer => @ip
30
+ }
31
+ end
32
+
33
+ def load_program(file)
34
+ content = File.open(file).read
35
+ @opcodes = assemble(content)
36
+ end
37
+
38
+ def assemble(str)
39
+ str.split("\n").map do |expr|
40
+ line = expr.split(", ")
41
+ keyword_opcode = OpCodes.const_get(line.first.to_sym)
42
+ line.size > 1 ? [keyword_opcode, line.last.to_i] : keyword_opcode
43
+ end.flatten
44
+ end
45
+
46
+ end
47
+ end
@@ -0,0 +1,3 @@
1
+ module Carban
2
+ VERSION = "0.0.1"
3
+ end
data/lib/carban.rb ADDED
@@ -0,0 +1,8 @@
1
+ require "carban/version"
2
+ require "carban/op_codes"
3
+ require "carban/instruction_set"
4
+ require "carban/stack_machine"
5
+
6
+ module Carban
7
+
8
+ end
metadata ADDED
@@ -0,0 +1,57 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: carban
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - patrick
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-02-13 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: A Virtual Machine implemented as Abstract Stack Machine and Abstract
15
+ Register Machine
16
+ email:
17
+ - patrick@patrickjones.ca
18
+ executables: []
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - .gitignore
23
+ - Gemfile
24
+ - LICENSE.txt
25
+ - README.md
26
+ - Rakefile
27
+ - carban.gemspec
28
+ - lib/carban.rb
29
+ - lib/carban/instruction_set.rb
30
+ - lib/carban/op_codes.rb
31
+ - lib/carban/stack_machine.rb
32
+ - lib/carban/version.rb
33
+ homepage: ''
34
+ licenses: []
35
+ post_install_message:
36
+ rdoc_options: []
37
+ require_paths:
38
+ - lib
39
+ required_ruby_version: !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ required_rubygems_version: !ruby/object:Gem::Requirement
46
+ none: false
47
+ requirements:
48
+ - - ! '>='
49
+ - !ruby/object:Gem::Version
50
+ version: '0'
51
+ requirements: []
52
+ rubyforge_project:
53
+ rubygems_version: 1.8.23
54
+ signing_key:
55
+ specification_version: 3
56
+ summary: Virtual Machine implementations of the Carban Instruction Set
57
+ test_files: []