koi-vm 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/README.rdoc +47 -0
- data/Rakefile +42 -0
- data/VERSION +1 -0
- data/architecture.rdoc +112 -0
- data/examples/blastoff.rb +20 -0
- data/examples/hello_world.rb +8 -0
- data/koi-vm.gemspec +174 -0
- data/lib/.gitkeep +0 -0
- data/lib/koi-vm/accessors.rb +63 -0
- data/lib/koi-vm/core.rb +48 -0
- data/lib/koi-vm/exceptions.rb +8 -0
- data/lib/koi-vm/helpers.rb +5 -0
- data/lib/koi-vm/opcodes/_opcode_constants.rb +58 -0
- data/lib/koi-vm/opcodes/_value_constants.rb +10 -0
- data/lib/koi-vm/opcodes/comparative_operations/equal.rb +11 -0
- data/lib/koi-vm/opcodes/comparative_operations/greater_than.rb +14 -0
- data/lib/koi-vm/opcodes/comparative_operations/less_than.rb +14 -0
- data/lib/koi-vm/opcodes/control_operations/exit.rb +10 -0
- data/lib/koi-vm/opcodes/control_operations/no_op.rb +9 -0
- data/lib/koi-vm/opcodes/flow_control_operations/jump.rb +11 -0
- data/lib/koi-vm/opcodes/flow_control_operations/jump_if.rb +16 -0
- data/lib/koi-vm/opcodes/flow_control_operations/jump_unless.rb +16 -0
- data/lib/koi-vm/opcodes/function_operations/call.rb +13 -0
- data/lib/koi-vm/opcodes/function_operations/push_function.rb +15 -0
- data/lib/koi-vm/opcodes/function_operations/return.rb +11 -0
- data/lib/koi-vm/opcodes/function_operations/tailcall.rb +12 -0
- data/lib/koi-vm/opcodes/io_operations/gets.rb +10 -0
- data/lib/koi-vm/opcodes/io_operations/print.rb +13 -0
- data/lib/koi-vm/opcodes/math_operations/add.rb +14 -0
- data/lib/koi-vm/opcodes/math_operations/divide.rb +14 -0
- data/lib/koi-vm/opcodes/math_operations/multiply.rb +14 -0
- data/lib/koi-vm/opcodes/math_operations/subtract.rb +14 -0
- data/lib/koi-vm/opcodes/push_operations/push_bool.rb +12 -0
- data/lib/koi-vm/opcodes/push_operations/push_float.rb +12 -0
- data/lib/koi-vm/opcodes/push_operations/push_int.rb +12 -0
- data/lib/koi-vm/opcodes/push_operations/push_nil.rb +10 -0
- data/lib/koi-vm/opcodes/push_operations/push_string.rb +12 -0
- data/lib/koi-vm/opcodes/stack_operations/dup.rb +11 -0
- data/lib/koi-vm/opcodes/stack_operations/pop.rb +11 -0
- data/lib/koi-vm/opcodes/stack_operations/stksize.rb +10 -0
- data/lib/koi-vm/opcodes/stack_operations/swap.rb +11 -0
- data/lib/koi-vm/opcodes/stack_operations/top.rb +13 -0
- data/lib/koi-vm/opcodes/stack_operations/typeof.rb +16 -0
- data/lib/koi-vm/opcodes/string_operations/concat.rb +12 -0
- data/lib/koi-vm/opcodes/string_operations/strlen.rb +12 -0
- data/lib/koi-vm/opcodes/string_operations/to_string.rb +16 -0
- data/lib/koi-vm/opcodes/variable_operations/get_global.rb +10 -0
- data/lib/koi-vm/opcodes/variable_operations/get_local.rb +10 -0
- data/lib/koi-vm/opcodes/variable_operations/set_global.rb +11 -0
- data/lib/koi-vm/opcodes/variable_operations/set_local.rb +11 -0
- data/lib/koi-vm.rb +10 -0
- data/test/.gitkeep +0 -0
- data/test/performance/.gitignore +1 -0
- data/test/performance/simple_benchmark.rb +87 -0
- data/test/setup/test_unit_extensions.rb +21 -0
- data/test/test_helper.rb +13 -0
- data/test/unit/opcodes/comparative_operations/equal_test.rb +116 -0
- data/test/unit/opcodes/comparative_operations/greater_than_test.rb +53 -0
- data/test/unit/opcodes/comparative_operations/less_than_test.rb +53 -0
- data/test/unit/opcodes/control_operations/exit_test.rb +20 -0
- data/test/unit/opcodes/control_operations/no_op_test.rb +17 -0
- data/test/unit/opcodes/flow_control_operations/jump_if_test.rb +50 -0
- data/test/unit/opcodes/flow_control_operations/jump_test.rb +36 -0
- data/test/unit/opcodes/flow_control_operations/jump_unless_test.rb +50 -0
- data/test/unit/opcodes/function_operations/call_test.rb +39 -0
- data/test/unit/opcodes/function_operations/push_function_test.rb +21 -0
- data/test/unit/opcodes/function_operations/return_test.rb +31 -0
- data/test/unit/opcodes/function_operations/tailcall_test.rb +41 -0
- data/test/unit/opcodes/io_operations/gets_test.rb +38 -0
- data/test/unit/opcodes/io_operations/print_test.rb +42 -0
- data/test/unit/opcodes/math_operations/add_test.rb +62 -0
- data/test/unit/opcodes/math_operations/divide_test.rb +62 -0
- data/test/unit/opcodes/math_operations/multiply_test.rb +62 -0
- data/test/unit/opcodes/math_operations/subtract_test.rb +62 -0
- data/test/unit/opcodes/push_operations/push_bool_test.rb +36 -0
- data/test/unit/opcodes/push_operations/push_float_test.rb +27 -0
- data/test/unit/opcodes/push_operations/push_int_test.rb +27 -0
- data/test/unit/opcodes/push_operations/push_nil_test.rb +16 -0
- data/test/unit/opcodes/push_operations/push_string_test.rb +27 -0
- data/test/unit/opcodes/stack_operations/dup_test.rb +25 -0
- data/test/unit/opcodes/stack_operations/pop_test.rb +28 -0
- data/test/unit/opcodes/stack_operations/stksize_test.rb +20 -0
- data/test/unit/opcodes/stack_operations/swap_test.rb +36 -0
- data/test/unit/opcodes/stack_operations/top_test.rb +45 -0
- data/test/unit/opcodes/stack_operations/typeof_test.rb +61 -0
- data/test/unit/opcodes/string_operations/concat_test.rb +65 -0
- data/test/unit/opcodes/string_operations/strlen_test.rb +44 -0
- data/test/unit/opcodes/string_operations/to_string_test.rb +70 -0
- data/test/unit/opcodes/variable_operations/get_global_test.rb +18 -0
- data/test/unit/opcodes/variable_operations/get_local_test.rb +18 -0
- data/test/unit/opcodes/variable_operations/set_global_test.rb +27 -0
- data/test/unit/opcodes/variable_operations/set_local_test.rb +27 -0
- data/test/unit/vm_initialization_test.rb +86 -0
- metadata +200 -0
data/.gitignore
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
= KoiVM
|
2
|
+
|
3
|
+
KoiVM is an extremely simple prototype Virtual Machine written in Ruby. It was created with learning in mind and is written so that it is easy to understand and play with.
|
4
|
+
|
5
|
+
=== Examples
|
6
|
+
|
7
|
+
The standard 'Hello world!', KoiVM style:
|
8
|
+
|
9
|
+
require 'koi'
|
10
|
+
include KoiVM
|
11
|
+
|
12
|
+
VM.new.run [
|
13
|
+
PUSH_STRING, "Hello World!\n",
|
14
|
+
PRINT
|
15
|
+
]
|
16
|
+
|
17
|
+
#=> Hello world!
|
18
|
+
|
19
|
+
And an old-school 'Blast off' example:
|
20
|
+
|
21
|
+
require 'koi'
|
22
|
+
include KoiVM
|
23
|
+
|
24
|
+
VM.new.run [
|
25
|
+
PUSH_INT, 11,
|
26
|
+
PUSH_INT, 1,
|
27
|
+
SUBTRACT,
|
28
|
+
DUP,
|
29
|
+
TO_STRING,
|
30
|
+
PRINT,
|
31
|
+
PUSH_STRING, ", ",
|
32
|
+
PRINT,
|
33
|
+
DUP,
|
34
|
+
PUSH_INT, 0,
|
35
|
+
EQUAL,
|
36
|
+
JUMP_UNLESS, -13,
|
37
|
+
PUSH_STRING, "Blast Off!\n",
|
38
|
+
PRINT
|
39
|
+
]
|
40
|
+
|
41
|
+
#=> 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, Blast off!
|
42
|
+
|
43
|
+
=== Author & Credits
|
44
|
+
|
45
|
+
Author:: {Aaron Gough}[mailto:aaron@aarongough.com]
|
46
|
+
|
47
|
+
Copyright (c) 2010 {Aaron Gough}[http://thingsaaronmade.com/] ({thingsaaronmade.com}[http://thingsaaronmade.com/]), released under the MIT license
|
data/Rakefile
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
desc 'Default: run unit tests.'
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
begin
|
9
|
+
require 'jeweler'
|
10
|
+
Jeweler::Tasks.new do |gemspec|
|
11
|
+
gemspec.name = "koi-vm"
|
12
|
+
gemspec.summary = "A prototype Virtual Machine written in Ruby"
|
13
|
+
gemspec.description = "A prototype Virtual Machine written in Ruby. Why would anyone write such a thing? Because it's fun, and it's a great learning tool."
|
14
|
+
gemspec.email = "aaron@aarongough.com"
|
15
|
+
gemspec.homepage = "https://github.com/aarongough/koi"
|
16
|
+
gemspec.authors = ["Aaron Gough"]
|
17
|
+
gemspec.rdoc_options << '--line-numbers' << '--inline-source'
|
18
|
+
gemspec.extra_rdoc_files = ['README.rdoc', 'MIT-LICENSE']
|
19
|
+
end
|
20
|
+
rescue LoadError
|
21
|
+
puts "Jeweler not available. Install it with: gem install jeweler"
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
desc 'Test Koi.'
|
26
|
+
Rake::TestTask.new(:test) do |t|
|
27
|
+
t.libs << 'lib/*.rb'
|
28
|
+
t.libs << 'test'
|
29
|
+
t.pattern = 'test/**/*_test.rb'
|
30
|
+
t.verbose = true
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
desc 'Generate documentation for Koi.'
|
35
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
36
|
+
rdoc.rdoc_dir = 'rdoc'
|
37
|
+
rdoc.title = 'Koi'
|
38
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
39
|
+
rdoc.rdoc_files.include('README.rdoc')
|
40
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
41
|
+
rdoc.rdoc_files.include('app/**/*.rb')
|
42
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
data/architecture.rdoc
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
= Koi Architecture
|
2
|
+
|
3
|
+
This document is a general overview of the Koi VM architecture. It is used internally as a design document and to keep track of what work still needs to be done.
|
4
|
+
|
5
|
+
=== Datatypes
|
6
|
+
|
7
|
+
* Integer
|
8
|
+
* Float
|
9
|
+
* String
|
10
|
+
* Array (coming later)
|
11
|
+
* Hash (coming later)
|
12
|
+
|
13
|
+
=== Operations
|
14
|
+
|
15
|
+
* Stack
|
16
|
+
PUSH_NIL
|
17
|
+
PUSH_BOOL boolean
|
18
|
+
PUSH_INT integer
|
19
|
+
PUSH_FLOAT float
|
20
|
+
PUSH_STRING string
|
21
|
+
PUSH_ARRAY array
|
22
|
+
PUSH_HASH hash
|
23
|
+
x POP
|
24
|
+
x SWAP
|
25
|
+
x DUP
|
26
|
+
x TOP number_of_stack_items
|
27
|
+
|
28
|
+
* Variables
|
29
|
+
x SET_LOCAL index
|
30
|
+
x GET_LOCAL index
|
31
|
+
x SET_GLOBAL index
|
32
|
+
x GET_GLOBAL index
|
33
|
+
|
34
|
+
* Instruction Pointer
|
35
|
+
x ABS_JUMP
|
36
|
+
x REL_JUMP destination_offset
|
37
|
+
x JUMP_IF destination_offset
|
38
|
+
x JUMP_UNLESS destination_offset
|
39
|
+
|
40
|
+
* Integers / Floats
|
41
|
+
x ADD
|
42
|
+
x SUBTRACT
|
43
|
+
x MULTIPLY
|
44
|
+
x DIVIDE
|
45
|
+
MODULO
|
46
|
+
x INCREMENT
|
47
|
+
x DECREMENT
|
48
|
+
EQUAL
|
49
|
+
NOT_EQUAL
|
50
|
+
LESS_THAN
|
51
|
+
GREATER_THAN
|
52
|
+
EQUAL_LESS_THAN
|
53
|
+
EQUAL_GREATER_THAN
|
54
|
+
|
55
|
+
* Strings
|
56
|
+
CONCATENATE
|
57
|
+
LENGTH
|
58
|
+
|
59
|
+
* Arrays
|
60
|
+
x ARRAY_NEW
|
61
|
+
x ARRAY_GET_INDEX
|
62
|
+
x ARRAY_PUT_INDEX
|
63
|
+
ARRAY_PUSH
|
64
|
+
ARRAY_SIZE
|
65
|
+
ARRAY_INCLUDE
|
66
|
+
ARRAY_EXPLODE
|
67
|
+
|
68
|
+
* Hashes
|
69
|
+
x HASH_NEW
|
70
|
+
x HASH_GET_KEY
|
71
|
+
x HASH_PUT_KEY
|
72
|
+
HASH_SIZE
|
73
|
+
HASH_HAS_KEY
|
74
|
+
HASH_EXPLODE
|
75
|
+
|
76
|
+
* Socket I/O
|
77
|
+
NEW_SOCKET_IO
|
78
|
+
|
79
|
+
* File I/O
|
80
|
+
x FILE_OPEN
|
81
|
+
x FILE_PUT
|
82
|
+
FILE_GET
|
83
|
+
FILE_FLUSH
|
84
|
+
FILE_CLOSE
|
85
|
+
|
86
|
+
* Anonymous Functions
|
87
|
+
FUNCTION_PUSH
|
88
|
+
FUNCTION_END
|
89
|
+
FUNCTION_CALL
|
90
|
+
FUNCTION_RETURN
|
91
|
+
|
92
|
+
* Fibers
|
93
|
+
x FIBER_ID
|
94
|
+
FIBER_LENGTH
|
95
|
+
x FIBER_NEW
|
96
|
+
x FIBER_DELETE
|
97
|
+
FIBER_YIELD
|
98
|
+
|
99
|
+
* Misc
|
100
|
+
TYPE_OF
|
101
|
+
x TO_STRING
|
102
|
+
x EXIT
|
103
|
+
|
104
|
+
|
105
|
+
|
106
|
+
=== Exceptions
|
107
|
+
|
108
|
+
* StackError
|
109
|
+
Denotes that an error occurred when accessing items on the stack. The most likely cases are that there were not enough items on the stack for an opcode to work, or that the items were not of the correct type.
|
110
|
+
|
111
|
+
* OperandError
|
112
|
+
Denotes that an error occurred when reading an operand for an opcode. This may be because an operand was not supplied, or because it was not of the correct type.
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'koi.rb'))
|
2
|
+
|
3
|
+
include KoiVM
|
4
|
+
|
5
|
+
VM.new.run [
|
6
|
+
PUSH_INT, 11,
|
7
|
+
PUSH_INT, 1,
|
8
|
+
SUBTRACT,
|
9
|
+
DUP,
|
10
|
+
TO_STRING,
|
11
|
+
PRINT,
|
12
|
+
PUSH_STRING, ", ",
|
13
|
+
PRINT,
|
14
|
+
DUP,
|
15
|
+
PUSH_INT, 0,
|
16
|
+
EQUAL,
|
17
|
+
JUMP_UNLESS, -13,
|
18
|
+
PUSH_STRING, "Blast Off!\n",
|
19
|
+
PRINT
|
20
|
+
]
|
data/koi-vm.gemspec
ADDED
@@ -0,0 +1,174 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{koi-vm}
|
8
|
+
s.version = "0.0.1"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Aaron Gough"]
|
12
|
+
s.date = %q{2010-08-25}
|
13
|
+
s.description = %q{A prototype Virtual Machine written in Ruby. Why would anyone write such a thing? Because it's fun, and it's a great learning tool.}
|
14
|
+
s.email = %q{aaron@aarongough.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"README.rdoc"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
".gitignore",
|
20
|
+
"README.rdoc",
|
21
|
+
"Rakefile",
|
22
|
+
"VERSION",
|
23
|
+
"architecture.rdoc",
|
24
|
+
"examples/blastoff.rb",
|
25
|
+
"examples/hello_world.rb",
|
26
|
+
"koi-vm.gemspec",
|
27
|
+
"lib/.gitkeep",
|
28
|
+
"lib/koi-vm.rb",
|
29
|
+
"lib/koi-vm/accessors.rb",
|
30
|
+
"lib/koi-vm/core.rb",
|
31
|
+
"lib/koi-vm/exceptions.rb",
|
32
|
+
"lib/koi-vm/helpers.rb",
|
33
|
+
"lib/koi-vm/opcodes/_opcode_constants.rb",
|
34
|
+
"lib/koi-vm/opcodes/_value_constants.rb",
|
35
|
+
"lib/koi-vm/opcodes/comparative_operations/equal.rb",
|
36
|
+
"lib/koi-vm/opcodes/comparative_operations/greater_than.rb",
|
37
|
+
"lib/koi-vm/opcodes/comparative_operations/less_than.rb",
|
38
|
+
"lib/koi-vm/opcodes/control_operations/exit.rb",
|
39
|
+
"lib/koi-vm/opcodes/control_operations/no_op.rb",
|
40
|
+
"lib/koi-vm/opcodes/flow_control_operations/jump.rb",
|
41
|
+
"lib/koi-vm/opcodes/flow_control_operations/jump_if.rb",
|
42
|
+
"lib/koi-vm/opcodes/flow_control_operations/jump_unless.rb",
|
43
|
+
"lib/koi-vm/opcodes/function_operations/call.rb",
|
44
|
+
"lib/koi-vm/opcodes/function_operations/push_function.rb",
|
45
|
+
"lib/koi-vm/opcodes/function_operations/return.rb",
|
46
|
+
"lib/koi-vm/opcodes/function_operations/tailcall.rb",
|
47
|
+
"lib/koi-vm/opcodes/io_operations/gets.rb",
|
48
|
+
"lib/koi-vm/opcodes/io_operations/print.rb",
|
49
|
+
"lib/koi-vm/opcodes/math_operations/add.rb",
|
50
|
+
"lib/koi-vm/opcodes/math_operations/divide.rb",
|
51
|
+
"lib/koi-vm/opcodes/math_operations/multiply.rb",
|
52
|
+
"lib/koi-vm/opcodes/math_operations/subtract.rb",
|
53
|
+
"lib/koi-vm/opcodes/push_operations/push_bool.rb",
|
54
|
+
"lib/koi-vm/opcodes/push_operations/push_float.rb",
|
55
|
+
"lib/koi-vm/opcodes/push_operations/push_int.rb",
|
56
|
+
"lib/koi-vm/opcodes/push_operations/push_nil.rb",
|
57
|
+
"lib/koi-vm/opcodes/push_operations/push_string.rb",
|
58
|
+
"lib/koi-vm/opcodes/stack_operations/dup.rb",
|
59
|
+
"lib/koi-vm/opcodes/stack_operations/pop.rb",
|
60
|
+
"lib/koi-vm/opcodes/stack_operations/stksize.rb",
|
61
|
+
"lib/koi-vm/opcodes/stack_operations/swap.rb",
|
62
|
+
"lib/koi-vm/opcodes/stack_operations/top.rb",
|
63
|
+
"lib/koi-vm/opcodes/stack_operations/typeof.rb",
|
64
|
+
"lib/koi-vm/opcodes/string_operations/concat.rb",
|
65
|
+
"lib/koi-vm/opcodes/string_operations/strlen.rb",
|
66
|
+
"lib/koi-vm/opcodes/string_operations/to_string.rb",
|
67
|
+
"lib/koi-vm/opcodes/variable_operations/get_global.rb",
|
68
|
+
"lib/koi-vm/opcodes/variable_operations/get_local.rb",
|
69
|
+
"lib/koi-vm/opcodes/variable_operations/set_global.rb",
|
70
|
+
"lib/koi-vm/opcodes/variable_operations/set_local.rb",
|
71
|
+
"test/.gitkeep",
|
72
|
+
"test/performance/.gitignore",
|
73
|
+
"test/performance/simple_benchmark.rb",
|
74
|
+
"test/setup/test_unit_extensions.rb",
|
75
|
+
"test/test_helper.rb",
|
76
|
+
"test/unit/opcodes/comparative_operations/equal_test.rb",
|
77
|
+
"test/unit/opcodes/comparative_operations/greater_than_test.rb",
|
78
|
+
"test/unit/opcodes/comparative_operations/less_than_test.rb",
|
79
|
+
"test/unit/opcodes/control_operations/exit_test.rb",
|
80
|
+
"test/unit/opcodes/control_operations/no_op_test.rb",
|
81
|
+
"test/unit/opcodes/flow_control_operations/jump_if_test.rb",
|
82
|
+
"test/unit/opcodes/flow_control_operations/jump_test.rb",
|
83
|
+
"test/unit/opcodes/flow_control_operations/jump_unless_test.rb",
|
84
|
+
"test/unit/opcodes/function_operations/call_test.rb",
|
85
|
+
"test/unit/opcodes/function_operations/push_function_test.rb",
|
86
|
+
"test/unit/opcodes/function_operations/return_test.rb",
|
87
|
+
"test/unit/opcodes/function_operations/tailcall_test.rb",
|
88
|
+
"test/unit/opcodes/io_operations/gets_test.rb",
|
89
|
+
"test/unit/opcodes/io_operations/print_test.rb",
|
90
|
+
"test/unit/opcodes/math_operations/add_test.rb",
|
91
|
+
"test/unit/opcodes/math_operations/divide_test.rb",
|
92
|
+
"test/unit/opcodes/math_operations/multiply_test.rb",
|
93
|
+
"test/unit/opcodes/math_operations/subtract_test.rb",
|
94
|
+
"test/unit/opcodes/push_operations/push_bool_test.rb",
|
95
|
+
"test/unit/opcodes/push_operations/push_float_test.rb",
|
96
|
+
"test/unit/opcodes/push_operations/push_int_test.rb",
|
97
|
+
"test/unit/opcodes/push_operations/push_nil_test.rb",
|
98
|
+
"test/unit/opcodes/push_operations/push_string_test.rb",
|
99
|
+
"test/unit/opcodes/stack_operations/dup_test.rb",
|
100
|
+
"test/unit/opcodes/stack_operations/pop_test.rb",
|
101
|
+
"test/unit/opcodes/stack_operations/stksize_test.rb",
|
102
|
+
"test/unit/opcodes/stack_operations/swap_test.rb",
|
103
|
+
"test/unit/opcodes/stack_operations/top_test.rb",
|
104
|
+
"test/unit/opcodes/stack_operations/typeof_test.rb",
|
105
|
+
"test/unit/opcodes/string_operations/concat_test.rb",
|
106
|
+
"test/unit/opcodes/string_operations/strlen_test.rb",
|
107
|
+
"test/unit/opcodes/string_operations/to_string_test.rb",
|
108
|
+
"test/unit/opcodes/variable_operations/get_global_test.rb",
|
109
|
+
"test/unit/opcodes/variable_operations/get_local_test.rb",
|
110
|
+
"test/unit/opcodes/variable_operations/set_global_test.rb",
|
111
|
+
"test/unit/opcodes/variable_operations/set_local_test.rb",
|
112
|
+
"test/unit/vm_initialization_test.rb"
|
113
|
+
]
|
114
|
+
s.homepage = %q{https://github.com/aarongough/koi}
|
115
|
+
s.rdoc_options = ["--charset=UTF-8", "--line-numbers", "--inline-source"]
|
116
|
+
s.require_paths = ["lib"]
|
117
|
+
s.rubygems_version = %q{1.3.7}
|
118
|
+
s.summary = %q{A prototype Virtual Machine written in Ruby}
|
119
|
+
s.test_files = [
|
120
|
+
"test/performance/simple_benchmark.rb",
|
121
|
+
"test/setup/test_unit_extensions.rb",
|
122
|
+
"test/test_helper.rb",
|
123
|
+
"test/unit/opcodes/comparative_operations/equal_test.rb",
|
124
|
+
"test/unit/opcodes/comparative_operations/greater_than_test.rb",
|
125
|
+
"test/unit/opcodes/comparative_operations/less_than_test.rb",
|
126
|
+
"test/unit/opcodes/control_operations/exit_test.rb",
|
127
|
+
"test/unit/opcodes/control_operations/no_op_test.rb",
|
128
|
+
"test/unit/opcodes/flow_control_operations/jump_if_test.rb",
|
129
|
+
"test/unit/opcodes/flow_control_operations/jump_test.rb",
|
130
|
+
"test/unit/opcodes/flow_control_operations/jump_unless_test.rb",
|
131
|
+
"test/unit/opcodes/function_operations/call_test.rb",
|
132
|
+
"test/unit/opcodes/function_operations/push_function_test.rb",
|
133
|
+
"test/unit/opcodes/function_operations/return_test.rb",
|
134
|
+
"test/unit/opcodes/function_operations/tailcall_test.rb",
|
135
|
+
"test/unit/opcodes/io_operations/gets_test.rb",
|
136
|
+
"test/unit/opcodes/io_operations/print_test.rb",
|
137
|
+
"test/unit/opcodes/math_operations/add_test.rb",
|
138
|
+
"test/unit/opcodes/math_operations/divide_test.rb",
|
139
|
+
"test/unit/opcodes/math_operations/multiply_test.rb",
|
140
|
+
"test/unit/opcodes/math_operations/subtract_test.rb",
|
141
|
+
"test/unit/opcodes/push_operations/push_bool_test.rb",
|
142
|
+
"test/unit/opcodes/push_operations/push_float_test.rb",
|
143
|
+
"test/unit/opcodes/push_operations/push_int_test.rb",
|
144
|
+
"test/unit/opcodes/push_operations/push_nil_test.rb",
|
145
|
+
"test/unit/opcodes/push_operations/push_string_test.rb",
|
146
|
+
"test/unit/opcodes/stack_operations/dup_test.rb",
|
147
|
+
"test/unit/opcodes/stack_operations/pop_test.rb",
|
148
|
+
"test/unit/opcodes/stack_operations/stksize_test.rb",
|
149
|
+
"test/unit/opcodes/stack_operations/swap_test.rb",
|
150
|
+
"test/unit/opcodes/stack_operations/top_test.rb",
|
151
|
+
"test/unit/opcodes/stack_operations/typeof_test.rb",
|
152
|
+
"test/unit/opcodes/string_operations/concat_test.rb",
|
153
|
+
"test/unit/opcodes/string_operations/strlen_test.rb",
|
154
|
+
"test/unit/opcodes/string_operations/to_string_test.rb",
|
155
|
+
"test/unit/opcodes/variable_operations/get_global_test.rb",
|
156
|
+
"test/unit/opcodes/variable_operations/get_local_test.rb",
|
157
|
+
"test/unit/opcodes/variable_operations/set_global_test.rb",
|
158
|
+
"test/unit/opcodes/variable_operations/set_local_test.rb",
|
159
|
+
"test/unit/vm_initialization_test.rb",
|
160
|
+
"examples/blastoff.rb",
|
161
|
+
"examples/hello_world.rb"
|
162
|
+
]
|
163
|
+
|
164
|
+
if s.respond_to? :specification_version then
|
165
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
166
|
+
s.specification_version = 3
|
167
|
+
|
168
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
169
|
+
else
|
170
|
+
end
|
171
|
+
else
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
data/lib/.gitkeep
ADDED
File without changes
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module KoiVM
|
2
|
+
class VM
|
3
|
+
|
4
|
+
def data_stack
|
5
|
+
return @state[:fiber][:data_stack]
|
6
|
+
end
|
7
|
+
|
8
|
+
def data_stack=(stack)
|
9
|
+
@state[:fiber][:data_stack] = stack
|
10
|
+
end
|
11
|
+
|
12
|
+
def return_stack
|
13
|
+
return @state[:fiber][:return_stack]
|
14
|
+
end
|
15
|
+
|
16
|
+
def return_stack=(stack)
|
17
|
+
@state[:fiber][:return_stack] = stack
|
18
|
+
end
|
19
|
+
|
20
|
+
def instruction_pointer
|
21
|
+
return @state[:fiber][:instruction_pointer]
|
22
|
+
end
|
23
|
+
|
24
|
+
def instruction_pointer=(ip)
|
25
|
+
@state[:fiber][:instruction_pointer] = ip
|
26
|
+
end
|
27
|
+
|
28
|
+
def opcodes
|
29
|
+
return @state[:opcodes]
|
30
|
+
end
|
31
|
+
|
32
|
+
def locals
|
33
|
+
return @state[:fiber][:locals][@state[:fiber][:level]]
|
34
|
+
end
|
35
|
+
|
36
|
+
def globals
|
37
|
+
return @state[:globals]
|
38
|
+
end
|
39
|
+
|
40
|
+
def increment_scope
|
41
|
+
@state[:fiber][:level] += 1
|
42
|
+
@state[:fiber][:locals][@state[:fiber][:level]] = @state[:fiber][:locals][@state[:fiber][:level] - 1].dup
|
43
|
+
end
|
44
|
+
|
45
|
+
def decrement_scope
|
46
|
+
@state[:fiber][:locals].delete_at(@state[:fiber][:level])
|
47
|
+
@state[:fiber][:level] -= 1
|
48
|
+
end
|
49
|
+
|
50
|
+
def reload_scope
|
51
|
+
@state[:fiber][:locals][@state[:fiber][:level]] = {}
|
52
|
+
end
|
53
|
+
|
54
|
+
def level
|
55
|
+
return @state[:fiber][:level]
|
56
|
+
end
|
57
|
+
|
58
|
+
def level=(level)
|
59
|
+
@state[:fiber][:level] = level
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
data/lib/koi-vm/core.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
module KoiVM
|
2
|
+
class VM
|
3
|
+
|
4
|
+
@@instruction = []
|
5
|
+
|
6
|
+
attr_accessor :state, :files
|
7
|
+
|
8
|
+
def initialize(state = {}, opcodes = [])
|
9
|
+
default_state = {
|
10
|
+
:opcodes => opcodes,
|
11
|
+
:globals => {},
|
12
|
+
:fiber => {
|
13
|
+
:data_stack => [],
|
14
|
+
:return_stack => [],
|
15
|
+
:locals => [{}],
|
16
|
+
:instruction_pointer => 0,
|
17
|
+
:level => 0
|
18
|
+
}
|
19
|
+
}
|
20
|
+
@state = default_state.merge(state)
|
21
|
+
@files = {}
|
22
|
+
raise ArgumentError, "state[:fibers][x] must be a hash" unless(@state[:fiber].is_a?(Hash))
|
23
|
+
raise ArgumentError, "state[:fibers][x][:stack] must be an Array" unless(@state[:fiber][:data_stack].is_a?(Array))
|
24
|
+
raise ArgumentError, "state[:fibers][x][:stack] must be an Array" unless(@state[:fiber][:return_stack].is_a?(Array))
|
25
|
+
raise ArgumentError, "state[:fibers][x][:instruction_pointer] must be an Integer" unless(@state[:fiber][:instruction_pointer].is_a?(Integer))
|
26
|
+
raise ArgumentError, "state[:fibers][x][:level] must be an Integer" unless(@state[:fiber][:level].is_a?(Integer))
|
27
|
+
raise ArgumentError, "state[:globals] must be a hash" unless(@state[:globals].is_a?(Hash))
|
28
|
+
raise ArgumentError, "state[:opcodes] must be an array" unless(@state[:opcodes].is_a?(Array))
|
29
|
+
end
|
30
|
+
|
31
|
+
def run(opcodes = [])
|
32
|
+
@state[:opcodes].concat(opcodes)
|
33
|
+
opcode_size = @state[:opcodes].size
|
34
|
+
while (@state[:fiber][:instruction_pointer] < opcode_size)
|
35
|
+
begin
|
36
|
+
break if(@@instruction[@state[:opcodes][@state[:fiber][:instruction_pointer]]].call(self) == true)
|
37
|
+
rescue NoMethodError
|
38
|
+
@state.delete(:opcodes)
|
39
|
+
puts "\n\n" + @state.inspect + "\n\n" unless(defined?($test) && $test == true)
|
40
|
+
raise
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
return @state
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module KoiVM
|
2
|
+
# 0
|
3
|
+
PUSH_NIL = 0
|
4
|
+
PUSH_BOOL = 1
|
5
|
+
PUSH_INT = 2
|
6
|
+
PUSH_FLOAT = 3
|
7
|
+
PUSH_STRING = 4
|
8
|
+
|
9
|
+
# 20
|
10
|
+
JUMP = 20
|
11
|
+
JUMP_IF = 21
|
12
|
+
JUMP_UNLESS = 22
|
13
|
+
|
14
|
+
# 40
|
15
|
+
POP = 40
|
16
|
+
SWAP = 41
|
17
|
+
DUP = 42
|
18
|
+
STKSIZE = 43
|
19
|
+
TYPEOF = 44
|
20
|
+
TOP = 45
|
21
|
+
|
22
|
+
# 60
|
23
|
+
ADD = 60
|
24
|
+
SUBTRACT = 61
|
25
|
+
MULTIPLY = 62
|
26
|
+
DIVIDE = 63
|
27
|
+
|
28
|
+
# 80
|
29
|
+
CONCAT = 80
|
30
|
+
STRLEN = 81
|
31
|
+
TO_STRING = 82
|
32
|
+
|
33
|
+
# 100
|
34
|
+
EQUAL = 100
|
35
|
+
LESS_THAN = 101
|
36
|
+
GREATER_THAN = 102
|
37
|
+
|
38
|
+
# 120
|
39
|
+
PRINT = 120
|
40
|
+
GETS = 121
|
41
|
+
|
42
|
+
# 140
|
43
|
+
SET_LOCAL = 140
|
44
|
+
GET_LOCAL = 141
|
45
|
+
SET_GLOBAL = 142
|
46
|
+
GET_GLOBAL = 143
|
47
|
+
|
48
|
+
# 160
|
49
|
+
PUSH_FUNCTION = 160
|
50
|
+
END_FUNCTION = 161
|
51
|
+
CALL = 162
|
52
|
+
RETURN = 163
|
53
|
+
TAILCALL = 164
|
54
|
+
|
55
|
+
# 240
|
56
|
+
NO_OP = 240
|
57
|
+
EXIT = 255
|
58
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module KoiVM
|
2
|
+
class VM
|
3
|
+
|
4
|
+
@@instruction[EQUAL] = Proc.new() do |vm|
|
5
|
+
raise StackError, "Expecting at least two items on the data stack" unless(vm.data_stack.length > 1)
|
6
|
+
vm.data_stack.push([BOOL_, vm.data_stack.pop == vm.data_stack.pop])
|
7
|
+
vm.instruction_pointer = vm.instruction_pointer + 1
|
8
|
+
end
|
9
|
+
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module KoiVM
|
2
|
+
class VM
|
3
|
+
|
4
|
+
@@instruction[GREATER_THAN] = Proc.new() do |vm|
|
5
|
+
raise StackError, "Expecting at least two items on the data stack" unless(vm.data_stack.length > 1)
|
6
|
+
result = [BOOL_, vm.data_stack[-2][1] > vm.data_stack[-1][1]]
|
7
|
+
vm.data_stack.pop
|
8
|
+
vm.data_stack.pop
|
9
|
+
vm.data_stack.push(result)
|
10
|
+
vm.instruction_pointer = vm.instruction_pointer + 1
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module KoiVM
|
2
|
+
class VM
|
3
|
+
|
4
|
+
@@instruction[LESS_THAN] = Proc.new() do |vm|
|
5
|
+
raise StackError, "Expecting at least two items on the data stack" unless(vm.data_stack.length > 1)
|
6
|
+
result = [BOOL_, vm.data_stack[-2][1] < vm.data_stack[-1][1]]
|
7
|
+
vm.data_stack.pop
|
8
|
+
vm.data_stack.pop
|
9
|
+
vm.data_stack.push(result)
|
10
|
+
vm.instruction_pointer = vm.instruction_pointer + 1
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|