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