duby 0.0.2-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. data/History.txt +8 -0
  2. data/README.txt +39 -0
  3. data/Rakefile +13 -0
  4. data/bin/duby +9 -0
  5. data/bin/dubyc +9 -0
  6. data/bin/dubyp +9 -0
  7. data/examples/README +16 -0
  8. data/examples/appengine/Rakefile +72 -0
  9. data/examples/appengine/Readme +27 -0
  10. data/examples/appengine/config.ru +7 -0
  11. data/examples/appengine/lib/duby/plugin/datastore.rb +171 -0
  12. data/examples/appengine/src/com/google/appengine/ext/duby/db/Model.duby +132 -0
  13. data/examples/appengine/src/com/ribrdb/DubyApp.duby +28 -0
  14. data/examples/appengine/src/com/ribrdb/list.dhtml +15 -0
  15. data/examples/construction.duby +8 -0
  16. data/examples/edb.duby +3 -0
  17. data/examples/fib.duby +24 -0
  18. data/examples/fields.duby +22 -0
  19. data/examples/fractal.duby +57 -0
  20. data/examples/java_thing.duby +13 -0
  21. data/examples/simple_class.duby +12 -0
  22. data/examples/swing.duby +20 -0
  23. data/examples/tak.duby +15 -0
  24. data/examples/test.edb +9 -0
  25. data/javalib/JRubyParser.jar +0 -0
  26. data/lib/duby.rb +168 -0
  27. data/lib/duby/ast.rb +386 -0
  28. data/lib/duby/ast/call.rb +145 -0
  29. data/lib/duby/ast/class.rb +154 -0
  30. data/lib/duby/ast/flow.rb +332 -0
  31. data/lib/duby/ast/intrinsics.rb +56 -0
  32. data/lib/duby/ast/literal.rb +97 -0
  33. data/lib/duby/ast/local.rb +92 -0
  34. data/lib/duby/ast/method.rb +244 -0
  35. data/lib/duby/ast/structure.rb +62 -0
  36. data/lib/duby/ast/type.rb +93 -0
  37. data/lib/duby/c/compiler.rb +134 -0
  38. data/lib/duby/compiler.rb +282 -0
  39. data/lib/duby/jvm/compiler.rb +766 -0
  40. data/lib/duby/jvm/method_lookup.rb +193 -0
  41. data/lib/duby/jvm/source_compiler.rb +605 -0
  42. data/lib/duby/jvm/source_generator/builder.rb +387 -0
  43. data/lib/duby/jvm/source_generator/loops.rb +110 -0
  44. data/lib/duby/jvm/source_generator/precompile.rb +170 -0
  45. data/lib/duby/jvm/source_generator/typer.rb +11 -0
  46. data/lib/duby/jvm/typer.rb +131 -0
  47. data/lib/duby/jvm/types.rb +331 -0
  48. data/lib/duby/jvm/types/basic_types.rb +19 -0
  49. data/lib/duby/jvm/types/boolean.rb +11 -0
  50. data/lib/duby/jvm/types/enumerable.rb +63 -0
  51. data/lib/duby/jvm/types/factory.rb +155 -0
  52. data/lib/duby/jvm/types/floats.rb +70 -0
  53. data/lib/duby/jvm/types/integers.rb +110 -0
  54. data/lib/duby/jvm/types/intrinsics.rb +230 -0
  55. data/lib/duby/jvm/types/literals.rb +82 -0
  56. data/lib/duby/jvm/types/methods.rb +381 -0
  57. data/lib/duby/jvm/types/number.rb +92 -0
  58. data/lib/duby/nbcompiler.rb +29 -0
  59. data/lib/duby/old/compiler_old.rb +845 -0
  60. data/lib/duby/old/declaration.rb +72 -0
  61. data/lib/duby/old/mapper.rb +72 -0
  62. data/lib/duby/old/signature.rb +52 -0
  63. data/lib/duby/old/typer_old.rb +163 -0
  64. data/lib/duby/plugin/edb.rb +25 -0
  65. data/lib/duby/plugin/java.rb +42 -0
  66. data/lib/duby/plugin/math.rb +84 -0
  67. data/lib/duby/transform.rb +1028 -0
  68. data/lib/duby/typer.rb +369 -0
  69. data/test/TestUser.class +0 -0
  70. data/test/test_ast.rb +391 -0
  71. data/test/test_compilation.rb +98 -0
  72. data/test/test_java_typer.rb +199 -0
  73. data/test/test_javac_compiler.rb +58 -0
  74. data/test/test_jvm_compiler.rb +1770 -0
  75. data/test/test_math_plugin.rb +87 -0
  76. data/test/test_typer.rb +246 -0
  77. metadata +156 -0
@@ -0,0 +1,1028 @@
1
+ require 'jruby'
2
+
3
+ module Duby
4
+ module Transform
5
+ class Error < StandardError
6
+ attr_reader :position, :cause
7
+ def initialize(msg, position, cause=nil)
8
+ super(msg)
9
+ @position = position
10
+ @position = position.position if position.respond_to? :position
11
+ @cause = cause
12
+ end
13
+ end
14
+
15
+ class Transformer
16
+ attr_reader :errors
17
+ def initialize
18
+ @errors = []
19
+ @tmp_count = 0
20
+ @annotations = []
21
+ @scopes = []
22
+ end
23
+
24
+ def annotations
25
+ result, @annotations = @annotations, []
26
+ return result
27
+ end
28
+
29
+ def add_annotation(annotation)
30
+ @annotations << annotation
31
+ Duby::AST::Noop.new(annotation.parent, annotation.position)
32
+ end
33
+
34
+ def tmp
35
+ "__xform_tmp_#{@tmp_count += 1}"
36
+ end
37
+
38
+ def transform(node, parent)
39
+ begin
40
+ scope = node.getScope if node.respond_to? :getScope
41
+ if scope
42
+ @scopes << scope
43
+ end
44
+ begin
45
+ node.transform(self, parent)
46
+ ensure
47
+ if scope
48
+ @scopes.pop
49
+ end
50
+ end
51
+ rescue Error => ex
52
+ @errors << ex
53
+ Duby::AST::ErrorNode.new(parent, ex)
54
+ rescue Exception => ex
55
+ error = Error.new(ex.message, node.position, ex)
56
+ @errors << error
57
+ Duby::AST::ErrorNode.new(parent, error)
58
+ end
59
+ end
60
+
61
+ def captured?(node)
62
+ depth = node.depth
63
+ scope = @scopes[-1]
64
+ while depth > 0
65
+ depth -= 1
66
+ scope = scope.enclosing_scope
67
+ end
68
+ scope.isCaptured(node.index)
69
+ end
70
+
71
+ def eval(src, filename='-', parent=nil, *vars)
72
+ unless vars.empty?
73
+ src = "#{vars.join ','} = [];begin;#{src};end"
74
+ end
75
+ node = Duby::AST.parse_ruby(src, filename)
76
+ duby_node = transform(node, nil).body
77
+ unless vars.empty?
78
+ # We have
79
+ # (Script (Body ({vars} (NewlineNode (BeginNode ({src}))))))
80
+ duby_node = duby_node.children[1]
81
+ end
82
+ duby_node.parent = parent
83
+ duby_node
84
+ end
85
+
86
+ def expand(fvcall, parent)
87
+ result = yield self, fvcall, parent
88
+ unless result.kind_of?(AST::Node)
89
+ raise Error.new('Invalid macro result', fvcall.position)
90
+ end
91
+ result
92
+ end
93
+ end
94
+ end
95
+ TransformError = Transform::Error
96
+
97
+ module AST
98
+ begin
99
+ Parser = org.jrubyparser.Parser
100
+ rescue NameError
101
+ $CLASSPATH << File.dirname(__FILE__) + '/../../javalib/JRubyParser.jar'
102
+ Parser = org.jrubyparser.Parser
103
+ end
104
+ java_import org.jrubyparser.parser.ParserConfiguration
105
+ java_import org.jrubyparser.CompatVersion
106
+ java_import java.io.StringReader
107
+
108
+ def parse(src, filename='-', raise_errors=false, transformer=nil)
109
+ ast = parse_ruby(src, filename)
110
+ transformer ||= Transform::Transformer.new
111
+ ast = transformer.transform(ast, nil)
112
+ if raise_errors
113
+ transformer.errors.each do |e|
114
+ raise e.cause || e
115
+ end
116
+ end
117
+ ast
118
+ end
119
+ module_function :parse
120
+
121
+ def parse_ruby(src, filename='-')
122
+ raise ArgumentError if src.nil?
123
+ parser = Parser.new
124
+ config = ParserConfiguration.new(0, CompatVersion::RUBY1_9, true)
125
+ begin
126
+ parser.parse(filename, StringReader.new(src), config)
127
+ rescue => ex
128
+ if ex.cause.respond_to? :position
129
+ position = ex.cause.position
130
+ puts "#{position.file}:#{position.start_line + 1}: #{ex.message}"
131
+ end
132
+ raise ex
133
+ end
134
+ end
135
+ module_function :parse_ruby
136
+
137
+ JRubyAst = org.jrubyparser.ast
138
+
139
+ module CallOpAssignment
140
+ def call_op_assignment(transformer, parent, name, args)
141
+ set_args = JRubyAst::ListNode.new(position)
142
+ set_args.add_all(args)
143
+ set_args.add(value_node)
144
+
145
+ first = JRubyAst::CallNode.new(position, receiver_node, name, args)
146
+ second = JRubyAst::AttrAssignNode.new(position, receiver_node,
147
+ "#{name}=", set_args)
148
+
149
+ if operator_name == '||'
150
+ klass = JRubyAst::OrNode
151
+ elsif operator_name == '&&'
152
+ klass = JRubyAst::AndNode
153
+ else
154
+ raise "Unknown OpAsgn operator #{operator_name}"
155
+ end
156
+ transformer.transform(klass.new(position, first, second), parent)
157
+ end
158
+ end
159
+
160
+ # reload
161
+ module JRubyAst
162
+ class Node
163
+ def transform(transformer, parent)
164
+ # default behavior is to raise, to expose missing nodes
165
+ raise TransformError.new("Unsupported syntax: #{self}", position)
166
+ end
167
+
168
+ def [](ix)
169
+ self.child_nodes[ix]
170
+ end
171
+
172
+ def inspect(indent = 0)
173
+ s = ' '*indent + self.class.name.split('::').last
174
+
175
+ if self.respond_to?(:name)
176
+ s << " |#{self.name}|"
177
+ end
178
+ if self.respond_to?(:value)
179
+ s << " ==#{self.value.inspect}"
180
+ end
181
+
182
+ if self.respond_to?(:index)
183
+ s << " &#{self.index.inspect}"
184
+ end
185
+
186
+ if self.respond_to?(:depth)
187
+ s << " >#{self.depth.inspect}"
188
+ end
189
+
190
+ [:receiver_node, :args_node, :var_node, :head_node, :value_node, :iter_node, :body_node, :next_node, :condition, :then_body, :else_body].each do |mm|
191
+ if self.respond_to?(mm)
192
+ begin
193
+ s << "\n#{self.send(mm).inspect(indent+2)}" if self.send(mm)
194
+ rescue
195
+ s << "\n#{' '*(indent+2)}#{self.send(mm).inspect}" if self.send(mm)
196
+ end
197
+ end
198
+ end
199
+
200
+ if org::jruby::ast::ListNode === self
201
+ (0...self.size).each do |n|
202
+ begin
203
+ s << "\n#{self.get(n).inspect(indent+2)}" if self.get(n)
204
+ rescue
205
+ s << "\n#{' '*(indent+2)}#{self.get(n).inspect}" if self.get(n)
206
+ end
207
+ end
208
+ end
209
+ s
210
+ end
211
+
212
+ def signature(parent)
213
+ nil
214
+ end
215
+ end
216
+
217
+ class ListNode
218
+ include Enumerable
219
+
220
+ def each(&block)
221
+ child_nodes.each(&block)
222
+ end
223
+ end
224
+
225
+ class ArgsNode
226
+ def args
227
+ has_typed = optional &&
228
+ optional.child_nodes.all? {|n| n.kind_of? TypedArgumentNode}
229
+ if has_typed
230
+ optional
231
+ else
232
+ pre
233
+ end
234
+ end
235
+
236
+ def transform(transformer, parent)
237
+ Arguments.new(parent, position) do |args_node|
238
+ arg_list = args.child_nodes.map do |node|
239
+ if !node.respond_to?(:type_node) || node.type_node.respond_to?(:type_reference)
240
+ RequiredArgument.new(args_node, node.position, node.name)
241
+ else
242
+ OptionalArgument.new(args_node, node.position, node.name) {|opt_arg| [transformer.transform(node, opt_arg)]}
243
+ end
244
+ # argument nodes will have type soon
245
+ #RequiredArgument.new(args_node, node.name, node.type)
246
+ end if args
247
+
248
+ # TODO optional arguments.
249
+ opt_list = optional.child_nodes.map do |node|
250
+ OptionalArgument.new(args_node, node.position) {|opt_arg| [transformer.transform(node, opt_arg)]}
251
+ end if false && optional
252
+
253
+ rest_arg = RestArgument.new(args_node, rest.position, rest.name) if rest
254
+
255
+ block_arg = BlockArgument.new(args_node, block.position, block.name) if block
256
+
257
+ [arg_list, opt_list, rest_arg, block_arg]
258
+ end
259
+ end
260
+ end
261
+
262
+ class ArrayNode
263
+ def transform(transformer, parent)
264
+ Array.new(parent, position) do |array|
265
+ child_nodes.map {|child| transformer.transform(child, array)}
266
+ end
267
+ end
268
+ end
269
+
270
+ class AttrAssignNode
271
+ def transform(transformer, parent)
272
+ case name
273
+ when '[]='
274
+ Call.new(parent, position, name) do |call|
275
+ [
276
+ transformer.transform(receiver_node, call),
277
+ args_node ? args_node.child_nodes.map {|arg| transformer.transform(arg, call)} : [],
278
+ nil
279
+ ]
280
+ end
281
+ else
282
+ new_name = name[0..-2] + '_set'
283
+ Call.new(parent, position, new_name) do |call|
284
+ [
285
+ transformer.transform(receiver_node, call),
286
+ args_node ? args_node.child_nodes.map {|arg| transformer.transform(arg, call)} : [],
287
+ nil
288
+ ]
289
+ end
290
+ end
291
+ end
292
+ end
293
+
294
+ class BeginNode
295
+ def transform(transformer, parent)
296
+ transformer.transform(body_node, parent)
297
+ end
298
+ end
299
+
300
+ class BlockNode
301
+ def transform(transformer, parent)
302
+ Body.new(parent, position) do |body|
303
+ child_nodes.map {|child| transformer.transform(child, body)}
304
+ end
305
+ end
306
+ end
307
+
308
+ class BreakNode
309
+ def transform(transformer, parent)
310
+ # TODO support 'break value'?
311
+ Break.new(parent, position)
312
+ end
313
+ end
314
+
315
+ class ClassNode
316
+ def transform(transformer, parent)
317
+ ClassDefinition.new(parent, position,
318
+ cpath.name,
319
+ transformer.annotations) do |class_def|
320
+ [
321
+ super_node ? super_node.type_reference(class_def) : nil,
322
+ body_node ? transformer.transform(body_node, class_def) : nil
323
+ ]
324
+ end
325
+ end
326
+ end
327
+
328
+ class GlobalVarNode
329
+ def transform(transformer, parent)
330
+ classname = name[1..-1]
331
+ annotation = Annotation.new(parent, position, AST.type(classname))
332
+ transformer.add_annotation(annotation)
333
+ end
334
+ end
335
+
336
+ class CallNode
337
+ def transform(transformer, parent)
338
+ if annotation?
339
+ return transformer.add_annotation(annotation(transformer, parent))
340
+ end
341
+
342
+ actual_name = name
343
+ case actual_name
344
+ when '[]'
345
+ # could be array instantiation
346
+ case receiver_node
347
+ when VCallNode
348
+ case receiver_node.name
349
+ when 'boolean', 'byte', 'short', 'char', 'int', 'long', 'float', 'double'
350
+ return EmptyArray.new(parent, position, AST::type(receiver_node.name)) do |array|
351
+ transformer.transform(args_node.get(0), array)
352
+ end
353
+ # TODO look for imported, lower case class names
354
+ end
355
+ when ConstNode
356
+ return EmptyArray.new(parent, position, AST::type(receiver_node.name)) do |array|
357
+ transformer.transform(args_node.get(0), array)
358
+ end
359
+ end
360
+ when /=$/
361
+ if name.size > 2 || name =~ /^\w/
362
+ actual_name = name[0..-2] + '_set'
363
+ end
364
+ end
365
+
366
+ Call.new(parent, position, actual_name) do |call|
367
+ [
368
+ transformer.transform(receiver_node, call),
369
+ args_node ? args_node.child_nodes.map {|arg| transformer.transform(arg, call)} : [],
370
+ iter_node ? transformer.transform(iter_node, call) : nil
371
+ ]
372
+ end
373
+ end
374
+
375
+ def type_reference(parent)
376
+ if name == "[]"
377
+ # array type, top should be a constant; find the rest
378
+ array = true
379
+ elements = []
380
+ else
381
+ array = false
382
+ elements = [name]
383
+ end
384
+
385
+ receiver = receiver_node
386
+
387
+ loop do
388
+ case receiver
389
+ when ConstNode
390
+ elements << receiver_node.name
391
+ break
392
+ when CallNode
393
+ elements.unshift(receiver.name)
394
+ receiver = receiver.receiver_node
395
+ when SymbolNode
396
+ elements.unshift(receiver.name)
397
+ break
398
+ when VCallNode
399
+ elements.unshift(receiver.name)
400
+ break
401
+ when GlobalVarNode
402
+ elements.unshift(receiver.name[1..-1])
403
+ break
404
+ end
405
+ end
406
+
407
+ # join and load
408
+ class_name = elements.join(".")
409
+ AST::type(class_name, array)
410
+ end
411
+
412
+ def annotation(transformer, parent)
413
+ if name == '[]'
414
+ annotation = receiver_node.annotation(transformer, parent)
415
+ value = args_node[0]
416
+ case value
417
+ when HashNode
418
+ values = value.list_node
419
+ (0..(values.size / 2)).each do |i|
420
+ name = values.get(2 * i).name
421
+ value = values.get(2 * i + 1)
422
+ annotation[name] = transformer.transform(value, annotation)
423
+ end
424
+ when nil
425
+ # ignore an empty argument list
426
+ else
427
+ annotation['value'] = transformer.transform(value, annotation)
428
+ end
429
+ annotation
430
+ else
431
+ klass = type_reference(parent)
432
+ Annotation.new(parent, position, klass)
433
+ end
434
+ end
435
+
436
+ def annotation?
437
+ if name == '[]'
438
+ receiver = receiver_node
439
+ else
440
+ receiver = self
441
+ end
442
+ receiver = receiver.receiver_node while CallNode === receiver
443
+ GlobalVarNode === receiver
444
+ end
445
+ end
446
+
447
+ class Colon2Node
448
+ end
449
+
450
+ class ConstNode
451
+ def transform(transformer, parent)
452
+ Constant.new(parent, position, name)
453
+ end
454
+
455
+ def type_reference(parent)
456
+ AST::type(name, false, false)
457
+ end
458
+ end
459
+
460
+ class DefnNode
461
+ def transform(transformer, parent)
462
+ actual_name = name
463
+ if name =~ /=$/
464
+ actual_name = name[0..-2] + '_set'
465
+ end
466
+ if name == 'initialize'
467
+ klass = ConstructorDefinition
468
+ else
469
+ klass = MethodDefinition
470
+ end
471
+ klass.new(parent,
472
+ position,
473
+ actual_name,
474
+ transformer.annotations) do |defn|
475
+ signature = {:return => nil}
476
+
477
+ if args_node && args_node.args
478
+ args_node.args.child_nodes.each do |arg|
479
+ if arg.respond_to?(:type_node) && arg.type_node.respond_to?(:type_reference)
480
+ signature[arg.name.intern] =
481
+ arg.type_node.type_reference(parent)
482
+ end
483
+ end
484
+ end
485
+ if body_node
486
+ for node in body_node.child_nodes
487
+ sig = node.signature(defn)
488
+ break unless sig
489
+ signature.update(sig) if sig.kind_of? ::Hash
490
+ end
491
+ end
492
+ [
493
+ signature,
494
+ args_node ? transformer.transform(args_node, defn) : nil,
495
+ body_node ? transformer.transform(body_node, defn) : nil
496
+ ]
497
+ end
498
+ end
499
+ end
500
+
501
+ class DefsNode
502
+ def transform(transformer, parent)
503
+ actual_name = name
504
+ if name =~ /=$/
505
+ actual_name = name[0..-2] + '_set'
506
+ end
507
+ StaticMethodDefinition.new(parent,
508
+ position,
509
+ actual_name,
510
+ transformer.annotations) do |defn|
511
+ signature = {:return => nil}
512
+ if args_node && args_node.args
513
+ args_node.args.child_nodes.each do |arg|
514
+ if arg.respond_to? :type_node
515
+ signature[arg.name.intern] =
516
+ arg.type_node.type_reference(parent)
517
+ end
518
+ end
519
+ end
520
+ if body_node
521
+ for node in body_node.child_nodes
522
+ sig = node.signature(defn)
523
+ break unless sig
524
+ signature.update(sig) if sig.kind_of? ::Hash
525
+ end
526
+ end
527
+ [
528
+ signature,
529
+ args_node ? transformer.transform(args_node, defn) : nil,
530
+ body_node ? transformer.transform(body_node, defn) : nil
531
+ ]
532
+ end
533
+ end
534
+ end
535
+
536
+ class FalseNode
537
+ def transform(transformer, parent)
538
+ Boolean.new(parent, position, false)
539
+ end
540
+ end
541
+
542
+ class FCallNode
543
+ def signature(parent)
544
+ case name
545
+ when "returns"
546
+ @declaration = true
547
+ {:return => args_node.get(0).type_reference(parent)}
548
+ when "throws"
549
+ @declaration = true
550
+ exceptions = args_node.child_nodes.map do |node|
551
+ node.type_reference(parent)
552
+ end
553
+ {:throws => exceptions}
554
+ else
555
+ nil
556
+ end
557
+ end
558
+
559
+ def transform(transformer, parent)
560
+ @declaration ||= false
561
+
562
+ if @declaration
563
+ return Noop.new(parent, position)
564
+ end
565
+
566
+ macro = AST.macro(name)
567
+ if macro
568
+ transformer.expand(self, parent, &macro)
569
+ else
570
+ FunctionalCall.new(parent, position, name) do |call|
571
+ [
572
+ args_node ? args_node.child_nodes.map {|arg| transformer.transform(arg, call)} : [],
573
+ iter_node ? transformer.transform(iter_node, call) : nil
574
+ ]
575
+ end
576
+ end
577
+ end
578
+
579
+ def type_reference(parent)
580
+ AST::type(name)
581
+ end
582
+ end
583
+
584
+ class FixnumNode
585
+ def transform(transformer, parent)
586
+ AST::fixnum(parent, position, value)
587
+ end
588
+ end
589
+
590
+ class FloatNode
591
+ def transform(transformer, parent)
592
+ AST::float(parent, position, value)
593
+ end
594
+ end
595
+
596
+ class HashNode
597
+ def transform(transformer, parent)
598
+ @declaration ||= false
599
+
600
+ if @declaration
601
+ Noop.new(parent, position)
602
+ else
603
+ super
604
+ end
605
+ end
606
+
607
+ # Create a signature definition using a literal hash syntax
608
+ def signature(parent)
609
+ # flag this as a declaration, so it transforms to a noop
610
+ @declaration = true
611
+
612
+ arg_types = {:return => nil}
613
+
614
+ list = list_node.child_nodes.to_a
615
+ list.each_index do |index|
616
+ if index % 2 == 0
617
+ if SymbolNode === list[index] && list[index].name == 'return'
618
+ arg_types[:return] = list[index + 1].type_reference(parent)
619
+ else
620
+ arg_types[list[index].name.intern] = list[index + 1].type_reference(parent)
621
+ end
622
+ end
623
+ end
624
+ return arg_types
625
+ end
626
+ end
627
+
628
+ class IfNode
629
+ def transform(transformer, parent)
630
+ If.new(parent, position) do |iff|
631
+ [
632
+ Condition.new(iff, condition.position) {|cond| [transformer.transform(condition, cond)]},
633
+ then_body ? transformer.transform(then_body, iff) : nil,
634
+ else_body ? transformer.transform(else_body, iff) : nil
635
+ ]
636
+ end
637
+ end
638
+ end
639
+
640
+ class AndNode
641
+ def transform(transformer, parent)
642
+ If.new(parent, position) do |iff|
643
+ [
644
+ Condition.new(iff, first_node.position) {|cond| [transformer.transform(first_node, cond)]},
645
+ transformer.transform(second_node, iff),
646
+ nil
647
+ ]
648
+ end
649
+ end
650
+ end
651
+
652
+ class OpAsgnAndNode
653
+ def transform(transformer, parent)
654
+ transformer.transform(
655
+ AndNode.new(position, first_node, second_node), parent)
656
+ end
657
+ end
658
+
659
+ class OrNode
660
+ def transform(transformer, parent)
661
+ Body.new(parent, position) do |block|
662
+ temp = transformer.tmp
663
+ [
664
+ LocalAssignment.new(block, first_node.position, temp) do |l|
665
+ [transformer.transform(first_node, l)]
666
+ end,
667
+ If.new(parent, position) do |iff|
668
+ [
669
+ Condition.new(iff, first_node.position) do |cond|
670
+ [Local.new(cond, first_node.position, temp)]
671
+ end,
672
+ Local.new(iff, first_node.position, temp),
673
+ transformer.transform(second_node, iff)
674
+ ]
675
+ end
676
+ ]
677
+ end
678
+ end
679
+ end
680
+
681
+ class OpAsgnOrNode
682
+ def transform(transformer, parent)
683
+ transformer.transform(
684
+ OrNode.new(position, first_node, second_node), parent)
685
+ end
686
+ end
687
+
688
+ class OpAsgnNode
689
+ include CallOpAssignment
690
+ def transform(transformer, parent)
691
+ call_op_assignment(transformer, parent,
692
+ variable_name, ListNode.new(position))
693
+ end
694
+ end
695
+
696
+ class OpElementAsgnNode
697
+ include CallOpAssignment
698
+ def transform(transformer, parent)
699
+ Body.new(parent, position) do |block|
700
+ temps = []
701
+ arg_init = args_node.map do |arg|
702
+ temps << transformer.tmp
703
+ LocalAssignment.new(block, arg.position, temps[-1]) do |l|
704
+ [transformer.transform(arg, l)]
705
+ end
706
+ end
707
+ args = ListNode.new(position)
708
+ args_node.zip(temps) do |arg, temp_name|
709
+ args.add(LocalVarNode.new(arg.position, 0, temp_name))
710
+ end
711
+ arg_init + [call_op_assignment(transformer, parent, '[]', args)]
712
+ end
713
+ end
714
+ end
715
+
716
+ class RescueNode
717
+ def transform(transformer, parent)
718
+ Rescue.new(parent, position) do |node|
719
+ [
720
+ transformer.transform(body_node, node),
721
+ rescue_node ? transformer.transform(rescue_node, node) : []
722
+ ]
723
+ end
724
+ end
725
+ end
726
+
727
+ class RescueBodyNode
728
+ def transform(transformer, parent)
729
+ children = if opt_rescue_node
730
+ transformer.transform(opt_rescue_node, parent)
731
+ else
732
+ []
733
+ end
734
+ [
735
+ RescueClause.new(parent, position) do |clause|
736
+ exceptions = if exception_nodes
737
+ exception_nodes.map {|e| e.type_reference(clause)}
738
+ else
739
+ [AST.type('java.lang.Exception')]
740
+ end
741
+ [
742
+ exceptions,
743
+ transformer.transform(body_node, clause)
744
+ ]
745
+ end,
746
+ *children
747
+ ]
748
+ end
749
+ end
750
+
751
+ class EnsureNode
752
+ def transform(transformer, parent)
753
+ Ensure.new(parent, position) do |node|
754
+ child_nodes.map {|c| transformer.transform(c, node)}
755
+ end
756
+ end
757
+ end
758
+
759
+ class NilImplicitNode
760
+ def transform(transformer, parent)
761
+ Noop.new(parent, position)
762
+ end
763
+ end
764
+
765
+ class NilNode
766
+ def transform(transformer, parent)
767
+ Null.new(parent, position)
768
+ end
769
+ end
770
+
771
+ class InstAsgnNode
772
+ def transform(transformer, parent)
773
+ case value_node
774
+ when SymbolNode, ConstNode
775
+ FieldDeclaration.new(parent, position,
776
+ name, transformer.annotations) do |field_decl|
777
+ [value_node.type_reference(field_decl)]
778
+ end
779
+ else
780
+ FieldAssignment.new(parent, position, name, transformer.annotations) {|field| [transformer.transform(value_node, field)]}
781
+ end
782
+ end
783
+ end
784
+
785
+ class InstVarNode
786
+ def transform(transformer, parent)
787
+ Field.new(parent, position, name, transformer.annotations)
788
+ end
789
+ end
790
+
791
+ class LocalAsgnNode
792
+ def transform(transformer, parent)
793
+ captured = transformer.captured?(self)
794
+ case value_node
795
+ when SymbolNode, ConstNode
796
+ LocalDeclaration.new(parent, position, name, captured) {|local_decl| [value_node.type_reference(local_decl)]}
797
+ when JRubyAst::GlobalVarNode
798
+ real_parent = parent
799
+ real_parent = parent.parent if Body === real_parent
800
+ if value_node.name == '$!' && RescueClause === real_parent
801
+ real_parent.name = name
802
+ Noop.new(parent, position)
803
+ else
804
+ raise "Illegal global variable"
805
+ end
806
+ else
807
+ LocalAssignment.new(parent, position, name, captured) {|local| [transformer.transform(value_node, local)]}
808
+ end
809
+ end
810
+ end
811
+
812
+ class LocalVarNode
813
+ def transform(transformer, parent)
814
+ Local.new(parent, position, name, transformer.captured?(self))
815
+ end
816
+ end
817
+
818
+ class ModuleNode
819
+ end
820
+
821
+ class NewlineNode
822
+ def transform(transformer, parent)
823
+ actual = transformer.transform(next_node, parent)
824
+ actual.newline = true
825
+ actual
826
+ end
827
+
828
+ # newlines are bypassed during signature transformation
829
+ def signature(parent)
830
+ next_node.signature(parent)
831
+ end
832
+ end
833
+
834
+ class NextNode
835
+ def transform(transformer, parent)
836
+ # TODO support 'next value'?
837
+ Next.new(parent, position)
838
+ end
839
+ end
840
+
841
+ class NotNode
842
+ def transform(transformer, parent)
843
+ Not.new(parent, position) {|nott| [transformer.transform(condition_node, nott)]}
844
+ end
845
+ end
846
+
847
+ class RedoNode
848
+ def transform(transformer, parent)
849
+ Redo.new(parent, position)
850
+ end
851
+ end
852
+
853
+ class ReturnNode
854
+ def transform(transformer, parent)
855
+ Return.new(parent, position) do |ret|
856
+ [transformer.transform(value_node, ret)]
857
+ end
858
+ end
859
+ end
860
+
861
+ class RootNode
862
+ def getScope
863
+ getStaticScope
864
+ end
865
+
866
+ def transform(transformer, parent)
867
+ Script.new(parent, position) {|script| [transformer.transform(child_nodes[0], script)]}
868
+ end
869
+ end
870
+
871
+ class SelfNode
872
+ end
873
+
874
+ class StrNode
875
+ def transform(transformer, parent)
876
+ String.new(parent, position, value)
877
+ end
878
+
879
+ def type_reference(parent)
880
+ AST::type(value)
881
+ end
882
+ end
883
+
884
+ class SymbolNode
885
+ def type_reference(parent)
886
+ AST::type(name)
887
+ end
888
+ end
889
+
890
+ class TrueNode
891
+ def transform(transformer, parent)
892
+ Boolean.new(parent, position, true)
893
+ end
894
+ end
895
+
896
+ class TypedArgumentNode
897
+ def transform(transformer, parent)
898
+ type_node.transform(transformer, parent)
899
+ end
900
+ end
901
+
902
+ class VCallNode
903
+ def transform(transformer, parent)
904
+ if name == 'raise'
905
+ Raise.new(parent, position) do
906
+ []
907
+ end
908
+ elsif name == 'null'
909
+ Null.new(parent, position)
910
+ else
911
+ macro = AST.macro(name)
912
+ if macro
913
+ transformer.expand(self, parent, &macro)
914
+ else
915
+ FunctionalCall.new(parent, position, name) do |call|
916
+ [
917
+ [],
918
+ nil
919
+ ]
920
+ end
921
+ end
922
+ end
923
+ end
924
+
925
+ def type_reference(parent)
926
+ AST::type name
927
+ end
928
+ end
929
+
930
+ class WhileNode
931
+ def transform(transformer, parent)
932
+ Loop.new(parent, position, evaluate_at_start, false) do |loop|
933
+ [
934
+ Condition.new(loop, condition_node.position) {|cond| [transformer.transform(condition_node, cond)]},
935
+ transformer.transform(body_node, loop)
936
+ ]
937
+ end
938
+ end
939
+ end
940
+
941
+ class UntilNode
942
+ def transform(transformer, parent)
943
+ Loop.new(parent, position, evaluate_at_start, true) do |loop|
944
+ [
945
+ Condition.new(loop, condition_node.position) {|cond| [transformer.transform(condition_node, cond)]},
946
+ transformer.transform(body_node, loop)
947
+ ]
948
+ end
949
+ end
950
+ end
951
+
952
+ class DVarNode
953
+ def transform(transformer, parent)
954
+ # TODO does this need to be handled specially?
955
+ Local.new(parent, position, name, transformer.captured?(self))
956
+ end
957
+ end
958
+
959
+ class DAsgnNode
960
+ def transform(transformer, parent)
961
+ captured = transformer.captured?(self)
962
+ case value_node
963
+ when SymbolNode, ConstNode
964
+ LocalDeclaration.new(parent, position, name, captured) {|local_decl| [value_node.type_reference(local_decl)]}
965
+ else
966
+ LocalAssignment.new(parent, position, name, captured) {|local| [transformer.transform(value_node, local)]}
967
+ end
968
+ end
969
+ end
970
+
971
+ class IterNode
972
+ def transform(transformer, parent)
973
+ Block.new(parent, position) do |block|
974
+ [
975
+ transformer.transform(var_node, block),
976
+ transformer.transform(body_node, block)
977
+ ]
978
+ end
979
+ end
980
+ end
981
+
982
+ class ForNode
983
+ def transform(transformer, parent)
984
+ Call.new(parent, position, 'each') do |each|
985
+ [
986
+ transformer.transform(iter_node, each),
987
+ [],
988
+ Block.new(each, body_node.position) do |block|
989
+ [
990
+ Arguments.new(block, var_node.position) do |args|
991
+ [
992
+ # TODO support for multiple assignment?
993
+ [RequiredArgument.new(args,
994
+ var_node.position,
995
+ var_node.name)
996
+ ]
997
+ ]
998
+ end,
999
+ transformer.transform(body_node, block)
1000
+ ]
1001
+ end
1002
+ ]
1003
+ end
1004
+ end
1005
+ end
1006
+
1007
+ class SuperNode
1008
+ def transform(transformer, parent)
1009
+ Super.new(parent, position) do
1010
+ [args_node ? args_node.map {|arg| transformer.transform(arg, parent)} : []]
1011
+ end
1012
+ end
1013
+ end
1014
+
1015
+ class ZSuperNode
1016
+ def transform(transformer, parent)
1017
+ Super.new(parent, position)
1018
+ end
1019
+ end
1020
+
1021
+ class SelfNode
1022
+ def transform(transformer, parent)
1023
+ Self.new(parent, position)
1024
+ end
1025
+ end
1026
+ end
1027
+ end
1028
+ end