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.
Files changed (111) hide show
  1. data/.gitignore +2 -0
  2. data/README.rdoc +64 -0
  3. data/Rakefile +42 -0
  4. data/VERSION +1 -0
  5. data/architecture.rdoc +112 -0
  6. data/examples/blastoff.rb +20 -0
  7. data/examples/hello_world.rb +8 -0
  8. data/koi-vm.gemspec +198 -0
  9. data/lib/.gitkeep +0 -0
  10. data/lib/koi-vm-ruby.rb +10 -0
  11. data/lib/koi-vm-ruby/accessors.rb +63 -0
  12. data/lib/koi-vm-ruby/core.rb +48 -0
  13. data/lib/koi-vm-ruby/exceptions.rb +8 -0
  14. data/lib/koi-vm-ruby/helpers.rb +5 -0
  15. data/lib/koi-vm-ruby/opcodes/_opcode_constants.rb +68 -0
  16. data/lib/koi-vm-ruby/opcodes/_value_constants.rb +11 -0
  17. data/lib/koi-vm-ruby/opcodes/comparative_operations/equal.rb +11 -0
  18. data/lib/koi-vm-ruby/opcodes/comparative_operations/greater_than.rb +14 -0
  19. data/lib/koi-vm-ruby/opcodes/comparative_operations/invert.rb +12 -0
  20. data/lib/koi-vm-ruby/opcodes/comparative_operations/less_than.rb +14 -0
  21. data/lib/koi-vm-ruby/opcodes/control_operations/exit.rb +10 -0
  22. data/lib/koi-vm-ruby/opcodes/control_operations/no_op.rb +9 -0
  23. data/lib/koi-vm-ruby/opcodes/flow_control_operations/jump.rb +11 -0
  24. data/lib/koi-vm-ruby/opcodes/flow_control_operations/jump_if.rb +16 -0
  25. data/lib/koi-vm-ruby/opcodes/flow_control_operations/jump_unless.rb +16 -0
  26. data/lib/koi-vm-ruby/opcodes/function_operations/call.rb +13 -0
  27. data/lib/koi-vm-ruby/opcodes/function_operations/push_function.rb +19 -0
  28. data/lib/koi-vm-ruby/opcodes/function_operations/return.rb +11 -0
  29. data/lib/koi-vm-ruby/opcodes/function_operations/tailcall.rb +12 -0
  30. data/lib/koi-vm-ruby/opcodes/hash_operations/get_key.rb +14 -0
  31. data/lib/koi-vm-ruby/opcodes/hash_operations/has_key.rb +18 -0
  32. data/lib/koi-vm-ruby/opcodes/hash_operations/length.rb +19 -0
  33. data/lib/koi-vm-ruby/opcodes/hash_operations/num_pairs.rb +12 -0
  34. data/lib/koi-vm-ruby/opcodes/hash_operations/pairs.rb +22 -0
  35. data/lib/koi-vm-ruby/opcodes/hash_operations/push_hash.rb +10 -0
  36. data/lib/koi-vm-ruby/opcodes/hash_operations/set_key.rb +14 -0
  37. data/lib/koi-vm-ruby/opcodes/io_operations/gets.rb +10 -0
  38. data/lib/koi-vm-ruby/opcodes/io_operations/print.rb +13 -0
  39. data/lib/koi-vm-ruby/opcodes/math_operations/add.rb +14 -0
  40. data/lib/koi-vm-ruby/opcodes/math_operations/divide.rb +14 -0
  41. data/lib/koi-vm-ruby/opcodes/math_operations/multiply.rb +14 -0
  42. data/lib/koi-vm-ruby/opcodes/math_operations/subtract.rb +14 -0
  43. data/lib/koi-vm-ruby/opcodes/push_operations/push_bool.rb +12 -0
  44. data/lib/koi-vm-ruby/opcodes/push_operations/push_float.rb +12 -0
  45. data/lib/koi-vm-ruby/opcodes/push_operations/push_int.rb +12 -0
  46. data/lib/koi-vm-ruby/opcodes/push_operations/push_nil.rb +10 -0
  47. data/lib/koi-vm-ruby/opcodes/push_operations/push_string.rb +12 -0
  48. data/lib/koi-vm-ruby/opcodes/stack_operations/dup.rb +11 -0
  49. data/lib/koi-vm-ruby/opcodes/stack_operations/pop.rb +11 -0
  50. data/lib/koi-vm-ruby/opcodes/stack_operations/stksize.rb +10 -0
  51. data/lib/koi-vm-ruby/opcodes/stack_operations/swap.rb +11 -0
  52. data/lib/koi-vm-ruby/opcodes/stack_operations/top.rb +13 -0
  53. data/lib/koi-vm-ruby/opcodes/stack_operations/typeof.rb +18 -0
  54. data/lib/koi-vm-ruby/opcodes/string_operations/concat.rb +12 -0
  55. data/lib/koi-vm-ruby/opcodes/string_operations/strlen.rb +12 -0
  56. data/lib/koi-vm-ruby/opcodes/string_operations/to_string.rb +16 -0
  57. data/lib/koi-vm-ruby/opcodes/variable_operations/get_global.rb +10 -0
  58. data/lib/koi-vm-ruby/opcodes/variable_operations/get_local.rb +10 -0
  59. data/lib/koi-vm-ruby/opcodes/variable_operations/set_global.rb +11 -0
  60. data/lib/koi-vm-ruby/opcodes/variable_operations/set_local.rb +11 -0
  61. data/test/.gitkeep +0 -0
  62. data/test/performance/.gitignore +1 -0
  63. data/test/performance/simple_benchmark.rb +87 -0
  64. data/test/setup/test_unit_extensions.rb +21 -0
  65. data/test/test_helper.rb +13 -0
  66. data/test/unit/opcodes/comparative_operations/equal_test.rb +116 -0
  67. data/test/unit/opcodes/comparative_operations/greater_than_test.rb +53 -0
  68. data/test/unit/opcodes/comparative_operations/invert_test.rb +44 -0
  69. data/test/unit/opcodes/comparative_operations/less_than_test.rb +53 -0
  70. data/test/unit/opcodes/control_operations/exit_test.rb +20 -0
  71. data/test/unit/opcodes/control_operations/no_op_test.rb +17 -0
  72. data/test/unit/opcodes/flow_control_operations/jump_if_test.rb +50 -0
  73. data/test/unit/opcodes/flow_control_operations/jump_test.rb +36 -0
  74. data/test/unit/opcodes/flow_control_operations/jump_unless_test.rb +50 -0
  75. data/test/unit/opcodes/function_operations/call_test.rb +39 -0
  76. data/test/unit/opcodes/function_operations/push_function_test.rb +41 -0
  77. data/test/unit/opcodes/function_operations/return_test.rb +31 -0
  78. data/test/unit/opcodes/function_operations/tailcall_test.rb +41 -0
  79. data/test/unit/opcodes/hash_operations/get_key_test.rb +56 -0
  80. data/test/unit/opcodes/hash_operations/has_key_test.rb +56 -0
  81. data/test/unit/opcodes/hash_operations/length_test.rb +46 -0
  82. data/test/unit/opcodes/hash_operations/num_pairs_test.rb +46 -0
  83. data/test/unit/opcodes/hash_operations/pairs_test.rb +67 -0
  84. data/test/unit/opcodes/hash_operations/push_hash_test.rb +16 -0
  85. data/test/unit/opcodes/hash_operations/set_key_test.rb +56 -0
  86. data/test/unit/opcodes/io_operations/gets_test.rb +38 -0
  87. data/test/unit/opcodes/io_operations/print_test.rb +42 -0
  88. data/test/unit/opcodes/math_operations/add_test.rb +62 -0
  89. data/test/unit/opcodes/math_operations/divide_test.rb +62 -0
  90. data/test/unit/opcodes/math_operations/multiply_test.rb +62 -0
  91. data/test/unit/opcodes/math_operations/subtract_test.rb +62 -0
  92. data/test/unit/opcodes/push_operations/push_bool_test.rb +36 -0
  93. data/test/unit/opcodes/push_operations/push_float_test.rb +27 -0
  94. data/test/unit/opcodes/push_operations/push_int_test.rb +27 -0
  95. data/test/unit/opcodes/push_operations/push_nil_test.rb +16 -0
  96. data/test/unit/opcodes/push_operations/push_string_test.rb +27 -0
  97. data/test/unit/opcodes/stack_operations/dup_test.rb +25 -0
  98. data/test/unit/opcodes/stack_operations/pop_test.rb +28 -0
  99. data/test/unit/opcodes/stack_operations/stksize_test.rb +20 -0
  100. data/test/unit/opcodes/stack_operations/swap_test.rb +36 -0
  101. data/test/unit/opcodes/stack_operations/top_test.rb +45 -0
  102. data/test/unit/opcodes/stack_operations/typeof_test.rb +79 -0
  103. data/test/unit/opcodes/string_operations/concat_test.rb +65 -0
  104. data/test/unit/opcodes/string_operations/strlen_test.rb +44 -0
  105. data/test/unit/opcodes/string_operations/to_string_test.rb +70 -0
  106. data/test/unit/opcodes/variable_operations/get_global_test.rb +18 -0
  107. data/test/unit/opcodes/variable_operations/get_local_test.rb +18 -0
  108. data/test/unit/opcodes/variable_operations/set_global_test.rb +27 -0
  109. data/test/unit/opcodes/variable_operations/set_local_test.rb +27 -0
  110. data/test/unit/vm_initialization_test.rb +86 -0
  111. 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,10 @@
1
+ module KoiVMRuby
2
+ class VM
3
+
4
+ @@instruction[PUSH_HASH] = Proc.new() do |vm|
5
+ vm.data_stack.push([HASH_, {}])
6
+ vm.instruction_pointer = vm.instruction_pointer + 1
7
+ end
8
+
9
+ end
10
+ 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,10 @@
1
+ module KoiVMRuby
2
+ class VM
3
+
4
+ @@instruction[GETS] = Proc.new() do |vm|
5
+ vm.data_stack.push([STRING_, $stdin.gets("\n")])
6
+ vm.instruction_pointer = vm.instruction_pointer + 1
7
+ end
8
+
9
+ end
10
+ 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,10 @@
1
+ module KoiVMRuby
2
+ class VM
3
+
4
+ @@instruction[PUSH_NIL] = Proc.new() do |vm|
5
+ vm.data_stack.push([NIL_, nil])
6
+ vm.instruction_pointer = vm.instruction_pointer + 1
7
+ end
8
+
9
+ end
10
+ 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,10 @@
1
+ module KoiVMRuby
2
+ class VM
3
+
4
+ @@instruction[STKSIZE] = Proc.new() do |vm|
5
+ vm.data_stack.push([INTEGER_, vm.data_stack.length])
6
+ vm.instruction_pointer = vm.instruction_pointer + 1
7
+ end
8
+
9
+ end
10
+ 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,10 @@
1
+ module KoiVMRuby
2
+ class VM
3
+
4
+ @@instruction[GET_GLOBAL] = Proc.new() do |vm|
5
+ vm.data_stack.push( vm.globals[vm.opcodes[vm.instruction_pointer + 1]] )
6
+ vm.instruction_pointer = vm.instruction_pointer + 2
7
+ end
8
+
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module KoiVMRuby
2
+ class VM
3
+
4
+ @@instruction[GET_LOCAL] = Proc.new() do |vm|
5
+ vm.data_stack.push( vm.locals[vm.opcodes[vm.instruction_pointer + 1]] )
6
+ vm.instruction_pointer = vm.instruction_pointer + 2
7
+ end
8
+
9
+ end
10
+ 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
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