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.
- 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
@@ -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
|