koi-reference-compiler 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 (79) hide show
  1. data/.gitignore +3 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +76 -0
  4. data/Rakefile +42 -0
  5. data/VERSION +1 -0
  6. data/lib/koi-reference-compiler.rb +10 -0
  7. data/lib/koi-reference-compiler/exceptions.rb +2 -0
  8. data/lib/koi-reference-compiler/koi-reference-compiler.rb +23 -0
  9. data/lib/koi-reference-compiler/node_extensions/assignment/assignment.rb +12 -0
  10. data/lib/koi-reference-compiler/node_extensions/blocks/block.rb +13 -0
  11. data/lib/koi-reference-compiler/node_extensions/control_flow/if.rb +14 -0
  12. data/lib/koi-reference-compiler/node_extensions/control_flow/unless.rb +14 -0
  13. data/lib/koi-reference-compiler/node_extensions/expressions/additive_expression.rb +13 -0
  14. data/lib/koi-reference-compiler/node_extensions/expressions/comparative_expression.rb +13 -0
  15. data/lib/koi-reference-compiler/node_extensions/expressions/expression.rb +9 -0
  16. data/lib/koi-reference-compiler/node_extensions/expressions/multitive_expression.rb +13 -0
  17. data/lib/koi-reference-compiler/node_extensions/functions/function_call.rb +54 -0
  18. data/lib/koi-reference-compiler/node_extensions/functions/function_definition.rb +19 -0
  19. data/lib/koi-reference-compiler/node_extensions/hash_literals/hash_access.rb +12 -0
  20. data/lib/koi-reference-compiler/node_extensions/hash_literals/hash_accessor.rb +15 -0
  21. data/lib/koi-reference-compiler/node_extensions/hash_literals/hash_accessor_list.rb +26 -0
  22. data/lib/koi-reference-compiler/node_extensions/hash_literals/hash_assignment.rb +17 -0
  23. data/lib/koi-reference-compiler/node_extensions/hash_literals/hash_literal.rb +11 -0
  24. data/lib/koi-reference-compiler/node_extensions/hash_literals/key_value.rb +13 -0
  25. data/lib/koi-reference-compiler/node_extensions/hash_literals/key_value_list.rb +13 -0
  26. data/lib/koi-reference-compiler/node_extensions/identifiers/identifier.rb +31 -0
  27. data/lib/koi-reference-compiler/node_extensions/literals/false_literal.rb +9 -0
  28. data/lib/koi-reference-compiler/node_extensions/literals/float_literal.rb +9 -0
  29. data/lib/koi-reference-compiler/node_extensions/literals/integer_literal.rb +9 -0
  30. data/lib/koi-reference-compiler/node_extensions/literals/nil_literal.rb +9 -0
  31. data/lib/koi-reference-compiler/node_extensions/literals/string_literal.rb +9 -0
  32. data/lib/koi-reference-compiler/node_extensions/literals/true_literal.rb +9 -0
  33. data/lib/koi-reference-compiler/node_extensions/operators/addition_operator.rb +9 -0
  34. data/lib/koi-reference-compiler/node_extensions/operators/assignment_operator.rb +6 -0
  35. data/lib/koi-reference-compiler/node_extensions/operators/division_operator.rb +9 -0
  36. data/lib/koi-reference-compiler/node_extensions/operators/equality_operator.rb +9 -0
  37. data/lib/koi-reference-compiler/node_extensions/operators/great_than_operator.rb +9 -0
  38. data/lib/koi-reference-compiler/node_extensions/operators/inequality_operator.rb +9 -0
  39. data/lib/koi-reference-compiler/node_extensions/operators/less_than_operator.rb +9 -0
  40. data/lib/koi-reference-compiler/node_extensions/operators/multiplication_operator.rb +9 -0
  41. data/lib/koi-reference-compiler/node_extensions/operators/subtraction_operator.rb +9 -0
  42. data/lib/koi-reference-compiler/node_extensions/statements/statement.rb +9 -0
  43. data/lib/koi-reference-compiler/syntax_node.rb +18 -0
  44. data/lib/koi-reference-compiler/vm_opcodes.rb +70 -0
  45. data/test/compiler/unit/ast_hash_loader/ast_hash_loader_test.rb +46 -0
  46. data/test/compiler/unit/node_extensions/assignment/assignment_test.rb +22 -0
  47. data/test/compiler/unit/node_extensions/blocks/block_test.rb +37 -0
  48. data/test/compiler/unit/node_extensions/control_flow/if_test.rb +39 -0
  49. data/test/compiler/unit/node_extensions/control_flow/unless_test.rb +40 -0
  50. data/test/compiler/unit/node_extensions/expressions/additive_expression_test.rb +21 -0
  51. data/test/compiler/unit/node_extensions/expressions/comparative_expression_test.rb +21 -0
  52. data/test/compiler/unit/node_extensions/expressions/expression_test.rb +17 -0
  53. data/test/compiler/unit/node_extensions/expressions/multitive_expression_test.rb +21 -0
  54. data/test/compiler/unit/node_extensions/functions/function_call_test.rb +296 -0
  55. data/test/compiler/unit/node_extensions/functions/function_definition_test.rb +37 -0
  56. data/test/compiler/unit/node_extensions/hash_literals/hash_accessor_list_test.rb +83 -0
  57. data/test/compiler/unit/node_extensions/hash_literals/hash_accessor_test.rb +33 -0
  58. data/test/compiler/unit/node_extensions/hash_literals/hash_literal_test.rb +29 -0
  59. data/test/compiler/unit/node_extensions/hash_literals/key_value_list_test.rb +37 -0
  60. data/test/compiler/unit/node_extensions/hash_literals/key_value_test.rb +24 -0
  61. data/test/compiler/unit/node_extensions/identifiers/identifier_test.rb +103 -0
  62. data/test/compiler/unit/node_extensions/literals/false_literal_test.rb +13 -0
  63. data/test/compiler/unit/node_extensions/literals/float_literal_test.rb +13 -0
  64. data/test/compiler/unit/node_extensions/literals/integer_literal_test.rb +13 -0
  65. data/test/compiler/unit/node_extensions/literals/nil_literal_test.rb +13 -0
  66. data/test/compiler/unit/node_extensions/literals/string_literal_test.rb +13 -0
  67. data/test/compiler/unit/node_extensions/literals/true_literal_test.rb +13 -0
  68. data/test/compiler/unit/node_extensions/operators/addition_operator_test.rb +13 -0
  69. data/test/compiler/unit/node_extensions/operators/division_operator_test.rb +13 -0
  70. data/test/compiler/unit/node_extensions/operators/equality_operator_test.rb +13 -0
  71. data/test/compiler/unit/node_extensions/operators/greater_than_operator_test.rb +13 -0
  72. data/test/compiler/unit/node_extensions/operators/inequality_operator_test.rb +13 -0
  73. data/test/compiler/unit/node_extensions/operators/less_than_operator_test.rb +13 -0
  74. data/test/compiler/unit/node_extensions/operators/multiplication_operator_test.rb +13 -0
  75. data/test/compiler/unit/node_extensions/operators/subtraction_operator_test.rb +13 -0
  76. data/test/compiler/unit/node_extensions/statements/statement_test.rb +24 -0
  77. data/test/setup/test_unit_extensions.rb +21 -0
  78. data/test/test_helper.rb +10 -0
  79. metadata +177 -0
@@ -0,0 +1,39 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'test_helper.rb'))
2
+
3
+ class IfTest < Test::Unit::TestCase
4
+
5
+ include KoiReferenceCompiler
6
+
7
+ test "should compile If" do
8
+ tree = If.new("if( 1 == 1 )\n arg = 1\n end", 0, [
9
+ Expression.new("1 == 1", 4, [
10
+ ComparativeExpression.new("1 == 1", 4, [
11
+ IntegerLiteral.new("1", 4),
12
+ EqualityOperator.new("==", 6),
13
+ IntegerLiteral.new("1", 9)
14
+ ])
15
+ ]),
16
+ Block.new("arg = 1\n", 13,[
17
+ Statement.new("arg = 1", 13, [
18
+ Assignment.new("arg = 1", 14, [
19
+ Identifier.new("arg", 14),
20
+ AssignmentOperator.new("=", 18),
21
+ Expression.new("1", 20, [
22
+ IntegerLiteral.new("1", 20)
23
+ ])
24
+ ])
25
+ ])
26
+ ])
27
+ ])
28
+ bytecode = tree.compile
29
+ assert_equal [
30
+ PUSH_INT, 1,
31
+ PUSH_INT, 1,
32
+ EQUAL,
33
+ JUMP_UNLESS, 6,
34
+ PUSH_INT, 1,
35
+ SET_LOCAL, :arg
36
+ ], bytecode
37
+ end
38
+
39
+ end
@@ -0,0 +1,40 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'test_helper.rb'))
2
+
3
+ class UnlessTest < Test::Unit::TestCase
4
+
5
+ include KoiReferenceCompiler
6
+
7
+ test "should compile Unless" do
8
+ input = "unless( 1 == 1 )\n arg = 1\n end"
9
+ tree = Unless.new("unless( 1 == 1 )\n arg = 1\n end", 0, [
10
+ Expression.new("1 == 1", 8, [
11
+ ComparativeExpression.new("1 == 1", 8, [
12
+ IntegerLiteral.new("1", 8),
13
+ EqualityOperator.new("==", 10),
14
+ IntegerLiteral.new("1", 13)
15
+ ])
16
+ ]),
17
+ Block.new("arg = 1\n", 17,[
18
+ Statement.new("arg = 1", 17, [
19
+ Assignment.new("arg = 1", 18, [
20
+ Identifier.new("arg", 18),
21
+ AssignmentOperator.new("=", 22),
22
+ Expression.new("1", 24, [
23
+ IntegerLiteral.new("1", 24)
24
+ ])
25
+ ])
26
+ ])
27
+ ])
28
+ ])
29
+ bytecode = tree.compile
30
+ assert_equal [
31
+ PUSH_INT, 1,
32
+ PUSH_INT, 1,
33
+ EQUAL,
34
+ JUMP_IF, 6,
35
+ PUSH_INT, 1,
36
+ SET_LOCAL, :arg
37
+ ], bytecode
38
+ end
39
+
40
+ end
@@ -0,0 +1,21 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'test_helper.rb'))
2
+
3
+ class AdditiveExpressionTest < Test::Unit::TestCase
4
+
5
+ include KoiReferenceCompiler
6
+
7
+ test "should compile AdditiveExpression" do
8
+ tree = AdditiveExpression.new("1 + 2", 0, [
9
+ IntegerLiteral.new("1", 0),
10
+ AdditionOperator.new("+", 2),
11
+ IntegerLiteral.new("2", 4)
12
+ ])
13
+ bytecode = tree.compile
14
+ assert_equal [
15
+ PUSH_INT, 1,
16
+ PUSH_INT, 2,
17
+ ADD
18
+ ], bytecode
19
+ end
20
+
21
+ end
@@ -0,0 +1,21 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'test_helper.rb'))
2
+
3
+ class ComparativeExpressionTest < Test::Unit::TestCase
4
+
5
+ include KoiReferenceCompiler
6
+
7
+ test "should compile ComparativeExpression" do
8
+ tree = ComparativeExpression.new("1 == 2", 0, [
9
+ IntegerLiteral.new("1", 0),
10
+ EqualityOperator.new("==", 2),
11
+ IntegerLiteral.new("2", 5)
12
+ ])
13
+ bytecode = tree.compile
14
+ assert_equal [
15
+ PUSH_INT, 1,
16
+ PUSH_INT, 2,
17
+ EQUAL
18
+ ], bytecode
19
+ end
20
+
21
+ end
@@ -0,0 +1,17 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'test_helper.rb'))
2
+
3
+ class ExpressionTest < Test::Unit::TestCase
4
+
5
+ include KoiReferenceCompiler
6
+
7
+ test "should compile Expression" do
8
+ tree = Expression.new("1", 0, [
9
+ IntegerLiteral.new("1", 0)
10
+ ])
11
+ bytecode = tree.compile
12
+ assert_equal [
13
+ PUSH_INT, 1
14
+ ], bytecode
15
+ end
16
+
17
+ end
@@ -0,0 +1,21 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'test_helper.rb'))
2
+
3
+ class MultitiveExpressionTest < Test::Unit::TestCase
4
+
5
+ include KoiReferenceCompiler
6
+
7
+ test "should compile MultitiveExpression" do
8
+ tree = ComparativeExpression.new("1 * 2", 0, [
9
+ IntegerLiteral.new("1", 0),
10
+ MultiplicationOperator.new("*", 2),
11
+ IntegerLiteral.new("2", 4)
12
+ ])
13
+ bytecode = tree.compile
14
+ assert_equal [
15
+ PUSH_INT, 1,
16
+ PUSH_INT, 2,
17
+ MULTIPLY
18
+ ], bytecode
19
+ end
20
+
21
+ end
@@ -0,0 +1,296 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'test_helper.rb'))
2
+
3
+ class FunctionCallTest < Test::Unit::TestCase
4
+
5
+ include KoiReferenceCompiler
6
+
7
+ ##################
8
+ # call()
9
+
10
+ test "should compile FunctionCall for call() built-in" do
11
+ tree = FunctionCall.new("call( test, 1 )", 0, [
12
+ Identifier.new("call", 0),
13
+ Expression.new("test", 6, [
14
+ Identifier.new("test", 6)
15
+ ]),
16
+ Expression.new("1", 12, [
17
+ IntegerLiteral.new("1", 12)
18
+ ])
19
+ ])
20
+ bytecode = tree.compile
21
+ assert_equal [
22
+ PUSH_INT, 1,
23
+ GET_LOCAL, :test,
24
+ CALL
25
+ ], bytecode
26
+ end
27
+
28
+ test "should raise CompileError if call() is passed only 1 argument" do
29
+ assert_raises CompileError do
30
+ tree = FunctionCall.new("call( test )", 0, [
31
+ Identifier.new("call", 0),
32
+ Expression.new("test", 6, [
33
+ Identifier.new("test", 6)
34
+ ])
35
+ ])
36
+ tree.compile
37
+ end
38
+ end
39
+
40
+ test "should raise CompileError if call() is not passed any arguments" do
41
+ assert_raises CompileError do
42
+ tree = FunctionCall.new("call()", 0, [
43
+ Identifier.new("call", 0)
44
+ ])
45
+ tree.compile
46
+ end
47
+ end
48
+
49
+ ##################
50
+ # print()
51
+
52
+ test "should compile FunctionCall for print() built-in" do
53
+ tree = FunctionCall.new("print( test )", 0, [
54
+ Identifier.new("print", 0),
55
+ Expression.new("test", 7, [
56
+ Identifier.new("test", 7)
57
+ ])
58
+ ])
59
+ bytecode = tree.compile
60
+ assert_equal [
61
+ GET_LOCAL, :test,
62
+ PRINT
63
+ ], bytecode
64
+ end
65
+
66
+ test "should raise CompileError if print() is not passed any arguments" do
67
+ assert_raises CompileError do
68
+ tree = FunctionCall.new("print()", 0, [
69
+ Identifier.new("print", 0)
70
+ ])
71
+ tree.compile
72
+ end
73
+ end
74
+
75
+ test "should raise CompileError if print() is passed 2 arguments" do
76
+ assert_raises CompileError do
77
+ tree = FunctionCall.new("print( test, 1 )", 0, [
78
+ Identifier.new("print", 0),
79
+ Expression.new("test", 7, [
80
+ Identifier.new("test", 7)
81
+ ]),
82
+ Expression.new("1", 13, [
83
+ IntegerLiteral.new("1", 13)
84
+ ])
85
+ ])
86
+ tree.compile
87
+ end
88
+ end
89
+
90
+ ##################
91
+ # gets()
92
+
93
+ test "should compile FunctionCall for gets() built-in" do
94
+ tree = FunctionCall.new("gets()", 0, [
95
+ Identifier.new("gets", 0)
96
+ ])
97
+ bytecode = tree.compile
98
+ assert_equal [
99
+ GETS
100
+ ], bytecode
101
+ end
102
+
103
+ test "should raise CompileError if gets() is passed 1 argument" do
104
+ assert_raises CompileError do
105
+ tree = FunctionCall.new("gets( test )", 0, [
106
+ Identifier.new("gets", 0),
107
+ Expression.new("test", 6, [
108
+ Identifier.new("test", 6)
109
+ ])
110
+ ])
111
+ tree.compile
112
+ end
113
+ end
114
+
115
+ test "should raise CompileError if gets() is passed 2 arguments" do
116
+ assert_raises CompileError do
117
+ tree = FunctionCall.new("gets( test, 1 )", 0, [
118
+ Identifier.new("gets", 0),
119
+ Expression.new("test", 7, [
120
+ Identifier.new("test", 7)
121
+ ]),
122
+ Expression.new("1", 13, [
123
+ IntegerLiteral.new("1", 13)
124
+ ])
125
+ ])
126
+ tree.compile
127
+ end
128
+ end
129
+
130
+ ##################
131
+ # tailcall()
132
+
133
+ test "should compile FunctionCall for tailcall() built-in" do
134
+ tree = FunctionCall.new("tailcall( test, 1 )", 0, [
135
+ Identifier.new("tailcall", 0),
136
+ Expression.new("test", 10, [
137
+ Identifier.new("test", 10)
138
+ ]),
139
+ Expression.new("1", 16, [
140
+ IntegerLiteral.new("1", 16)
141
+ ])
142
+ ])
143
+ bytecode = tree.compile
144
+ assert_equal [
145
+ PUSH_INT, 1,
146
+ GET_LOCAL, :test,
147
+ TAILCALL
148
+ ], bytecode
149
+ end
150
+
151
+ test "should raise CompileError if tailcall() is not passed any arguments" do
152
+ assert_raises CompileError do
153
+ tree = FunctionCall.new("tailcall()", 0, [
154
+ Identifier.new("tailcall", 0)
155
+ ])
156
+ tree.compile
157
+ end
158
+ end
159
+
160
+ ##################
161
+ # return()
162
+
163
+ test "should compile FunctionCall for return() built-in" do
164
+ tree = FunctionCall.new("return( test )", 0, [
165
+ Identifier.new("return", 0),
166
+ Expression.new("test", 8, [
167
+ Identifier.new("test", 8)
168
+ ])
169
+ ])
170
+ bytecode = tree.compile
171
+ assert_equal [
172
+ GET_LOCAL, :test,
173
+ RETURN
174
+ ], bytecode
175
+ end
176
+
177
+ test "should compile FunctionCall for return() built-in with no arguments" do
178
+ tree = FunctionCall.new("return()", 0, [
179
+ Identifier.new("return", 0)
180
+ ])
181
+ bytecode = tree.compile
182
+ assert_equal [
183
+ RETURN
184
+ ], bytecode
185
+ end
186
+
187
+ test "should raise CompileError if return() is passed 2 arguments" do
188
+ assert_raises CompileError do
189
+ tree = FunctionCall.new("return( test, 1 )", 0, [
190
+ Identifier.new("return", 0),
191
+ Expression.new("test", 7, [
192
+ Identifier.new("test", 7)
193
+ ]),
194
+ Expression.new("1", 13, [
195
+ IntegerLiteral.new("1", 13)
196
+ ])
197
+ ])
198
+ tree.compile
199
+ end
200
+ end
201
+
202
+ ##################
203
+ # to_string()
204
+
205
+ test "should compile FunctionCall for to_string() built-in" do
206
+ tree = FunctionCall.new("to_string( test )", 0, [
207
+ Identifier.new("to_string", 0),
208
+ Expression.new("test", 11, [
209
+ Identifier.new("test", 11)
210
+ ])
211
+ ])
212
+ bytecode = tree.compile
213
+ assert_equal [
214
+ GET_LOCAL, :test,
215
+ TO_STRING
216
+ ], bytecode
217
+ end
218
+
219
+ test "should raise CompileError if to_string() is not passed any arguments" do
220
+ assert_raises CompileError do
221
+ tree = FunctionCall.new("to_string()", 0, [
222
+ Identifier.new("to_string", 0)
223
+ ])
224
+ tree.compile
225
+ end
226
+ end
227
+
228
+ test "should raise CompileError if to_string() is passed 2 arguments" do
229
+ assert_raises CompileError do
230
+ tree = FunctionCall.new("to_string( test, 1 )", 0, [
231
+ Identifier.new("to_string", 0),
232
+ Expression.new("test", 7, [
233
+ Identifier.new("test", 7)
234
+ ]),
235
+ Expression.new("1", 13, [
236
+ IntegerLiteral.new("1", 13)
237
+ ])
238
+ ])
239
+ tree.compile
240
+ end
241
+ end
242
+
243
+ ##################
244
+ # type_of()
245
+
246
+ test "should compile FunctionCall for type_of() built-in" do
247
+ tree = FunctionCall.new("type_of( test )", 0, [
248
+ Identifier.new("type_of", 0),
249
+ Expression.new("test", 9, [
250
+ Identifier.new("test", 9)
251
+ ])
252
+ ])
253
+ bytecode = tree.compile
254
+ assert_equal [
255
+ GET_LOCAL, :test,
256
+ TYPEOF
257
+ ], bytecode
258
+ end
259
+
260
+ test "should raise CompileError if type_of() is not passed any arguments" do
261
+ assert_raises CompileError do
262
+ tree = FunctionCall.new("type_of()", 0, [
263
+ Identifier.new("type_of", 0)
264
+ ])
265
+ tree.compile
266
+ end
267
+ end
268
+
269
+ test "should raise CompileError if type_of() is passed 2 arguments" do
270
+ assert_raises CompileError do
271
+ tree = FunctionCall.new("type_of( test, 1 )", 0, [
272
+ Identifier.new("type_of", 0),
273
+ Expression.new("test", 7, [
274
+ Identifier.new("test", 7)
275
+ ]),
276
+ Expression.new("1", 13, [
277
+ IntegerLiteral.new("1", 13)
278
+ ])
279
+ ])
280
+ tree.compile
281
+ end
282
+ end
283
+
284
+ ##################
285
+ # unknown!
286
+
287
+ test "should raise CompileError if function name is not defined" do
288
+ assert_raises CompileError do
289
+ tree = FunctionCall.new("fooey()", 0, [
290
+ Identifier.new("fooey", 0)
291
+ ])
292
+ tree.compile
293
+ end
294
+ end
295
+
296
+ end