mirah 0.0.4-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (141) hide show
  1. data/History.txt +15 -0
  2. data/README.txt +51 -0
  3. data/Rakefile +86 -0
  4. data/bin/duby +10 -0
  5. data/bin/dubyc +10 -0
  6. data/bin/dubyp +10 -0
  7. data/bin/jrubyp +36 -0
  8. data/bin/mirah +9 -0
  9. data/bin/mirah.cmd +1 -0
  10. data/bin/mirahc +9 -0
  11. data/bin/mirahc.cmd +1 -0
  12. data/bin/mirahp +9 -0
  13. data/bin/mirahp.cmd +1 -0
  14. data/examples/ant/example-build.xml +7 -0
  15. data/examples/appengine/Rakefile +19 -0
  16. data/examples/appengine/Readme +29 -0
  17. data/examples/appengine/src/org/mirah/MirahApp.mirah +57 -0
  18. data/examples/appengine/src/org/mirah/list.dhtml +15 -0
  19. data/examples/appengine/war/WEB-INF/lib/dubydatastore.jar +0 -0
  20. data/examples/bintrees.mirah +66 -0
  21. data/examples/construction.mirah +8 -0
  22. data/examples/dynamic.mirah +17 -0
  23. data/examples/edb.mirah +3 -0
  24. data/examples/fib.mirah +16 -0
  25. data/examples/fields.mirah +22 -0
  26. data/examples/fractal.mirah +55 -0
  27. data/examples/java_thing.mirah +13 -0
  28. data/examples/plugins/appengine/Rakefile +55 -0
  29. data/examples/plugins/appengine/lib/com/google/appengine/ext/duby/db/datastore.rb +375 -0
  30. data/examples/plugins/appengine/src/com/google/appengine/ext/duby/db/Model.duby +336 -0
  31. data/examples/plugins/appengine/test/com/google/appengine/ext/duby/db/ModelTest.duby +113 -0
  32. data/examples/simple_class.mirah +12 -0
  33. data/examples/sort_closure.mirah +7 -0
  34. data/examples/swing.mirah +20 -0
  35. data/examples/tak.mirah +15 -0
  36. data/examples/test.edb +9 -0
  37. data/examples/wiki/Rakefile +18 -0
  38. data/examples/wiki/src/org/mirah/wiki/MirahWiki.duby +324 -0
  39. data/examples/wiki/src/org/mirah/wiki/edit.eduby.html +42 -0
  40. data/examples/wiki/src/org/mirah/wiki/error.eduby.html +2 -0
  41. data/examples/wiki/src/org/mirah/wiki/layout.eduby.html +69 -0
  42. data/examples/wiki/src/org/mirah/wiki/parser.eduby.html +7 -0
  43. data/examples/wiki/src/org/mirah/wiki/view.eduby.html +15 -0
  44. data/examples/wiki/war/WEB-INF/classes/test/HeredocContext.class +0 -0
  45. data/examples/wiki/war/WEB-INF/classes/test/MirahParser.class +0 -0
  46. data/examples/wiki/war/WEB-INF/lib/appengine-api.jar +0 -0
  47. data/examples/wiki/war/WEB-INF/lib/dubydatastore.jar +0 -0
  48. data/examples/wiki/war/WEB-INF/lib/jmeta-runtime.jar +0 -0
  49. data/examples/wiki/war/WEB-INF/lib/pegdown-stubs.jar +0 -0
  50. data/examples/wiki/war/WEB-INF/pegdown.jar +0 -0
  51. data/examples/wiki/war/app.yaml +21 -0
  52. data/examples/wiki/war/public/favicon.ico +0 -0
  53. data/examples/wiki/war/public/images/appengine_duby.png +0 -0
  54. data/examples/wiki/war/public/images/back.gif +0 -0
  55. data/examples/wiki/war/public/images/dir.gif +0 -0
  56. data/examples/wiki/war/public/images/file.gif +0 -0
  57. data/examples/wiki/war/public/javascripts/prettify.js +61 -0
  58. data/examples/wiki/war/public/robots.txt +0 -0
  59. data/examples/wiki/war/public/stylesheets/main.css +156 -0
  60. data/examples/wiki/war/public/stylesheets/prettify.css +1 -0
  61. data/examples/wiki/war/public/stylesheets/sh_style.css +66 -0
  62. data/examples/wiki/war/public/stylesheets/source.css +21 -0
  63. data/examples/wiki/war/public/wmd/images/bg-fill.png +0 -0
  64. data/examples/wiki/war/public/wmd/images/bg.png +0 -0
  65. data/examples/wiki/war/public/wmd/images/blockquote.png +0 -0
  66. data/examples/wiki/war/public/wmd/images/bold.png +0 -0
  67. data/examples/wiki/war/public/wmd/images/code.png +0 -0
  68. data/examples/wiki/war/public/wmd/images/h1.png +0 -0
  69. data/examples/wiki/war/public/wmd/images/hr.png +0 -0
  70. data/examples/wiki/war/public/wmd/images/img.png +0 -0
  71. data/examples/wiki/war/public/wmd/images/italic.png +0 -0
  72. data/examples/wiki/war/public/wmd/images/link.png +0 -0
  73. data/examples/wiki/war/public/wmd/images/ol.png +0 -0
  74. data/examples/wiki/war/public/wmd/images/redo.png +0 -0
  75. data/examples/wiki/war/public/wmd/images/separator.png +0 -0
  76. data/examples/wiki/war/public/wmd/images/ul.png +0 -0
  77. data/examples/wiki/war/public/wmd/images/undo.png +0 -0
  78. data/examples/wiki/war/public/wmd/images/wmd-on.png +0 -0
  79. data/examples/wiki/war/public/wmd/images/wmd.png +0 -0
  80. data/examples/wiki/war/public/wmd/showdown.js +421 -0
  81. data/examples/wiki/war/public/wmd/wmd-base.js +1799 -0
  82. data/examples/wiki/war/public/wmd/wmd-plus.js +311 -0
  83. data/examples/wiki/war/public/wmd/wmd.js +73 -0
  84. data/javalib/JRubyParser.jar +0 -0
  85. data/javalib/dynalang-invoke-0.1.jar +0 -0
  86. data/javalib/mirah-bootstrap.jar +0 -0
  87. data/javalib/mirah-parser.jar +0 -0
  88. data/lib/duby.rb +2 -0
  89. data/lib/mirah.rb +338 -0
  90. data/lib/mirah/appengine_tasks.rb +146 -0
  91. data/lib/mirah/ast.rb +615 -0
  92. data/lib/mirah/ast/call.rb +307 -0
  93. data/lib/mirah/ast/class.rb +311 -0
  94. data/lib/mirah/ast/flow.rb +364 -0
  95. data/lib/mirah/ast/intrinsics.rb +470 -0
  96. data/lib/mirah/ast/literal.rb +154 -0
  97. data/lib/mirah/ast/local.rb +89 -0
  98. data/lib/mirah/ast/method.rb +360 -0
  99. data/lib/mirah/ast/scope.rb +208 -0
  100. data/lib/mirah/ast/structure.rb +226 -0
  101. data/lib/mirah/ast/type.rb +130 -0
  102. data/lib/mirah/compiler.rb +341 -0
  103. data/lib/mirah/env.rb +33 -0
  104. data/lib/mirah/jvm/base.rb +258 -0
  105. data/lib/mirah/jvm/compiler.rb +885 -0
  106. data/lib/mirah/jvm/method_lookup.rb +203 -0
  107. data/lib/mirah/jvm/source_compiler.rb +737 -0
  108. data/lib/mirah/jvm/source_generator/builder.rb +444 -0
  109. data/lib/mirah/jvm/source_generator/loops.rb +110 -0
  110. data/lib/mirah/jvm/source_generator/precompile.rb +188 -0
  111. data/lib/mirah/jvm/source_generator/typer.rb +11 -0
  112. data/lib/mirah/jvm/typer.rb +151 -0
  113. data/lib/mirah/jvm/types.rb +416 -0
  114. data/lib/mirah/jvm/types/basic_types.rb +33 -0
  115. data/lib/mirah/jvm/types/boolean.rb +17 -0
  116. data/lib/mirah/jvm/types/enumerable.rb +65 -0
  117. data/lib/mirah/jvm/types/extensions.rb +86 -0
  118. data/lib/mirah/jvm/types/factory.rb +186 -0
  119. data/lib/mirah/jvm/types/floats.rb +86 -0
  120. data/lib/mirah/jvm/types/integers.rb +171 -0
  121. data/lib/mirah/jvm/types/intrinsics.rb +376 -0
  122. data/lib/mirah/jvm/types/literals.rb +74 -0
  123. data/lib/mirah/jvm/types/methods.rb +614 -0
  124. data/lib/mirah/jvm/types/number.rb +143 -0
  125. data/lib/mirah/nbcompiler.rb +29 -0
  126. data/lib/mirah/plugin/edb.rb +29 -0
  127. data/lib/mirah/plugin/gwt.rb +173 -0
  128. data/lib/mirah/plugin/java.rb +55 -0
  129. data/lib/mirah/transform.rb +266 -0
  130. data/lib/mirah/transform2.rb +728 -0
  131. data/lib/mirah/typer.rb +407 -0
  132. data/lib/mirah_task.rb +107 -0
  133. data/test/test_ast.rb +359 -0
  134. data/test/test_compilation.rb +112 -0
  135. data/test/test_env.rb +42 -0
  136. data/test/test_gwt.rb +58 -0
  137. data/test/test_java_typer.rb +183 -0
  138. data/test/test_javac_compiler.rb +63 -0
  139. data/test/test_jvm_compiler.rb +2607 -0
  140. data/test/test_typer.rb +221 -0
  141. metadata +235 -0
@@ -0,0 +1,728 @@
1
+ module Duby::AST
2
+ class TransformHelper
3
+ java_import 'jmeta.Ast'
4
+ def initialize(transformer)
5
+ @mirah = transformer
6
+ end
7
+
8
+ def position(node)
9
+ @mirah.position(node)
10
+ end
11
+
12
+ def transformer
13
+ @mirah
14
+ end
15
+
16
+ def transform(node, parent)
17
+ @mirah.transform(node, parent)
18
+ end
19
+
20
+ def transform_script(node, parent)
21
+ Script.new(parent, position(node)) do |script|
22
+ script.filename = transformer.filename
23
+ [@mirah.transform(node.children[0], script)]
24
+ end
25
+ end
26
+
27
+ def transform_fixnum(node, parent)
28
+ Duby::AST::fixnum(parent, position(node), node[1])
29
+ end
30
+
31
+ def transform_float(node, parent)
32
+ Duby::AST::float(parent, position(node), node[1])
33
+ end
34
+
35
+ def transform_true(node, parent)
36
+ Boolean.new(parent, position(node), true)
37
+ end
38
+
39
+ def transform_false(node, parent)
40
+ Boolean.new(parent, position(node), false)
41
+ end
42
+
43
+ def transform_nil(node, parent)
44
+ Null.new(parent, position(node))
45
+ end
46
+
47
+ def transform_self(node, parent)
48
+ Self.new(parent, position(node))
49
+ end
50
+
51
+ def transform_string(node, parent)
52
+ String.new(parent, position(node), node[1])
53
+ end
54
+
55
+ def transform_symbol(node, parent)
56
+ String.new(parent, position(node), node[1])
57
+ end
58
+
59
+ def transform_body(node, parent)
60
+ Body.new(parent, position(node)) do |body|
61
+ node.children.map {|child| @mirah.transform(child, body)}
62
+ end
63
+ end
64
+
65
+ def transform_begin(node, parent)
66
+ @mirah.transform(node[1], parent)
67
+ end
68
+
69
+ def transform_break(node, parent)
70
+ Break.new(parent, position(node))
71
+ end
72
+
73
+ def transform_arguments(node, parent)
74
+ Arguments.new(parent, position(node)) do |args_node|
75
+ node.children.map do |child|
76
+ if child.nil?
77
+ nil
78
+ elsif child.kind_of?(Ast)
79
+ @mirah.transform(child, args_node)
80
+ else
81
+ child.map {|x| @mirah.transform(x, args_node)}
82
+ end
83
+ end
84
+ end
85
+ end
86
+
87
+ def transform_required_argument(node, parent)
88
+ name = node[1]
89
+ name = transform(name, nil) unless name.kind_of?(::String)
90
+ type = node[2]
91
+ type_node = transform(type, parent) if type
92
+ RequiredArgument.new(parent, position(node), name, type_node)
93
+ end
94
+
95
+ def transform_opt_arg(node, parent)
96
+ name = node[1]
97
+ name = transform(name, nil) unless name.kind_of?(::String)
98
+ type = node[2]
99
+ value = node[3]
100
+ OptionalArgument.new(parent, position(node), name) do |optarg|
101
+ [
102
+ type ? transform(type, optarg) : nil,
103
+ transform(value, optarg),
104
+ ]
105
+ end
106
+ end
107
+
108
+ def transform_rest_arg(node, parent)
109
+ name = node[1]
110
+ name = transform(name, nil) unless name.kind_of?(::String)
111
+ type = node[2]
112
+ RestArgument.new(parent, position(node), name) do |restarg|
113
+ [type ? transform(type, restarg) : nil]
114
+ end
115
+ end
116
+
117
+ def transform_block_arg(node, parent)
118
+ name = node[1]
119
+ name = transform(name, nil) unless name.kind_of?(::String)
120
+ type = node[2]
121
+ BlockArgument.new(parent, position(node), name) do |blkarg|
122
+ [type ? transform(type, blkarg) : nil]
123
+ end
124
+ end
125
+
126
+ def transform_opt_block_arg(node, parent)
127
+ block_arg = transform_block_arg(node, parent)
128
+ block_arg.optional = true
129
+ return block_arg
130
+ end
131
+
132
+ # TODO UnnamedRestArg
133
+
134
+ def transform_sclass(node, parent)
135
+ ClassAppendSelf.new(parent, position(node)) do |class_append_self|
136
+ raise "Singleton class not supported" unless node[1][0] == 'Self'
137
+
138
+ [transformer.transform(node[2], class_append_self)]
139
+ end
140
+ end
141
+
142
+ def transform_array(node, parent)
143
+ Array.new(parent, position(node)) do |array|
144
+ node.children.map {|child| transformer.transform(child, array)}
145
+ end
146
+ end
147
+
148
+ def transform_attr_assign(node, parent)
149
+ name = node[1]
150
+ target = node[2]
151
+ args = node[3] + [node[4]]
152
+ position = position(node)
153
+ case name
154
+ when '[]='
155
+ Call.new(parent, position, name) do |call|
156
+ [
157
+ transformer.transform(target, call),
158
+ args.map {|arg| transformer.transform(arg, call)},
159
+ nil
160
+ ]
161
+ end
162
+ else
163
+ new_name = name[0..-2] + '_set'
164
+ Call.new(parent, position, new_name) do |call|
165
+ [
166
+ transformer.transform(target, call),
167
+ args.map {|arg| transformer.transform(arg, call)},
168
+ nil
169
+ ]
170
+ end
171
+ end
172
+ end
173
+
174
+ def transform_class(node, parent)
175
+ cpath = node[1]
176
+ body_node = node[2]
177
+ super_node = node[3]
178
+ if cpath[0] == 'Constant'
179
+ name = cpath[1]
180
+ elsif cpath[0] == 'Unquote'
181
+ name = cpath
182
+ else
183
+ raise "Unsupported class name #{cpath[0]}"
184
+ end
185
+ name = transform(name, nil) unless name.kind_of?(::String)
186
+ ClassDefinition.new(parent, position(node),
187
+ name,
188
+ transformer.annotations) do |class_def|
189
+ [
190
+ super_node ? transform(super_node, class_def) : nil,
191
+ body_node ? transform(body_node, class_def) : nil
192
+ ]
193
+ end
194
+ end
195
+
196
+ def transform_def(node, parent)
197
+ name, args_node, type_node, body_node = node[1], node[2], node[3], node[4]
198
+ name = transform(name, nil) unless name.kind_of?(::String)
199
+ position = position(node)
200
+ actual_name = name
201
+ if name =~ /=$/
202
+ actual_name = name[0..-2] + '_set'
203
+ end
204
+ if name == 'initialize'
205
+ klass = ConstructorDefinition
206
+ else
207
+ klass = MethodDefinition
208
+ end
209
+ klass.new(parent,
210
+ position,
211
+ actual_name,
212
+ transformer.annotations) do |defn|
213
+ defn.signature = signature = {:return => nil}
214
+ defn.return_type = transform(type_node, defn) if type_node
215
+ [
216
+ signature,
217
+ args_node ? transformer.transform(args_node, defn) : nil,
218
+ body_node ? transformer.transform(body_node, defn) : nil,
219
+ ]
220
+ end
221
+ end
222
+
223
+ def transform_def_static(node, parent)
224
+ name, args_node, type_node, body_node = node[1], node[2], node[3], node[4]
225
+ name = transform(name, nil) unless name.kind_of?(::String)
226
+ position = position(node)
227
+ actual_name = name
228
+ if name =~ /=$/
229
+ actual_name = name[0..-2] + '_set'
230
+ end
231
+ StaticMethodDefinition.new(parent,
232
+ position,
233
+ actual_name,
234
+ transformer.annotations) do |defn|
235
+ defn.signature = signature = {:return => nil}
236
+ defn.return_type = transform(type_node, defn) if type_node
237
+ [
238
+ signature,
239
+ args_node ? transformer.transform(args_node, defn) : nil,
240
+ body_node ? transformer.transform(body_node, defn) : nil,
241
+ ]
242
+ end
243
+ end
244
+
245
+ def transform_fcall(node, parent)
246
+ if node.respond_to?(:declaration?) && node.declaration?
247
+ return Noop.new(parent, position(node))
248
+ end
249
+
250
+ name = node[1]
251
+ name = transform(name, nil) unless name.kind_of?(::String)
252
+ args = node[2]
253
+ iter_node = node[3]
254
+ fcall = FunctionalCall.new(parent, position(node), name) do |call|
255
+ [
256
+ args ? args.map {|arg| transformer.transform(arg, call)} : [],
257
+ iter_node ? transformer.transform(iter_node, call) : nil
258
+ ]
259
+ end
260
+ macro = Duby::AST.macro(name)
261
+ if macro
262
+ transformer.expand(fcall, parent, &macro)
263
+ else
264
+ fcall
265
+ end
266
+ end
267
+
268
+ def transform_call(node, parent)
269
+ name = node[1]
270
+ name = transform(name, nil) unless name.kind_of?(::String)
271
+ target = node[2]
272
+ args = node[3]
273
+ iter_node = node[4]
274
+ position = position(node)
275
+
276
+ actual_name = name
277
+ case actual_name
278
+ when '[]'
279
+ # could be array instantiation
280
+ case target[0]
281
+ when 'Identifier'
282
+ case target[1]
283
+ when 'boolean', 'byte', 'short', 'char', 'int', 'long', 'float', 'double'
284
+ if args.nil? || args.size == 0
285
+ constant = Constant.new(parent, position, target[1])
286
+ constant.array = true
287
+ return constant
288
+ elsif args && args.size == 1
289
+ return EmptyArray.new(parent, position) do |array|
290
+ [transform(target, array), transform(args[0], array)]
291
+ end
292
+ end
293
+ # TODO look for imported, lower case class names
294
+ end
295
+ when 'Constant'
296
+ if args.nil? || args.size == 0
297
+ constant = Constant.new(parent, position, target[1])
298
+ constant.array = true
299
+ return constant
300
+ elsif args && args.size == 1
301
+ return EmptyArray.new(parent, position) do |array|
302
+ [transform(target, array), transform(args[0], array)]
303
+ end
304
+ end
305
+ end
306
+ when /=$/
307
+ if name.size > 2 || name =~ /^\w/
308
+ actual_name = name[0..-2] + '_set'
309
+ end
310
+ end
311
+
312
+ Call.new(parent, position, actual_name) do |call|
313
+ [
314
+ transformer.transform(target, call),
315
+ args ? args.map {|arg| transformer.transform(arg, call)} : [],
316
+ iter_node ? transformer.transform(iter_node, call) : nil
317
+ ]
318
+ end
319
+ end
320
+
321
+ def transform_constant(node, parent)
322
+ Constant.new(parent, position(node), node[1])
323
+ end
324
+
325
+ def transform_identifier(node, parent)
326
+ name = node[1]
327
+ position = position(node)
328
+ if name == 'raise'
329
+ Raise.new(parent, position) do
330
+ []
331
+ end
332
+ elsif name == 'null'
333
+ Null.new(parent, position)
334
+ elsif ['public', 'private', 'protected'].include?(name)
335
+ AccessLevel.new(parent, position, name)
336
+ else
337
+ macro = Duby::AST.macro(name)
338
+ fcall = FunctionalCall.new(parent, position, name) do |call|
339
+ [
340
+ [],
341
+ nil
342
+ ]
343
+ end
344
+ if macro
345
+ transformer.expand(fcall, parent, &macro)
346
+ else
347
+ fcall
348
+ end
349
+ end
350
+ end
351
+
352
+ def transform_local_assign(node, parent)
353
+ name = node[1]
354
+ value_node = node[2]
355
+ position = position(node)
356
+ case value_node[0]
357
+ when 'Symbol', 'Constant'
358
+ LocalDeclaration.new(parent, position, name) {|local_decl| [transform(value_node, local_decl)]}
359
+ else
360
+ LocalAssignment.new(parent, position, name) {|local| [transform(value_node, local)]}
361
+ end
362
+ end
363
+
364
+ def transform_local(node, parent)
365
+ name = node[1]
366
+ Local.new(parent, position(node), name)
367
+ end
368
+
369
+ def transform_iter(node, parent)
370
+ args = node[1]
371
+ body = node[2]
372
+ Block.new(parent, position(node)) do |block|
373
+ [
374
+ args ? transformer.transform(args, block) : Arguments.new(block, position(node)),
375
+ body ? transformer.transform(body, block) : nil,
376
+ ]
377
+ end
378
+ end
379
+
380
+ def transform_inst_var(node, parent)
381
+ name = node[1]
382
+ name = transform(name, nil) unless name.kind_of?(::String)
383
+ Field.new(parent, position(node), name, transformer.annotations)
384
+ end
385
+
386
+ def transform_inst_var_assign(node, parent)
387
+ name = node[1]
388
+ name = transform(name, nil) unless name.kind_of?(::String)
389
+ value_node = node[2]
390
+ position = position(node)
391
+ case value_node[0]
392
+ when 'Symbol', 'Constant'
393
+ FieldDeclaration.new(parent, position,
394
+ name, transformer.annotations) do |field_decl|
395
+ [transform(value_node, field_decl)]
396
+ end
397
+ else
398
+ FieldAssignment.new(parent, position, name, transformer.annotations) {|field| [transformer.transform(value_node, field)]}
399
+ end
400
+ end
401
+
402
+ def transform_class_var(node, parent)
403
+ name = node[1]
404
+ name = transform(name, nil) unless name.kind_of?(::String)
405
+ Field.new(parent, position(node), name, transformer.annotations, true)
406
+ end
407
+
408
+ def transform_class_var_assign(node, parent)
409
+ name = node[1]
410
+ name = transform(name, nil) unless name.kind_of?(::String)
411
+ value_node = node[2]
412
+ position = position(node)
413
+ case value_node[0]
414
+ when 'Symbol', 'Constant'
415
+ FieldDeclaration.new(parent, position,
416
+ name, transformer.annotations, true) do |field_decl|
417
+ [transform(value_node, field_decl)]
418
+ end
419
+ else
420
+ FieldAssignment.new(parent, position, name, transformer.annotations, true) {|field| [transformer.transform(value_node, field)]}
421
+ end
422
+ end
423
+
424
+ def transform_if(node, parent)
425
+ condition = node[1]
426
+ then_body = node[2]
427
+ else_body = node[3]
428
+ If.new(parent, position(node)) do |iff|
429
+ [
430
+ Condition.new(iff, position(condition)) {|cond| [transformer.transform(condition, cond)]},
431
+ then_body ? transformer.transform(then_body, iff) : nil,
432
+ else_body ? transformer.transform(else_body, iff) : nil
433
+ ]
434
+ end
435
+ end
436
+
437
+ def transform_zsuper(node, parent)
438
+ Super.new(parent, position(node))
439
+ end
440
+
441
+ def transform_super(node, parent)
442
+ args = node[1]
443
+ iter = node[2]
444
+ Super.new(parent, position(node)) do |s|
445
+ [args ? args.map {|arg| transformer.transform(arg, s)} : []]
446
+ end
447
+ end
448
+
449
+ def transform_return(node, parent)
450
+ value_node = node[1] if node.size > 1
451
+ Return.new(parent, position(node)) do |ret|
452
+ [value_node ? transform(value_node, ret) : nil]
453
+ end
454
+ end
455
+
456
+ def transform_dstring(node, parent)
457
+ StringConcat.new(parent, position(node)) do |p|
458
+ node.children.map{|n| transform(n, p)}
459
+ end
460
+ end
461
+
462
+ def transform_ev_string(node, parent)
463
+ ToString.new(parent, position(node)) do |p|
464
+ [transform(node[1], p)]
465
+ end
466
+ end
467
+
468
+ def transform_and(node, parent)
469
+ first_node = node[1]
470
+ second_node = node[2]
471
+ If.new(parent, position(node)) do |iff|
472
+ [
473
+ Condition.new(iff, position(first_node)) {|cond| [transform(first_node, cond)]},
474
+ transform(second_node, iff),
475
+ nil
476
+ ]
477
+ end
478
+ end
479
+
480
+ def transform_or(node, parent)
481
+ first_node = node[1]
482
+ second_node = node[2]
483
+ Body.new(parent, position(node)) do |block|
484
+ temp = transformer.tmp
485
+ [
486
+ LocalAssignment.new(block, position(first_node), temp) do |l|
487
+ [transform(first_node, l)]
488
+ end,
489
+ If.new(parent, position(node)) do |iff|
490
+ [
491
+ Condition.new(iff, position(first_node)) do |cond|
492
+ [Local.new(cond, position(first_node), temp)]
493
+ end,
494
+ Local.new(iff, position(first_node), temp),
495
+ transform(second_node, iff)
496
+ ]
497
+ end
498
+ ]
499
+ end
500
+ end
501
+
502
+ def transform_next(node, parent)
503
+ Next.new(parent, position(node))
504
+ end
505
+
506
+ def transform_not(node, parent)
507
+ # TODO it's probably better to keep a not node
508
+ # and actually implement compiling it properly.
509
+ # Bonus points for optimizing branches that use Not's.
510
+ If.new(parent, position(node)) do |iff|
511
+ [
512
+ Condition.new(iff, position(node)) do |cond|
513
+ [ transform(node[1], cond) ]
514
+ end,
515
+ Boolean.new(iff, position(node), false),
516
+ Boolean.new(iff, position(node), true)
517
+ ]
518
+ end
519
+ end
520
+
521
+ def transform_redo(node, parent)
522
+ Redo.new(parent, position(node))
523
+ end
524
+
525
+ def transform_regex(node, parent)
526
+ contents = node[1]
527
+ modifiers = node[2]
528
+ if contents.size == 1 && contents[0][0] == 'String'
529
+ value = contents[0][1]
530
+ Regexp.new(parent, position(node), value)
531
+ else
532
+ raise "Unsupported regex #{node}"
533
+ end
534
+ end
535
+
536
+ def transform_ensure(node, parent)
537
+ Ensure.new(parent, position(node)) do |n|
538
+ node.children.map {|c| transform(c, n)}
539
+ end
540
+ end
541
+
542
+ def evaluate_at_start?(node)
543
+ if node[0] =~ /Mod$/ && node[2] && node[2][0] == 'Begin'
544
+ false
545
+ else
546
+ true
547
+ end
548
+ end
549
+
550
+ def transform_while(node, parent)
551
+ condition_node = node[1]
552
+ body_node = node[2]
553
+ Loop.new(parent, position(node), evaluate_at_start?(node), false) do |loop|
554
+ [
555
+ Condition.new(loop, position(condition_node)) {|cond| [transform(condition_node, cond)]},
556
+ transform(body_node, loop)
557
+ ]
558
+ end
559
+ end
560
+ def transform_while_mod(node, parent)
561
+ transform_while(node, parent)
562
+ end
563
+
564
+ def transform_until(node, parent)
565
+ condition_node = node[1]
566
+ body_node = node[2]
567
+ Loop.new(parent, position(node), evaluate_at_start?(node), true) do |loop|
568
+ [
569
+ Condition.new(loop, position(condition_node)) {|cond| [transform(condition_node, cond)]},
570
+ transform(body_node, loop)
571
+ ]
572
+ end
573
+ end
574
+ def transform_until_mod(node, parent)
575
+ transform_until(node, parent)
576
+ end
577
+
578
+ def transform_for(node, parent)
579
+ var_node = node[1]
580
+ body_node = node[2]
581
+ iter_node = node[3]
582
+ Call.new(parent, position(node), 'each') do |each|
583
+ [
584
+ transformer.transform(iter_node, each),
585
+ [],
586
+ Block.new(each, position(body_node)) do |block|
587
+ [
588
+ Arguments.new(block, position(var_node)) do |args|
589
+ [
590
+ # TODO support for multiple assignment?
591
+ [RequiredArgument.new(args,
592
+ position(var_node),
593
+ var_node[1])
594
+ ]
595
+ ]
596
+ end,
597
+ transformer.transform(body_node, block)
598
+ ]
599
+ end
600
+ ]
601
+ end
602
+ end
603
+
604
+ def transform_rescue(node, parent)
605
+ body_node = node[1]
606
+ clauses = node[2]
607
+ Rescue.new(parent, position(node)) do |node|
608
+ [
609
+ transformer.transform(body_node, node),
610
+ clauses.map {|clause| transformer.transform(clause, node)}
611
+ ]
612
+ end
613
+ end
614
+
615
+ def transform_rescue_clause(node, parent)
616
+ exceptions = node[1]
617
+ var_name = node[2]
618
+ name = transform(var_name, nil) unless var_name.nil? || var_name.kind_of?(::String)
619
+ body = node[3]
620
+ RescueClause.new(parent, position(node)) do |clause|
621
+ clause.name = var_name if var_name
622
+ [
623
+ if exceptions.size == 0
624
+ [String.new(clause, position(node), 'java.lang.Exception')]
625
+ else
626
+ exceptions.map {|name| Constant.new(clause, position(node), name)}
627
+ end,
628
+ body ? transformer.transform(body, clause) : Null.new(clause, position(node))
629
+ ]
630
+ end
631
+ end
632
+
633
+ def transform_hash(node, parent)
634
+ Call.new(parent, position(node), 'new_hash') do |call|
635
+ [
636
+ Builtin.new(call, position(node)),
637
+ [
638
+ Array.new(call, position(node)) do |array|
639
+ values = []
640
+ node.children.each do |assoc|
641
+ assoc.children.each do |child|
642
+ values << transform(child, array)
643
+ end
644
+ end
645
+ values
646
+ end
647
+ ]
648
+ ]
649
+ end
650
+ end
651
+
652
+ def transform_op_assign(node, parent)
653
+ target = node[1]
654
+ attribute = node[2]
655
+ op = node[3]
656
+ value = node[4]
657
+ temp = transformer.tmp
658
+ tempval = transformer.tmp
659
+ position = position(node)
660
+ setter = "#{attribute}="
661
+ getter = attribute
662
+ Body.new(parent, position) do |body|
663
+ [
664
+ LocalAssignment.new(body, position, temp) {|l| transform(target, l)},
665
+ LocalAssignment.new(body, position, tempval) do |l|
666
+ Call.new(l, position, op) do |op_call|
667
+ [
668
+ Call.new(op_call, position, getter) do |get_call|
669
+ [
670
+ Local.new(get_call, position, temp),
671
+ []
672
+ ]
673
+ end,
674
+ [transform(value, op_call)],
675
+ ]
676
+ end
677
+ end,
678
+ Call.new(body, position, setter) do |set_call|
679
+ [
680
+ Local.new(set_call, position, temp),
681
+ [ Local.new(set_call, position, tempval) ],
682
+ ]
683
+ end,
684
+ Local.new(body, position, tempval),
685
+ ]
686
+ end
687
+ end
688
+
689
+ def transform_unquote(node, parent)
690
+ Unquote.new(parent, position(node)) do |unquote|
691
+ [transform(node[1], unquote)]
692
+ end
693
+ end
694
+
695
+ def transform_unquote_assign(node, parent)
696
+ name, value = node[1], node[2]
697
+ UnquoteAssign.new(parent, position(node)) do |unquote|
698
+ [transform(name, unquote), transform(value, unquote)]
699
+ end
700
+ end
701
+
702
+ def transform_block_pass(node, parent)
703
+ BlockPass.new(parent, position(node)) do |blockpass|
704
+ [transform(node[1], blockpass)]
705
+ end
706
+ end
707
+
708
+ def transform_annotation(node, parent)
709
+ classname = node[1]
710
+ values = if node[2]
711
+ node[2].children
712
+ else
713
+ []
714
+ end
715
+ annotation = Annotation.new(parent, position(node)) do |anno|
716
+ [String.new(anno, position(node), classname)]
717
+ end
718
+ values.each do |assoc|
719
+ key = assoc[1]
720
+ value = assoc[2]
721
+ name = key[1]
722
+ annotation[name] = transform(value, annotation)
723
+ end
724
+ transformer.add_annotation(annotation)
725
+ return Noop.new(parent, position(node))
726
+ end
727
+ end
728
+ end