duby 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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