koi-vm-ruby 0.0.4
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 +2 -0
- data/README.rdoc +64 -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 +198 -0
- data/lib/.gitkeep +0 -0
- data/lib/koi-vm-ruby.rb +10 -0
- data/lib/koi-vm-ruby/accessors.rb +63 -0
- data/lib/koi-vm-ruby/core.rb +48 -0
- data/lib/koi-vm-ruby/exceptions.rb +8 -0
- data/lib/koi-vm-ruby/helpers.rb +5 -0
- data/lib/koi-vm-ruby/opcodes/_opcode_constants.rb +68 -0
- data/lib/koi-vm-ruby/opcodes/_value_constants.rb +11 -0
- data/lib/koi-vm-ruby/opcodes/comparative_operations/equal.rb +11 -0
- data/lib/koi-vm-ruby/opcodes/comparative_operations/greater_than.rb +14 -0
- data/lib/koi-vm-ruby/opcodes/comparative_operations/invert.rb +12 -0
- data/lib/koi-vm-ruby/opcodes/comparative_operations/less_than.rb +14 -0
- data/lib/koi-vm-ruby/opcodes/control_operations/exit.rb +10 -0
- data/lib/koi-vm-ruby/opcodes/control_operations/no_op.rb +9 -0
- data/lib/koi-vm-ruby/opcodes/flow_control_operations/jump.rb +11 -0
- data/lib/koi-vm-ruby/opcodes/flow_control_operations/jump_if.rb +16 -0
- data/lib/koi-vm-ruby/opcodes/flow_control_operations/jump_unless.rb +16 -0
- data/lib/koi-vm-ruby/opcodes/function_operations/call.rb +13 -0
- data/lib/koi-vm-ruby/opcodes/function_operations/push_function.rb +19 -0
- data/lib/koi-vm-ruby/opcodes/function_operations/return.rb +11 -0
- data/lib/koi-vm-ruby/opcodes/function_operations/tailcall.rb +12 -0
- data/lib/koi-vm-ruby/opcodes/hash_operations/get_key.rb +14 -0
- data/lib/koi-vm-ruby/opcodes/hash_operations/has_key.rb +18 -0
- data/lib/koi-vm-ruby/opcodes/hash_operations/length.rb +19 -0
- data/lib/koi-vm-ruby/opcodes/hash_operations/num_pairs.rb +12 -0
- data/lib/koi-vm-ruby/opcodes/hash_operations/pairs.rb +22 -0
- data/lib/koi-vm-ruby/opcodes/hash_operations/push_hash.rb +10 -0
- data/lib/koi-vm-ruby/opcodes/hash_operations/set_key.rb +14 -0
- data/lib/koi-vm-ruby/opcodes/io_operations/gets.rb +10 -0
- data/lib/koi-vm-ruby/opcodes/io_operations/print.rb +13 -0
- data/lib/koi-vm-ruby/opcodes/math_operations/add.rb +14 -0
- data/lib/koi-vm-ruby/opcodes/math_operations/divide.rb +14 -0
- data/lib/koi-vm-ruby/opcodes/math_operations/multiply.rb +14 -0
- data/lib/koi-vm-ruby/opcodes/math_operations/subtract.rb +14 -0
- data/lib/koi-vm-ruby/opcodes/push_operations/push_bool.rb +12 -0
- data/lib/koi-vm-ruby/opcodes/push_operations/push_float.rb +12 -0
- data/lib/koi-vm-ruby/opcodes/push_operations/push_int.rb +12 -0
- data/lib/koi-vm-ruby/opcodes/push_operations/push_nil.rb +10 -0
- data/lib/koi-vm-ruby/opcodes/push_operations/push_string.rb +12 -0
- data/lib/koi-vm-ruby/opcodes/stack_operations/dup.rb +11 -0
- data/lib/koi-vm-ruby/opcodes/stack_operations/pop.rb +11 -0
- data/lib/koi-vm-ruby/opcodes/stack_operations/stksize.rb +10 -0
- data/lib/koi-vm-ruby/opcodes/stack_operations/swap.rb +11 -0
- data/lib/koi-vm-ruby/opcodes/stack_operations/top.rb +13 -0
- data/lib/koi-vm-ruby/opcodes/stack_operations/typeof.rb +18 -0
- data/lib/koi-vm-ruby/opcodes/string_operations/concat.rb +12 -0
- data/lib/koi-vm-ruby/opcodes/string_operations/strlen.rb +12 -0
- data/lib/koi-vm-ruby/opcodes/string_operations/to_string.rb +16 -0
- data/lib/koi-vm-ruby/opcodes/variable_operations/get_global.rb +10 -0
- data/lib/koi-vm-ruby/opcodes/variable_operations/get_local.rb +10 -0
- data/lib/koi-vm-ruby/opcodes/variable_operations/set_global.rb +11 -0
- data/lib/koi-vm-ruby/opcodes/variable_operations/set_local.rb +11 -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/invert_test.rb +44 -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 +41 -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/hash_operations/get_key_test.rb +56 -0
- data/test/unit/opcodes/hash_operations/has_key_test.rb +56 -0
- data/test/unit/opcodes/hash_operations/length_test.rb +46 -0
- data/test/unit/opcodes/hash_operations/num_pairs_test.rb +46 -0
- data/test/unit/opcodes/hash_operations/pairs_test.rb +67 -0
- data/test/unit/opcodes/hash_operations/push_hash_test.rb +16 -0
- data/test/unit/opcodes/hash_operations/set_key_test.rb +56 -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 +79 -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 +224 -0
@@ -0,0 +1,19 @@
|
|
1
|
+
module KoiVMRuby
|
2
|
+
class VM
|
3
|
+
|
4
|
+
@@instruction[LENGTH] = Proc.new() do |vm|
|
5
|
+
raise StackError, "Expecting at least one item on the data stack" unless(vm.data_stack.length > 0)
|
6
|
+
raise StackError, "Expecting a hash" unless(vm.data_stack[-1][0] == HASH_)
|
7
|
+
hash = vm.data_stack.pop[1]
|
8
|
+
integer_keys = hash.keys.reject{|x| x[0] != INTEGER_ }.map{|x| x[1]}
|
9
|
+
highest_key = integer_keys.sort.last
|
10
|
+
if(highest_key.nil?)
|
11
|
+
vm.data_stack.push([INTEGER_, 0])
|
12
|
+
else
|
13
|
+
vm.data_stack.push([INTEGER_, highest_key + 1])
|
14
|
+
end
|
15
|
+
vm.instruction_pointer = vm.instruction_pointer + 1
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module KoiVMRuby
|
2
|
+
class VM
|
3
|
+
|
4
|
+
@@instruction[NUM_PAIRS] = Proc.new() do |vm|
|
5
|
+
raise StackError, "Expecting at least one item on the data stack" unless(vm.data_stack.length > 0)
|
6
|
+
raise StackError, "Expecting a hash" unless(vm.data_stack[-1][0] == HASH_)
|
7
|
+
vm.data_stack.push([INTEGER_, vm.data_stack.pop[1].length ])
|
8
|
+
vm.instruction_pointer = vm.instruction_pointer + 1
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module KoiVMRuby
|
2
|
+
class VM
|
3
|
+
|
4
|
+
@@instruction[PAIRS] = Proc.new() do |vm|
|
5
|
+
raise StackError, "Expecting at least one item on the data stack" unless(vm.data_stack.length > 0)
|
6
|
+
raise StackError, "Expecting a hash" unless(vm.data_stack[-1][0] == HASH_)
|
7
|
+
hash = vm.data_stack.pop[1]
|
8
|
+
hashed_hash = {}
|
9
|
+
index = 0
|
10
|
+
hash.each_pair do |k,v|
|
11
|
+
hashed_hash[[INTEGER_, index]] = [HASH_, {
|
12
|
+
[INTEGER_, 0] => k,
|
13
|
+
[INTEGER_, 1] => v
|
14
|
+
}]
|
15
|
+
index += 1
|
16
|
+
end
|
17
|
+
vm.data_stack.push([HASH_, hashed_hash])
|
18
|
+
vm.instruction_pointer = vm.instruction_pointer + 1
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module KoiVMRuby
|
2
|
+
class VM
|
3
|
+
|
4
|
+
@@instruction[SET_KEY] = Proc.new() do |vm|
|
5
|
+
raise StackError, "Expecting at least three items on the data stack" unless(vm.data_stack.length > 2)
|
6
|
+
raise StackError, "Expecting a hash" unless(vm.data_stack[-3][0] == HASH_)
|
7
|
+
value = vm.data_stack.pop
|
8
|
+
key = vm.data_stack.pop
|
9
|
+
vm.data_stack[-1][1][key] = value
|
10
|
+
vm.instruction_pointer = vm.instruction_pointer + 1
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module KoiVMRuby
|
2
|
+
class VM
|
3
|
+
|
4
|
+
@@instruction[PRINT] = Proc.new() do |vm|
|
5
|
+
raise StackError, "Expecting at least one item on the data stack" unless(vm.data_stack.length > 0)
|
6
|
+
value = vm.data_stack.pop
|
7
|
+
raise StackError, "Expecting topmost stack item to be a string but was #{value.class}" unless(value[0] == STRING_)
|
8
|
+
print value[1]
|
9
|
+
vm.instruction_pointer = vm.instruction_pointer + 1
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module KoiVMRuby
|
2
|
+
class VM
|
3
|
+
|
4
|
+
@@instruction[ADD] = 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[-2][1] += vm.data_stack[-1][1]
|
7
|
+
vm.data_stack.pop
|
8
|
+
vm.data_stack[-1][0] = INTEGER_ if(vm.data_stack[-1][1].is_a?(Integer))
|
9
|
+
vm.data_stack[-1][0] = FLOAT_ if(vm.data_stack[-1][1].is_a?(Float))
|
10
|
+
vm.instruction_pointer = vm.instruction_pointer + 1
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module KoiVMRuby
|
2
|
+
class VM
|
3
|
+
|
4
|
+
@@instruction[DIVIDE] = 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[-2][1] = vm.data_stack[-2][1] / vm.data_stack[-1][1]
|
7
|
+
vm.data_stack.pop
|
8
|
+
vm.data_stack[-1][0] = INTEGER_ if(vm.data_stack[-1][1].is_a?(Integer))
|
9
|
+
vm.data_stack[-1][0] = FLOAT_ if(vm.data_stack[-1][1].is_a?(Float))
|
10
|
+
vm.instruction_pointer = vm.instruction_pointer + 1
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module KoiVMRuby
|
2
|
+
class VM
|
3
|
+
|
4
|
+
@@instruction[MULTIPLY] = 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[-2][1] = vm.data_stack[-2][1] * vm.data_stack[-1][1]
|
7
|
+
vm.data_stack.pop
|
8
|
+
vm.data_stack[-1][0] = INTEGER_ if(vm.data_stack[-1][1].is_a?(Integer))
|
9
|
+
vm.data_stack[-1][0] = FLOAT_ if(vm.data_stack[-1][1].is_a?(Float))
|
10
|
+
vm.instruction_pointer = vm.instruction_pointer + 1
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module KoiVMRuby
|
2
|
+
class VM
|
3
|
+
|
4
|
+
@@instruction[SUBTRACT] = 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[-2][1] -= vm.data_stack[-1][1]
|
7
|
+
vm.data_stack.pop
|
8
|
+
vm.data_stack[-1][0] = INTEGER_ if(vm.data_stack[-1][1].is_a?(Integer))
|
9
|
+
vm.data_stack[-1][0] = FLOAT_ if(vm.data_stack[-1][1].is_a?(Float))
|
10
|
+
vm.instruction_pointer = vm.instruction_pointer + 1
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module KoiVMRuby
|
2
|
+
class VM
|
3
|
+
|
4
|
+
@@instruction[PUSH_BOOL] = Proc.new() do |vm|
|
5
|
+
operand = vm.opcodes[vm.instruction_pointer + 1]
|
6
|
+
raise OperandError, "Expecting boolean value but got #{operand.inspect}" unless(operand.is_a?(TrueClass) or operand.is_a?(FalseClass))
|
7
|
+
vm.data_stack.push([BOOL_, operand])
|
8
|
+
vm.instruction_pointer = vm.instruction_pointer + 2
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module KoiVMRuby
|
2
|
+
class VM
|
3
|
+
|
4
|
+
@@instruction[PUSH_FLOAT] = Proc.new() do |vm|
|
5
|
+
operand = vm.opcodes[vm.instruction_pointer + 1]
|
6
|
+
raise OperandError, "Expecting float value but got #{operand.inspect}" unless(operand.is_a?(Float))
|
7
|
+
vm.data_stack.push([FLOAT_, operand])
|
8
|
+
vm.instruction_pointer = vm.instruction_pointer + 2
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module KoiVMRuby
|
2
|
+
class VM
|
3
|
+
|
4
|
+
@@instruction[PUSH_INT] = Proc.new() do |vm|
|
5
|
+
operand = vm.opcodes[vm.instruction_pointer + 1]
|
6
|
+
raise OperandError, "Expecting integer value but got #{operand.inspect}" unless(operand.is_a?(Integer))
|
7
|
+
vm.data_stack.push([INTEGER_, operand])
|
8
|
+
vm.instruction_pointer = vm.instruction_pointer + 2
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module KoiVMRuby
|
2
|
+
class VM
|
3
|
+
|
4
|
+
@@instruction[PUSH_STRING] = Proc.new() do |vm|
|
5
|
+
operand = vm.opcodes[vm.instruction_pointer + 1]
|
6
|
+
raise OperandError, "Expecting string value but got #{operand.inspect}" unless(operand.is_a?(String))
|
7
|
+
vm.data_stack.push([STRING_, operand])
|
8
|
+
vm.instruction_pointer = vm.instruction_pointer + 2
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module KoiVMRuby
|
2
|
+
class VM
|
3
|
+
|
4
|
+
@@instruction[DUP] = Proc.new() do |vm|
|
5
|
+
raise StackError, "Expecting at least two items on the data stack" unless(vm.data_stack.length > 0)
|
6
|
+
vm.data_stack.push(vm.data_stack[-1])
|
7
|
+
vm.instruction_pointer = vm.instruction_pointer + 1
|
8
|
+
end
|
9
|
+
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module KoiVMRuby
|
2
|
+
class VM
|
3
|
+
|
4
|
+
@@instruction[POP] = Proc.new() do |vm|
|
5
|
+
raise StackError, "Expecting at least one item on the data stack" unless(vm.data_stack.length > 0)
|
6
|
+
vm.data_stack.pop
|
7
|
+
vm.instruction_pointer = vm.instruction_pointer + 1
|
8
|
+
end
|
9
|
+
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module KoiVMRuby
|
2
|
+
class VM
|
3
|
+
|
4
|
+
@@instruction[SWAP] = 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.insert(-2, vm.data_stack.pop)
|
7
|
+
vm.instruction_pointer = vm.instruction_pointer + 1
|
8
|
+
end
|
9
|
+
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module KoiVMRuby
|
2
|
+
class VM
|
3
|
+
|
4
|
+
@@instruction[TOP] = Proc.new() do |vm|
|
5
|
+
operand = vm.opcodes[vm.instruction_pointer + 1]
|
6
|
+
raise OperandError, "Expecting operand to be a integer but got #{operand.class}" unless(operand.is_a?(Integer))
|
7
|
+
raise StackError, "Expecting at least #{operand} items on the data stack" unless(vm.data_stack.length > (operand - 1))
|
8
|
+
vm.data_stack.concat(vm.data_stack.slice(-1 - (operand - 1), vm.data_stack.length))
|
9
|
+
vm.instruction_pointer = vm.instruction_pointer + 2
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module KoiVMRuby
|
2
|
+
class VM
|
3
|
+
|
4
|
+
@@instruction[TYPEOF] = Proc.new() do |vm|
|
5
|
+
raise StackError, "Expecting at least one item on the data stack" unless(vm.data_stack.length > 0)
|
6
|
+
value = vm.data_stack.pop
|
7
|
+
vm.data_stack.push([STRING_, "nil"]) if(value[0] == NIL_)
|
8
|
+
vm.data_stack.push([STRING_, "bool"]) if(value[0] == BOOL_)
|
9
|
+
vm.data_stack.push([STRING_, "integer"]) if(value[0] == INTEGER_)
|
10
|
+
vm.data_stack.push([STRING_, "float"]) if(value[0] == FLOAT_)
|
11
|
+
vm.data_stack.push([STRING_, "string"]) if(value[0] == STRING_)
|
12
|
+
vm.data_stack.push([STRING_, "hash"]) if(value[0] == HASH_)
|
13
|
+
vm.data_stack.push([STRING_, "function"]) if(value[0] == FUNCTION_)
|
14
|
+
vm.instruction_pointer = vm.instruction_pointer + 1
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module KoiVMRuby
|
2
|
+
class VM
|
3
|
+
|
4
|
+
@@instruction[CONCAT] = Proc.new() do |vm|
|
5
|
+
raise StackError, "Expecting at least two items on the data stack" unless(vm.data_stack.length > 1)
|
6
|
+
raise StackError, "Expecting at least two strings on the stack" unless((vm.data_stack[-1][0] == STRING_) and (vm.data_stack[-2][0] == STRING_))
|
7
|
+
vm.data_stack[-2][1].concat(vm.data_stack.pop[1])
|
8
|
+
vm.instruction_pointer = vm.instruction_pointer + 1
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module KoiVMRuby
|
2
|
+
class VM
|
3
|
+
|
4
|
+
@@instruction[STRLEN] = Proc.new() do |vm|
|
5
|
+
raise StackError, "Expecting at least one items on the data stack" unless(vm.data_stack.length > 0)
|
6
|
+
raise StackError, "Expecting topmost item on stack to be a string" unless((vm.data_stack[-1][0] == STRING_))
|
7
|
+
vm.data_stack.push([INTEGER_, vm.data_stack.pop[1].length])
|
8
|
+
vm.instruction_pointer = vm.instruction_pointer + 1
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module KoiVMRuby
|
2
|
+
class VM
|
3
|
+
|
4
|
+
@@instruction[TO_STRING] = Proc.new() do |vm|
|
5
|
+
raise StackError, "Expecting at least one item on the data stack" unless(vm.data_stack.length > 0)
|
6
|
+
value = vm.data_stack.pop
|
7
|
+
if(value[0] == NIL_)
|
8
|
+
vm.data_stack.push([STRING_, "nil"])
|
9
|
+
else
|
10
|
+
vm.data_stack.push([STRING_, value[1].to_s])
|
11
|
+
end
|
12
|
+
vm.instruction_pointer = vm.instruction_pointer + 1
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module KoiVMRuby
|
2
|
+
class VM
|
3
|
+
|
4
|
+
@@instruction[SET_GLOBAL] = Proc.new() do |vm|
|
5
|
+
raise StackError, "Expecting at least one item on the data stack" unless(vm.data_stack.length > 0)
|
6
|
+
vm.globals[vm.opcodes[vm.instruction_pointer + 1]] = vm.data_stack.pop
|
7
|
+
vm.instruction_pointer = vm.instruction_pointer + 2
|
8
|
+
end
|
9
|
+
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module KoiVMRuby
|
2
|
+
class VM
|
3
|
+
|
4
|
+
@@instruction[SET_LOCAL] = Proc.new() do |vm|
|
5
|
+
raise StackError, "Expecting at least one item on the data stack" unless(vm.data_stack.length > 0)
|
6
|
+
vm.locals[vm.opcodes[vm.instruction_pointer + 1]] = vm.data_stack.pop
|
7
|
+
vm.instruction_pointer = vm.instruction_pointer + 2
|
8
|
+
end
|
9
|
+
|
10
|
+
end
|
11
|
+
end
|
data/test/.gitkeep
ADDED
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
*.html
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper.rb'))
|
2
|
+
|
3
|
+
class SimpleBenchmark < Test::Unit::TestCase
|
4
|
+
|
5
|
+
require "benchmark"
|
6
|
+
require "stringio"
|
7
|
+
require 'ruby-prof'
|
8
|
+
include KoiVMRuby
|
9
|
+
|
10
|
+
vm = VM.new
|
11
|
+
|
12
|
+
test "simple benchmark" do
|
13
|
+
Benchmark.bmbm do |b|
|
14
|
+
b.report("Ruby") do
|
15
|
+
silence do
|
16
|
+
1000.times do
|
17
|
+
x = 10
|
18
|
+
while(x > -1) do
|
19
|
+
print "#{x}, "
|
20
|
+
x -= 1
|
21
|
+
end
|
22
|
+
print "Blast off!\n"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
b.report("Koi") do
|
28
|
+
silence do
|
29
|
+
1000.times do
|
30
|
+
vm.run [
|
31
|
+
PUSH_INT, 11,
|
32
|
+
PUSH_INT, 1,
|
33
|
+
SUBTRACT,
|
34
|
+
DUP,
|
35
|
+
TO_STRING,
|
36
|
+
PRINT,
|
37
|
+
PUSH_STRING, ", ",
|
38
|
+
PRINT,
|
39
|
+
DUP,
|
40
|
+
PUSH_INT, 0,
|
41
|
+
EQUAL,
|
42
|
+
JUMP_UNLESS, -13,
|
43
|
+
PUSH_STRING, "Blast Off!\n",
|
44
|
+
PRINT
|
45
|
+
]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
test "simple profile" do
|
53
|
+
silence do
|
54
|
+
result = RubyProf.profile do
|
55
|
+
vm.run [
|
56
|
+
PUSH_INT, 11,
|
57
|
+
PUSH_INT, 1,
|
58
|
+
SUBTRACT,
|
59
|
+
DUP,
|
60
|
+
TO_STRING,
|
61
|
+
PRINT,
|
62
|
+
PUSH_STRING, ", ",
|
63
|
+
PRINT,
|
64
|
+
DUP,
|
65
|
+
PUSH_INT, 0,
|
66
|
+
EQUAL,
|
67
|
+
JUMP_UNLESS, -13,
|
68
|
+
PUSH_STRING, "Blast Off!\n",
|
69
|
+
PRINT
|
70
|
+
]
|
71
|
+
end
|
72
|
+
file = File.new(File.join(File.dirname(__FILE__), "koi_profile.html"), "w+")
|
73
|
+
printer = RubyProf::GraphHtmlPrinter.new(result)
|
74
|
+
printer.print(file, :min_percent=>0)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def silence
|
81
|
+
old_stdout = $stdout
|
82
|
+
$stdout = StringIO.new
|
83
|
+
yield
|
84
|
+
$stdout = old_stdout
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|