mirah 0.0.4-java

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 (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