duby 0.0.1

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