koi-vm 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.
Files changed (95) hide show
  1. data/.gitignore +2 -0
  2. data/README.rdoc +47 -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 +174 -0
  9. data/lib/.gitkeep +0 -0
  10. data/lib/koi-vm/accessors.rb +63 -0
  11. data/lib/koi-vm/core.rb +48 -0
  12. data/lib/koi-vm/exceptions.rb +8 -0
  13. data/lib/koi-vm/helpers.rb +5 -0
  14. data/lib/koi-vm/opcodes/_opcode_constants.rb +58 -0
  15. data/lib/koi-vm/opcodes/_value_constants.rb +10 -0
  16. data/lib/koi-vm/opcodes/comparative_operations/equal.rb +11 -0
  17. data/lib/koi-vm/opcodes/comparative_operations/greater_than.rb +14 -0
  18. data/lib/koi-vm/opcodes/comparative_operations/less_than.rb +14 -0
  19. data/lib/koi-vm/opcodes/control_operations/exit.rb +10 -0
  20. data/lib/koi-vm/opcodes/control_operations/no_op.rb +9 -0
  21. data/lib/koi-vm/opcodes/flow_control_operations/jump.rb +11 -0
  22. data/lib/koi-vm/opcodes/flow_control_operations/jump_if.rb +16 -0
  23. data/lib/koi-vm/opcodes/flow_control_operations/jump_unless.rb +16 -0
  24. data/lib/koi-vm/opcodes/function_operations/call.rb +13 -0
  25. data/lib/koi-vm/opcodes/function_operations/push_function.rb +15 -0
  26. data/lib/koi-vm/opcodes/function_operations/return.rb +11 -0
  27. data/lib/koi-vm/opcodes/function_operations/tailcall.rb +12 -0
  28. data/lib/koi-vm/opcodes/io_operations/gets.rb +10 -0
  29. data/lib/koi-vm/opcodes/io_operations/print.rb +13 -0
  30. data/lib/koi-vm/opcodes/math_operations/add.rb +14 -0
  31. data/lib/koi-vm/opcodes/math_operations/divide.rb +14 -0
  32. data/lib/koi-vm/opcodes/math_operations/multiply.rb +14 -0
  33. data/lib/koi-vm/opcodes/math_operations/subtract.rb +14 -0
  34. data/lib/koi-vm/opcodes/push_operations/push_bool.rb +12 -0
  35. data/lib/koi-vm/opcodes/push_operations/push_float.rb +12 -0
  36. data/lib/koi-vm/opcodes/push_operations/push_int.rb +12 -0
  37. data/lib/koi-vm/opcodes/push_operations/push_nil.rb +10 -0
  38. data/lib/koi-vm/opcodes/push_operations/push_string.rb +12 -0
  39. data/lib/koi-vm/opcodes/stack_operations/dup.rb +11 -0
  40. data/lib/koi-vm/opcodes/stack_operations/pop.rb +11 -0
  41. data/lib/koi-vm/opcodes/stack_operations/stksize.rb +10 -0
  42. data/lib/koi-vm/opcodes/stack_operations/swap.rb +11 -0
  43. data/lib/koi-vm/opcodes/stack_operations/top.rb +13 -0
  44. data/lib/koi-vm/opcodes/stack_operations/typeof.rb +16 -0
  45. data/lib/koi-vm/opcodes/string_operations/concat.rb +12 -0
  46. data/lib/koi-vm/opcodes/string_operations/strlen.rb +12 -0
  47. data/lib/koi-vm/opcodes/string_operations/to_string.rb +16 -0
  48. data/lib/koi-vm/opcodes/variable_operations/get_global.rb +10 -0
  49. data/lib/koi-vm/opcodes/variable_operations/get_local.rb +10 -0
  50. data/lib/koi-vm/opcodes/variable_operations/set_global.rb +11 -0
  51. data/lib/koi-vm/opcodes/variable_operations/set_local.rb +11 -0
  52. data/lib/koi-vm.rb +10 -0
  53. data/test/.gitkeep +0 -0
  54. data/test/performance/.gitignore +1 -0
  55. data/test/performance/simple_benchmark.rb +87 -0
  56. data/test/setup/test_unit_extensions.rb +21 -0
  57. data/test/test_helper.rb +13 -0
  58. data/test/unit/opcodes/comparative_operations/equal_test.rb +116 -0
  59. data/test/unit/opcodes/comparative_operations/greater_than_test.rb +53 -0
  60. data/test/unit/opcodes/comparative_operations/less_than_test.rb +53 -0
  61. data/test/unit/opcodes/control_operations/exit_test.rb +20 -0
  62. data/test/unit/opcodes/control_operations/no_op_test.rb +17 -0
  63. data/test/unit/opcodes/flow_control_operations/jump_if_test.rb +50 -0
  64. data/test/unit/opcodes/flow_control_operations/jump_test.rb +36 -0
  65. data/test/unit/opcodes/flow_control_operations/jump_unless_test.rb +50 -0
  66. data/test/unit/opcodes/function_operations/call_test.rb +39 -0
  67. data/test/unit/opcodes/function_operations/push_function_test.rb +21 -0
  68. data/test/unit/opcodes/function_operations/return_test.rb +31 -0
  69. data/test/unit/opcodes/function_operations/tailcall_test.rb +41 -0
  70. data/test/unit/opcodes/io_operations/gets_test.rb +38 -0
  71. data/test/unit/opcodes/io_operations/print_test.rb +42 -0
  72. data/test/unit/opcodes/math_operations/add_test.rb +62 -0
  73. data/test/unit/opcodes/math_operations/divide_test.rb +62 -0
  74. data/test/unit/opcodes/math_operations/multiply_test.rb +62 -0
  75. data/test/unit/opcodes/math_operations/subtract_test.rb +62 -0
  76. data/test/unit/opcodes/push_operations/push_bool_test.rb +36 -0
  77. data/test/unit/opcodes/push_operations/push_float_test.rb +27 -0
  78. data/test/unit/opcodes/push_operations/push_int_test.rb +27 -0
  79. data/test/unit/opcodes/push_operations/push_nil_test.rb +16 -0
  80. data/test/unit/opcodes/push_operations/push_string_test.rb +27 -0
  81. data/test/unit/opcodes/stack_operations/dup_test.rb +25 -0
  82. data/test/unit/opcodes/stack_operations/pop_test.rb +28 -0
  83. data/test/unit/opcodes/stack_operations/stksize_test.rb +20 -0
  84. data/test/unit/opcodes/stack_operations/swap_test.rb +36 -0
  85. data/test/unit/opcodes/stack_operations/top_test.rb +45 -0
  86. data/test/unit/opcodes/stack_operations/typeof_test.rb +61 -0
  87. data/test/unit/opcodes/string_operations/concat_test.rb +65 -0
  88. data/test/unit/opcodes/string_operations/strlen_test.rb +44 -0
  89. data/test/unit/opcodes/string_operations/to_string_test.rb +70 -0
  90. data/test/unit/opcodes/variable_operations/get_global_test.rb +18 -0
  91. data/test/unit/opcodes/variable_operations/get_local_test.rb +18 -0
  92. data/test/unit/opcodes/variable_operations/set_global_test.rb +27 -0
  93. data/test/unit/opcodes/variable_operations/set_local_test.rb +27 -0
  94. data/test/unit/vm_initialization_test.rb +86 -0
  95. metadata +200 -0
@@ -0,0 +1,62 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper.rb'))
2
+
3
+ class DivideTest < Test::Unit::TestCase
4
+
5
+ include KoiVM
6
+
7
+ test "should divide top two integers on stack" do
8
+ vm = VM.new
9
+ vm.data_stack = [[INTEGER_, 10], [INTEGER_, 3]]
10
+ vm.run [
11
+ DIVIDE
12
+ ]
13
+ assert_equal [[INTEGER_, 3]], vm.data_stack
14
+ end
15
+
16
+ test "should divide top two floats on stack" do
17
+ vm = VM.new
18
+ vm.data_stack = [[FLOAT_, 10.0], [FLOAT_, 3.0]]
19
+ vm.run [
20
+ DIVIDE
21
+ ]
22
+ assert_equal [[FLOAT_, 10.0 / 3.0]], vm.data_stack
23
+ end
24
+
25
+ test "should divide top two numbers on stack and implicitly convert them to floats" do
26
+ vm = VM.new
27
+ vm.data_stack = [[INTEGER_, 10], [FLOAT_, 3.0]]
28
+ vm.run [
29
+ DIVIDE
30
+ ]
31
+ assert_equal [[FLOAT_, 10.0 / 3.0]], vm.data_stack
32
+ end
33
+
34
+ test "should divide top two numbers on stack and implicitly convert them to floats if receiver is a float" do
35
+ vm = VM.new
36
+ vm.data_stack = [[FLOAT_, 10.0], [INTEGER_, 3]]
37
+ vm.run [
38
+ DIVIDE
39
+ ]
40
+ assert_equal [[FLOAT_, 10.0 / 3.0]], vm.data_stack
41
+ end
42
+
43
+ test "should raise StackError if there is only one item on the stack" do
44
+ assert_raises StackError do
45
+ vm = VM.new
46
+ vm.data_stack = [1]
47
+ vm.run [
48
+ DIVIDE
49
+ ]
50
+ end
51
+ end
52
+
53
+ test "should raise StackError if there are no items on the stack" do
54
+ assert_raises StackError do
55
+ vm = VM.new
56
+ vm.run [
57
+ DIVIDE
58
+ ]
59
+ end
60
+ end
61
+
62
+ end
@@ -0,0 +1,62 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper.rb'))
2
+
3
+ class MultiplyTest < Test::Unit::TestCase
4
+
5
+ include KoiVM
6
+
7
+ test "should multiply top two integers on stack" do
8
+ vm = VM.new
9
+ vm.data_stack = [[INTEGER_, 5], [INTEGER_, 2]]
10
+ vm.run [
11
+ MULTIPLY
12
+ ]
13
+ assert_equal [[INTEGER_, 10]], vm.data_stack
14
+ end
15
+
16
+ test "should multiply top two floats on stack" do
17
+ vm = VM.new
18
+ vm.data_stack = [[FLOAT_, 5.0], [FLOAT_, 2.0]]
19
+ vm.run [
20
+ MULTIPLY
21
+ ]
22
+ assert_equal [[FLOAT_, 10.0]], vm.data_stack
23
+ end
24
+
25
+ test "should multiply top two numbers on stack and implicitly convert them to floats" do
26
+ vm = VM.new
27
+ vm.data_stack = [[INTEGER_, 5], [FLOAT_, 2.0]]
28
+ vm.run [
29
+ MULTIPLY
30
+ ]
31
+ assert_equal [[FLOAT_, 10.0]], vm.data_stack
32
+ end
33
+
34
+ test "should multiply top two numbers on stack and implicitly convert them to floats if receiver is a float" do
35
+ vm = VM.new
36
+ vm.data_stack = [[FLOAT_, 5.0], [INTEGER_, 2]]
37
+ vm.run [
38
+ MULTIPLY
39
+ ]
40
+ assert_equal [[FLOAT_, 10.0]], vm.data_stack
41
+ end
42
+
43
+ test "should raise StackError if there is only one item on the stack" do
44
+ assert_raises StackError do
45
+ vm = VM.new
46
+ vm.data_stack = [1]
47
+ vm.run [
48
+ MULTIPLY
49
+ ]
50
+ end
51
+ end
52
+
53
+ test "should raise StackError if there are no items on the stack" do
54
+ assert_raises StackError do
55
+ vm = VM.new
56
+ vm.run [
57
+ MULTIPLY
58
+ ]
59
+ end
60
+ end
61
+
62
+ end
@@ -0,0 +1,62 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper.rb'))
2
+
3
+ class SubtractTest < Test::Unit::TestCase
4
+
5
+ include KoiVM
6
+
7
+ test "should subtract top two integers on stack" do
8
+ vm = VM.new
9
+ vm.data_stack = [[INTEGER_, 5], [INTEGER_, 2]]
10
+ vm.run [
11
+ SUBTRACT
12
+ ]
13
+ assert_equal [[INTEGER_, 3]], vm.data_stack
14
+ end
15
+
16
+ test "should subtract top two floats on stack" do
17
+ vm = VM.new
18
+ vm.data_stack = [[FLOAT_, 5.0], [FLOAT_, 2.0]]
19
+ vm.run [
20
+ SUBTRACT
21
+ ]
22
+ assert_equal [[FLOAT_, 3.0]], vm.data_stack
23
+ end
24
+
25
+ test "should subtract top two numbers on stack and implicitly convert them to floats" do
26
+ vm = VM.new
27
+ vm.data_stack = [[INTEGER_, 5], [FLOAT_, 2.0]]
28
+ vm.run [
29
+ SUBTRACT
30
+ ]
31
+ assert_equal [[FLOAT_, 3.0]], vm.data_stack
32
+ end
33
+
34
+ test "should subtract top two numbers on stack and implicitly convert them to floats if receiver is a float" do
35
+ vm = VM.new
36
+ vm.data_stack = [[FLOAT_, 5.0], [INTEGER_, 2]]
37
+ vm.run [
38
+ SUBTRACT
39
+ ]
40
+ assert_equal [[FLOAT_, 3.0]], vm.data_stack
41
+ end
42
+
43
+ test "should raise StackError if there is only one item on the stack" do
44
+ assert_raises StackError do
45
+ vm = VM.new
46
+ vm.data_stack = [1]
47
+ vm.run [
48
+ SUBTRACT
49
+ ]
50
+ end
51
+ end
52
+
53
+ test "should raise StackError if there are no items on the stack" do
54
+ assert_raises StackError do
55
+ vm = VM.new
56
+ vm.run [
57
+ SUBTRACT
58
+ ]
59
+ end
60
+ end
61
+
62
+ end
@@ -0,0 +1,36 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper.rb'))
2
+
3
+ class PushBoolTest < Test::Unit::TestCase
4
+
5
+ include KoiVM
6
+
7
+ test "should put true onto stack" do
8
+ vm = VM.new
9
+ vm.run [
10
+ PUSH_BOOL, true
11
+ ]
12
+ assert_equal [[BOOL_, true]], vm.data_stack
13
+ assert_equal 2, vm.instruction_pointer
14
+ end
15
+
16
+ test "should put false onto stack" do
17
+ vm = VM.new
18
+ vm.run [
19
+ PUSH_BOOL, false
20
+ ]
21
+ assert_equal [[BOOL_, false]], vm.data_stack
22
+ assert_equal 2, vm.instruction_pointer
23
+ end
24
+
25
+ test "should raise error if operand is not a boolean value" do
26
+ [1,2.0,"string", [1], {:t=>1}].each do |x|
27
+ assert_raises OperandError do
28
+ vm = VM.new
29
+ vm.run [
30
+ PUSH_BOOL, x
31
+ ]
32
+ end
33
+ end
34
+ end
35
+
36
+ end
@@ -0,0 +1,27 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper.rb'))
2
+
3
+ class PushFloatTest < Test::Unit::TestCase
4
+
5
+ include KoiVM
6
+
7
+ test "should push float onto stack" do
8
+ vm = VM.new
9
+ vm.run [
10
+ PUSH_FLOAT, 99.9
11
+ ]
12
+ assert_equal [[FLOAT_, 99.9]], vm.data_stack
13
+ assert_equal 2, vm.instruction_pointer
14
+ end
15
+
16
+ test "should raise error if operand is not a float" do
17
+ [false, 2, "string", [1], {:t=>1}].each do |x|
18
+ assert_raises OperandError do
19
+ vm = VM.new
20
+ vm.run [
21
+ PUSH_FLOAT, x
22
+ ]
23
+ end
24
+ end
25
+ end
26
+
27
+ end
@@ -0,0 +1,27 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper.rb'))
2
+
3
+ class PushIntTest < Test::Unit::TestCase
4
+
5
+ include KoiVM
6
+
7
+ test "should put integer onto stack" do
8
+ vm = VM.new
9
+ vm.run [
10
+ PUSH_INT, 99
11
+ ]
12
+ assert_equal [[INTEGER_, 99]], vm.data_stack
13
+ assert_equal 2, vm.instruction_pointer
14
+ end
15
+
16
+ test "should raise error if operand is not an integer" do
17
+ [false, 2.0, "string", [1], {:t=>1}].each do |x|
18
+ assert_raises OperandError do
19
+ vm = VM.new
20
+ vm.run [
21
+ PUSH_INT, x
22
+ ]
23
+ end
24
+ end
25
+ end
26
+
27
+ end
@@ -0,0 +1,16 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper.rb'))
2
+
3
+ class PushNilTest < Test::Unit::TestCase
4
+
5
+ include KoiVM
6
+
7
+ test "should put nil onto stack" do
8
+ vm = VM.new
9
+ vm.run [
10
+ PUSH_NIL
11
+ ]
12
+ assert_equal [[NIL_, nil]], vm.data_stack
13
+ assert_equal 1, vm.instruction_pointer
14
+ end
15
+
16
+ end
@@ -0,0 +1,27 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper.rb'))
2
+
3
+ class PushStringTest < Test::Unit::TestCase
4
+
5
+ include KoiVM
6
+
7
+ test "should push string onto stack" do
8
+ vm = VM.new
9
+ vm.run [
10
+ PUSH_STRING, "test"
11
+ ]
12
+ assert_equal [[STRING_, "test"]], vm.data_stack
13
+ assert_equal 2, vm.instruction_pointer
14
+ end
15
+
16
+ test "should raise error if operand is not a string" do
17
+ [false, 2, 2.0, [1], {:t=>1}].each do |x|
18
+ assert_raises OperandError do
19
+ vm = VM.new
20
+ vm.run [
21
+ PUSH_STRING, x
22
+ ]
23
+ end
24
+ end
25
+ end
26
+
27
+ end
@@ -0,0 +1,25 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper.rb'))
2
+
3
+ class DupTest < Test::Unit::TestCase
4
+
5
+ include KoiVM
6
+
7
+ test "should duplicate the topmost item on the data stack" do
8
+ vm = VM.new
9
+ vm.data_stack = [2]
10
+ vm.run [
11
+ DUP
12
+ ]
13
+ assert_equal [2,2], vm.data_stack
14
+ end
15
+
16
+ test "should raise StackError if there are no items on the stack" do
17
+ assert_raises StackError do
18
+ vm = VM.new
19
+ vm.run [
20
+ DUP
21
+ ]
22
+ end
23
+ end
24
+
25
+ end
@@ -0,0 +1,28 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper.rb'))
2
+
3
+ class PopTest < Test::Unit::TestCase
4
+
5
+ include KoiVM
6
+
7
+ test "should pop a single item off the data stack" do
8
+ (1..10).each do |x|
9
+ vm = VM.new
10
+ vm.data_stack.fill("x", 0..(x - 1))
11
+ assert_equal x, vm.data_stack.length
12
+ vm.run [
13
+ POP
14
+ ]
15
+ assert_equal x - 1, vm.data_stack.length
16
+ end
17
+ end
18
+
19
+ test "should raise StackError if there are no items on the stack" do
20
+ assert_raises StackError do
21
+ vm = VM.new
22
+ vm.run [
23
+ POP
24
+ ]
25
+ end
26
+ end
27
+
28
+ end
@@ -0,0 +1,20 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper.rb'))
2
+
3
+ class StksizeTest < Test::Unit::TestCase
4
+
5
+ include KoiVM
6
+
7
+ test "should push an integer onto the stack representing the number of entries on the stack before the call" do
8
+ (1..10).each do |x|
9
+ vm = VM.new
10
+ vm.data_stack.fill("x", 0..(x - 1))
11
+ assert_equal x, vm.data_stack.length
12
+ vm.data_stack.length
13
+ vm.run [
14
+ STKSIZE
15
+ ]
16
+ assert_equal [INTEGER_, vm.data_stack.length - 1], vm.data_stack.last
17
+ end
18
+ end
19
+
20
+ end
@@ -0,0 +1,36 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper.rb'))
2
+
3
+ class SwapTest < Test::Unit::TestCase
4
+
5
+ include KoiVM
6
+
7
+ test "should swap the two topmost items on the data stack" do
8
+ vm = VM.new
9
+ vm.data_stack = [1,2]
10
+ vm.run [
11
+ SWAP
12
+ ]
13
+ assert_equal [2,1], vm.data_stack
14
+ assert_equal 1, vm.instruction_pointer
15
+ end
16
+
17
+ test "should raise StackError if there are no items on the stack" do
18
+ assert_raises StackError do
19
+ vm = VM.new
20
+ vm.run [
21
+ SWAP
22
+ ]
23
+ end
24
+ end
25
+
26
+ test "should raise StackError if there are less than 2 items on the stack" do
27
+ assert_raises StackError do
28
+ vm = VM.new
29
+ vm.data_stack = [1]
30
+ vm.run [
31
+ SWAP
32
+ ]
33
+ end
34
+ end
35
+
36
+ end
@@ -0,0 +1,45 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper.rb'))
2
+
3
+ class TopTest < Test::Unit::TestCase
4
+
5
+ include KoiVM
6
+
7
+ test "should duplicate the topmost n items on the data stack" do
8
+ vm = VM.new
9
+ vm.data_stack = [1,2,2]
10
+ vm.run [
11
+ TOP, 2
12
+ ]
13
+ assert_equal [1,2,2,2,2], vm.data_stack
14
+ end
15
+
16
+ test "should raise OperandError if operand is not an integer" do
17
+ assert_raises OperandError do
18
+ vm = VM.new
19
+ vm.data_stack = [1,2]
20
+ vm.run [
21
+ TOP, "a"
22
+ ]
23
+ end
24
+ end
25
+
26
+ test "should raise StackError if there are not enough items on the stack" do
27
+ assert_raises StackError do
28
+ vm = VM.new
29
+ vm.data_stack = [1]
30
+ vm.run [
31
+ TOP, 2
32
+ ]
33
+ end
34
+ end
35
+
36
+ test "should raise StackError if there are no items on the stack" do
37
+ assert_raises StackError do
38
+ vm = VM.new
39
+ vm.run [
40
+ TOP, 2
41
+ ]
42
+ end
43
+ end
44
+
45
+ end
@@ -0,0 +1,61 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper.rb'))
2
+
3
+ class TypeofTest < Test::Unit::TestCase
4
+
5
+ include KoiVM
6
+
7
+ test "should push string representing type of topmost stack item onto the stack (nil)" do
8
+ vm = VM.new
9
+ vm.data_stack = [[NIL_, nil]]
10
+ vm.run [
11
+ TYPEOF
12
+ ]
13
+ assert_equal [[STRING_, "nil"]], vm.data_stack
14
+ end
15
+
16
+ test "should push string representing type of topmost stack item onto the stack (bool)" do
17
+ vm = VM.new
18
+ vm.data_stack = [[BOOL_, true]]
19
+ vm.run [
20
+ TYPEOF
21
+ ]
22
+ assert_equal [[STRING_, "bool"]], vm.data_stack
23
+ end
24
+
25
+ test "should push string representing type of topmost stack item onto the stack (integer)" do
26
+ vm = VM.new
27
+ vm.data_stack = [[INTEGER_, 1]]
28
+ vm.run [
29
+ TYPEOF
30
+ ]
31
+ assert_equal [[STRING_, "integer"]], vm.data_stack
32
+ end
33
+
34
+ test "should push string representing type of topmost stack item onto the stack (float)" do
35
+ vm = VM.new
36
+ vm.data_stack = [[FLOAT_, 1.0]]
37
+ vm.run [
38
+ TYPEOF
39
+ ]
40
+ assert_equal [[STRING_, "float"]], vm.data_stack
41
+ end
42
+
43
+ test "should push string representing type of topmost stack item onto the stack (string)" do
44
+ vm = VM.new
45
+ vm.data_stack = [[STRING_, true]]
46
+ vm.run [
47
+ TYPEOF
48
+ ]
49
+ assert_equal [[STRING_, "string"]], vm.data_stack
50
+ end
51
+
52
+ test "should raise StackError if there are no items on the stack" do
53
+ assert_raises StackError do
54
+ vm = VM.new
55
+ vm.run [
56
+ TYPEOF
57
+ ]
58
+ end
59
+ end
60
+
61
+ end
@@ -0,0 +1,65 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper.rb'))
2
+
3
+ class ConcatTest < Test::Unit::TestCase
4
+
5
+ include KoiVM
6
+
7
+ test "should add top two strings on stack" do
8
+ vm = VM.new
9
+ vm.data_stack = [[STRING_, "hi"], [STRING_, "hi"]]
10
+ vm.run [
11
+ CONCAT
12
+ ]
13
+ assert_equal [[STRING_, "hihi"]], vm.data_stack
14
+ end
15
+
16
+ test "should raise StackError if either of the top two stack items are not strings 1" do
17
+ assert_raises StackError do
18
+ vm = VM.new
19
+ vm.data_stack = [[STRING_, "hi"], [INTEGER_, 1]]
20
+ vm.run [
21
+ CONCAT
22
+ ]
23
+ end
24
+ end
25
+
26
+ test "should raise StackError if either of the top two stack items are not strings 2" do
27
+ assert_raises StackError do
28
+ vm = VM.new
29
+ vm.data_stack = [[INTEGER_, 1], [STRING_, "hi"]]
30
+ vm.run [
31
+ CONCAT
32
+ ]
33
+ end
34
+ end
35
+
36
+ test "should raise StackError if either of the top two stack items are not strings 3" do
37
+ assert_raises StackError do
38
+ vm = VM.new
39
+ vm.data_stack = [[INTEGER_, 1], [INTEGER_, 1]]
40
+ vm.run [
41
+ CONCAT
42
+ ]
43
+ end
44
+ end
45
+
46
+ test "should raise StackError if there is only one item on the stack" do
47
+ assert_raises StackError do
48
+ vm = VM.new
49
+ vm.data_stack = [1]
50
+ vm.run [
51
+ CONCAT
52
+ ]
53
+ end
54
+ end
55
+
56
+ test "should raise StackError if there are no items on the stack" do
57
+ assert_raises StackError do
58
+ vm = VM.new
59
+ vm.run [
60
+ CONCAT
61
+ ]
62
+ end
63
+ end
64
+
65
+ end
@@ -0,0 +1,44 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper.rb'))
2
+
3
+ class StrlenTest < Test::Unit::TestCase
4
+
5
+ include KoiVM
6
+
7
+ test "should push length of topmost string onto stack 1" do
8
+ vm = VM.new
9
+ vm.data_stack = [[STRING_, "hi"]]
10
+ vm.run [
11
+ STRLEN
12
+ ]
13
+ assert_equal [[INTEGER_, 2]], vm.data_stack
14
+ end
15
+
16
+ test "should push length of topmost string onto stack 2" do
17
+ vm = VM.new
18
+ vm.data_stack = [[STRING_, "hihi"]]
19
+ vm.run [
20
+ STRLEN
21
+ ]
22
+ assert_equal [[INTEGER_, 4]], vm.data_stack
23
+ end
24
+
25
+ test "should raise StackError if topmost item is not a string" do
26
+ assert_raises StackError do
27
+ vm = VM.new
28
+ vm.data_stack = [[STRING_, "hi"], [INTEGER_, 1]]
29
+ vm.run [
30
+ STRLEN
31
+ ]
32
+ end
33
+ end
34
+
35
+ test "should raise StackError if there are no items on the stack" do
36
+ assert_raises StackError do
37
+ vm = VM.new
38
+ vm.run [
39
+ STRLEN
40
+ ]
41
+ end
42
+ end
43
+
44
+ end