koi-reference-compiler 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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