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,193 @@
1
+ module Duby
2
+ module JVM
3
+ module MethodLookup
4
+ # dummy log; it's expected the inclusion target will have it
5
+ def log(msg); end
6
+
7
+ # def jvm_type(type)
8
+ # return type if type.kind_of? Java::JavaClass
9
+ # return type.jvm_type
10
+ # end
11
+ #
12
+ # def convert_params(params)
13
+ # params.map {|param| jvm_type(param)}
14
+ # end
15
+
16
+ def find_method(mapped_type, name, mapped_params, meta)
17
+ # mapped_type = jvm_type(mapped_type)
18
+ # mapped_params = convert_params(mapped_params)
19
+ raise ArgumentError if mapped_params.any? {|p| p.nil?}
20
+ if name == 'new'
21
+ if meta
22
+ name = "<init>"
23
+ constructor = true
24
+ else
25
+ constructor = false
26
+ end
27
+ end
28
+
29
+ begin
30
+ if constructor
31
+ method = mapped_type.constructor(*mapped_params)
32
+ else
33
+ method = mapped_type.java_method(name, *mapped_params)
34
+ end
35
+ rescue NameError
36
+ # exact args failed, do a deeper search
37
+ log "No exact match for #{mapped_type.name}.#{name}(#{mapped_params.map(&:name)})"
38
+
39
+ method = find_jls(mapped_type, name, mapped_params, meta, constructor)
40
+
41
+ unless method
42
+ log "Failed to locate method #{mapped_type.name}.#{name}(#{mapped_params.map(&:name)})"
43
+ return nil
44
+ end
45
+ end
46
+
47
+ log "Found method #{method.declaring_class.name}.#{name}(#{method.argument_types.map(&:name)}) from #{mapped_type.name}"
48
+ return method
49
+ end
50
+
51
+ def find_jls(mapped_type, name, mapped_params, meta, constructor)
52
+ # mapped_type = jvm_type(mapped_type)
53
+ # mapped_params = convert_params(mapped_params)
54
+ if constructor
55
+ all_methods = mapped_type.unmeta.declared_constructors
56
+ by_name = all_methods
57
+ elsif meta
58
+ all_methods = mapped_type.declared_class_methods
59
+ else
60
+ all_methods = []
61
+ cls = mapped_type
62
+ while cls
63
+ all_methods += cls.declared_instance_methods
64
+ cls = cls.superclass
65
+ end
66
+ end
67
+ # filter by name, if we haven't already got a by_name list
68
+ by_name ||= all_methods.select {|m| m.name == name && mapped_params.size <= m.argument_types.size}
69
+ # filter by arity
70
+ by_name_and_arity = by_name.select {|m| m.argument_types.size == mapped_params.size}
71
+
72
+ phase1_methods = phase1(mapped_params, by_name_and_arity)
73
+
74
+ if phase1_methods.size > 1
75
+ raise "Ambiguous targets invoking #{mapped_type}.#{name}:\n#{phase1_methods}"
76
+ end
77
+
78
+ phase1_methods[0] ||
79
+ phase2(mapped_params, by_name) ||
80
+ phase3(mapped_params, by_name)
81
+ end
82
+
83
+ def phase1(mapped_params, potentials)
84
+ log "Beginning JLS phase 1 search with params (#{mapped_params.map(&:name)})"
85
+
86
+ # cycle through methods looking for more specific matches; gather matches of equal specificity
87
+ methods = potentials.inject([]) do |currents, potential|
88
+ method_params = potential.argument_types
89
+
90
+ # exact match always wins; duplicates not possible
91
+ if each_is_exact(mapped_params, method_params)
92
+ return [potential]
93
+ end
94
+
95
+ # otherwise, check for potential match and compare to current
96
+ # TODO: missing ambiguity check; picks last method of equal specificity
97
+ if each_is_exact_or_subtype_or_convertible(mapped_params, method_params)
98
+ if currents.size > 0
99
+ if is_more_specific?(potential.argument_types, currents[0].argument_types)
100
+ # potential is better, dump all currents
101
+ currents = [potential]
102
+ elsif is_more_specific?(currents[0].argument_types, potential.argument_types)
103
+ # currents are better, try next potential
104
+ #next
105
+ else
106
+ # equal specificity, append to currents
107
+ currents << potential
108
+ end
109
+ else
110
+ # no previous matches, use potential
111
+ currents = [potential]
112
+ end
113
+ end
114
+
115
+ currents
116
+ end
117
+
118
+ methods
119
+ end
120
+
121
+ def is_more_specific?(potential, current)
122
+ each_is_exact_or_subtype_or_convertible(potential, current)
123
+ end
124
+
125
+ def phase2(mapped_params, potentials)
126
+ nil
127
+ end
128
+
129
+ def phase3(mapped_params, potentials)
130
+ nil
131
+ end
132
+
133
+ def each_is_exact(incoming, target)
134
+ incoming.each_with_index do |in_type, i|
135
+ target_type = target[i]
136
+
137
+ # exact match
138
+ return false unless target_type == in_type
139
+ end
140
+ return true
141
+ end
142
+
143
+ def each_is_exact_or_subtype_or_convertible(incoming, target)
144
+ incoming.each_with_index do |in_type, i|
145
+ target_type = target[i]
146
+
147
+ # exact match
148
+ next if target_type == in_type
149
+
150
+ # primitive is safely convertible
151
+ if target_type.primitive?
152
+ if in_type.primitive?
153
+ next if primitive_convertible? in_type, target_type
154
+ end
155
+ return false
156
+ end
157
+
158
+ # object type is assignable
159
+ return false unless target_type.assignable_from? in_type
160
+ end
161
+ return true
162
+ end
163
+
164
+ BOOLEAN = Java::boolean.java_class
165
+ BYTE = Java::byte.java_class
166
+ SHORT = Java::short.java_class
167
+ CHAR = Java::char.java_class
168
+ INT = Java::int.java_class
169
+ LONG = Java::long.java_class
170
+ FLOAT = Java::float.java_class
171
+ DOUBLE = Java::double.java_class
172
+
173
+ PrimitiveConversions = {
174
+ BOOLEAN => [BOOLEAN],
175
+ BYTE => [BYTE, SHORT, CHAR, INT, LONG, FLOAT, DOUBLE],
176
+ SHORT => [SHORT, INT, LONG, FLOAT, DOUBLE],
177
+ CHAR => [CHAR, INT, LONG, FLOAT, DOUBLE],
178
+ INT => [INT, LONG, FLOAT, DOUBLE],
179
+ LONG => [LONG, DOUBLE],
180
+ FLOAT => [FLOAT, DOUBLE],
181
+ DOUBLE => [DOUBLE]
182
+ }
183
+
184
+ def primitive_convertible?(in_type, target_type)
185
+ if PrimitiveConversions.include? in_type
186
+ PrimitiveConversions[in_type].include?(target_type)
187
+ else
188
+ in_type.convertible_to?(target_type)
189
+ end
190
+ end
191
+ end
192
+ end
193
+ end
@@ -0,0 +1,605 @@
1
+ require 'duby'
2
+ require 'duby/ast'
3
+ require 'duby/jvm/types'
4
+ require 'duby/jvm/compiler'
5
+ require 'duby/jvm/source_generator/builder'
6
+ require 'duby/jvm/source_generator/precompile'
7
+ require 'duby/jvm/source_generator/loops'
8
+
9
+ class String
10
+ def compile(compiler, expression)
11
+ compiler.method.print self if expression
12
+ end
13
+ end
14
+
15
+ module Duby
16
+ module Compiler
17
+ class JavaSource
18
+ JVMTypes = Duby::JVM::Types
19
+ include Duby::Compiler::JVM::JVMLogger
20
+ attr_accessor :filename, :method, :static, :class, :lvalue
21
+
22
+ Operators = [
23
+ '+', '-', '+@', '-@', '/', '%', '*', '<',
24
+ '<=', '==', '!=', '>=', '>',
25
+ '<<', '>>', '>>>', '|', '&', '^', '~'
26
+ ]
27
+ ArrayOps = [
28
+ '[]', '[]=', 'length'
29
+ ]
30
+
31
+ ImplicitReturn = Struct.new(:value)
32
+
33
+ def initialize(filename)
34
+ @filename = File.basename(filename)
35
+ @static = true
36
+ parts = filename.split '/'
37
+ classname = parts.pop.sub /[.].+/, ''
38
+ package = parts.join('.') unless parts.empty?
39
+
40
+ @file = Duby::JavaSource::Builder.new(filename, self)
41
+ #@file.package = package
42
+ @type = AST::type(classname)
43
+ end
44
+
45
+ def toplevel_class
46
+ @class = @type.define(@file)
47
+ end
48
+
49
+ def generate(&block)
50
+ log "Generating source files..."
51
+ @file.generate do |filename, builder|
52
+ log " #{builder.class_name}"
53
+ if block_given?
54
+ yield filename, builder
55
+ else
56
+ File.open(filename, 'w') {|f| f.write(builder.generate)}
57
+ end
58
+ end
59
+ log "...done!"
60
+ end
61
+
62
+ def define_main(body)
63
+ if body.class != AST::ClassDefinition
64
+ @class = @type.define(@file)
65
+ with :method => @class.main do
66
+ log "Starting main method"
67
+
68
+ @method.start
69
+
70
+ body.compile(self, false)
71
+
72
+ @method.stop
73
+ end
74
+ @class.stop
75
+ else
76
+ body.compile(self, false)
77
+ end
78
+
79
+ log "Main method complete!"
80
+ end
81
+
82
+ def define_method(node)
83
+ name, signature, args = node.name, node.signature, node.arguments.args
84
+ args ||= []
85
+ return_type = signature[:return]
86
+ exceptions = signature[:throws] || []
87
+ with :static => @static || node.static? do
88
+ if @static
89
+ method = @class.public_static_method(name.to_s, return_type, exceptions, *args)
90
+ else
91
+ method = @class.public_method(name.to_s, return_type, exceptions, *args)
92
+ end
93
+
94
+ with :method => method do
95
+ log "Starting new method #{name}"
96
+ @method.annotate(node.annotations)
97
+ @method.start
98
+
99
+ unless @method.type.nil? || @method.type.void?
100
+ self.return(ImplicitReturn.new(node.body))
101
+ else
102
+ node.body.compile(self, false) if node.body
103
+ end
104
+
105
+ log "Method #{name} complete!"
106
+ @method.stop
107
+ end
108
+ end
109
+ end
110
+
111
+ def constructor(node)
112
+ args = node.arguments.args || []
113
+ exceptions = node.signature[:throws] || []
114
+ method = @class.public_constructor(exceptions, *args)
115
+ with :method => method do
116
+ @method.annotate(node.annotations)
117
+ @method.start
118
+ if node.delegate_args
119
+ delegate = if node.calls_super
120
+ "super"
121
+ else
122
+ "this"
123
+ end
124
+ method.print "#{delegate}("
125
+ node.delegate_args.each_with_index do |arg, index|
126
+ method.print ', ' unless index == 0
127
+ raise "Invalid constructor argument #{arg}" unless arg.expr?(self)
128
+ arg.compile(self, true)
129
+ end
130
+ method.puts ");"
131
+ end
132
+
133
+ node.body.compile(self, false) if node.body
134
+ method.stop
135
+ end
136
+ end
137
+
138
+ def return(node)
139
+ if @method.type.nil? || @method.type.void?
140
+ @method.puts 'return;'
141
+ return
142
+ end
143
+ if node.value.expr?(self)
144
+ @method.print 'return '
145
+ node.value.compile(self, true)
146
+ @method.puts ';'
147
+ else
148
+ store_value('return ', node.value)
149
+ end
150
+ end
151
+
152
+ def _raise(node)
153
+ if node.expr?(self)
154
+ @method.print 'throw '
155
+ node.compile(self, true)
156
+ @method.puts ';'
157
+ else
158
+ store_value('throw ', node)
159
+ end
160
+ end
161
+
162
+ def rescue(node, expression)
163
+ @method.block 'try' do
164
+ maybe_store(node.body, expression)
165
+ end
166
+ node.clauses.each do |clause|
167
+ clause.types.each do |type|
168
+ name = clause.name || 'tmp$ex'
169
+ @method.block "catch (#{type.to_source} #{name})" do
170
+ maybe_store(clause.body, expression)
171
+ end
172
+ end
173
+ end
174
+ end
175
+
176
+ def ensure(node, expression)
177
+ @method.block 'try' do
178
+ maybe_store(node.body, expression)
179
+ end
180
+ @method.block 'finally' do
181
+ node.clause.compile(self, false)
182
+ end
183
+ end
184
+
185
+ def line(num)
186
+ end
187
+
188
+ def declare_local(name, type)
189
+ @method.declare_local(type, name)
190
+ end
191
+
192
+ def declare_field(name, type, annotations)
193
+ @class.declare_field(name, type, @static, annotations)
194
+ end
195
+
196
+ def local(name, type)
197
+ @method.print name
198
+ end
199
+
200
+ def field(name, type, annotations)
201
+ name = name[1..-1]
202
+ declare_field(name, type, annotations)
203
+ @method.print "#{this}.#{name}"
204
+ end
205
+
206
+ def this
207
+ @static ? @class.class_name : 'this'
208
+ end
209
+
210
+ def local_assign(name, type, expression, value)
211
+ value = value.precompile(self)
212
+ if method.local?(name)
213
+ @method.print @lvalue if expression
214
+ @method.print "#{name} = "
215
+ value.compile(self, true)
216
+ @method.puts ';'
217
+ else
218
+ @method.declare_local(type, name) do
219
+ value.compile(self, true)
220
+ end
221
+ if expression
222
+ @method.puts "#{@lvalue}#{name};"
223
+ end
224
+ end
225
+ end
226
+
227
+ def field_declare(name, type, annotations)
228
+ name = name[1..-1]
229
+ declare_field(name, type, annotations)
230
+ end
231
+
232
+ def local_declare(name, type)
233
+ declare_local(name, type)
234
+ end
235
+
236
+ def field_assign(name, type, expression, value, annotations)
237
+ name = name[1..-1]
238
+ declare_field(name, type, annotations)
239
+ lvalue = "#{@lvalue if expression}#{this}.#{name} = "
240
+ store_value(lvalue, value)
241
+ end
242
+
243
+ def store_value(lvalue, value)
244
+ if value.is_a? String
245
+ @method.puts "#{lvalue}#{value};"
246
+ elsif value.expr?(self)
247
+ @method.print lvalue
248
+ value.compile(self, true)
249
+ @method.puts ';'
250
+ else
251
+ with :lvalue => lvalue do
252
+ value.compile(self, true)
253
+ end
254
+ end
255
+ end
256
+
257
+ def assign(name, value)
258
+ store_value("#{name} = ", value)
259
+ name
260
+ end
261
+
262
+ def maybe_store(value, expression)
263
+ if expression
264
+ store_value(@lvalue, value)
265
+ else
266
+ value.compile(self, false)
267
+ end
268
+ end
269
+
270
+ def body(body, expression)
271
+ # all except the last element in a body of code is treated as a statement
272
+ i, last = 0, body.children.size - 1
273
+ while i < last
274
+ body.children[i].compile(self, false)
275
+ i += 1
276
+ end
277
+ # last element is an expression only if the body is an expression
278
+ maybe_store(body.children[last], expression)
279
+ end
280
+
281
+ def branch_expression(node)
282
+ node.condition.compile(self, true)
283
+ @method.print ' ? ('
284
+ if node.body
285
+ node.body.compile(self, true)
286
+ else
287
+ @method.print @method.init_value(node.inferred_type)
288
+ end
289
+ @method.print ') : ('
290
+ if node.else
291
+ node.else.compile(self, true)
292
+ else
293
+ @method.print @method.init_value(node.inferred_type)
294
+ end
295
+ @method.print ')'
296
+ end
297
+
298
+ def branch(node, expression)
299
+ if expression && node.expr?(self)
300
+ return branch_expression(node)
301
+ end
302
+ predicate = node.condition.predicate.precompile(self)
303
+ @method.print 'if ('
304
+ predicate.compile(self, true)
305
+ @method.block ")" do
306
+ if node.body
307
+ maybe_store(node.body, expression)
308
+ elsif expression
309
+ store_value(@lvalue, @method.init_value(node.inferred_type))
310
+ end
311
+ end
312
+ if node.else || expression
313
+ @method.block 'else' do
314
+ if node.else
315
+ maybe_store(node.else, expression)
316
+ else
317
+ store_value(@lvalue, @method.init_value(node.inferred_type))
318
+ end
319
+ end
320
+ end
321
+ end
322
+
323
+ def loop(loop, expression)
324
+ if loop.redo? || loop.post || !loop.condition.predicate.expr?(self)
325
+ loop = ComplexWhileLoop.new(loop, self)
326
+ else
327
+ loop = SimpleWhileLoop.new(loop, self)
328
+ end
329
+ with(:loop => loop) do
330
+ loop.compile(expression)
331
+ end
332
+ end
333
+
334
+ def expr?(target, params)
335
+ !([target] + params).any? {|x| x.kind_of? Duby::AST::TempValue}
336
+ end
337
+
338
+ def operator(target, op, params, expression)
339
+ simple = expr?(target, params)
340
+ if expression && !simple
341
+ @method.print @lvalue
342
+ end
343
+ if params.size == 0
344
+ # unary operator
345
+ op = op[0,1]
346
+ @method.print op
347
+ target.compile(self, true)
348
+ else
349
+ @method.print '('
350
+ other = params[0]
351
+ target.compile(self, true)
352
+ @method.print " #{op} "
353
+ other.compile(self, true)
354
+ @method.print ')'
355
+ end
356
+ unless expression && simple
357
+ @method.puts ';'
358
+ end
359
+ end
360
+
361
+ def compile_args(call)
362
+ call.parameters.map do |param|
363
+ param.precompile(self)
364
+ end
365
+ end
366
+
367
+ def self_type
368
+ type = AST::type(@class.name.tr('/', '.'))
369
+ type = type.meta if @static
370
+ type
371
+ end
372
+
373
+ def super_call(call, expression)
374
+ super_method_call(this, call, compile_args(call), expression)
375
+ end
376
+
377
+ def self_call(call, expression)
378
+ if call.cast?
379
+ args = compile_args(call)
380
+ simple = call.expr?(self)
381
+ @method.print @lvalue if expression && !simple
382
+ @method.print "(#{call.inferred_type.name})("
383
+ args.each{|arg| arg.compile(self, true)}
384
+ @method.print ")"
385
+ @method.puts ';' unless simple && expression
386
+ else
387
+ method_call(this, call, compile_args(call), expression)
388
+ end
389
+ end
390
+
391
+ def call(call, expression)
392
+ if Duby::AST::Constant === call.target
393
+ target = call.target.inferred_type.name
394
+ else
395
+ target = call.target.precompile(self)
396
+ end
397
+ params = compile_args(call)
398
+
399
+ if Operators.include? call.name
400
+ operator(target, call.name, params, expression)
401
+ elsif call.target.inferred_type.array? && ArrayOps.include?(call.name)
402
+ array_op(target, call.name, params, expression)
403
+ elsif call.name == 'nil?'
404
+ operator(target, '==', ['null'], expression)
405
+ else
406
+ method_call(target, call, params, expression)
407
+ end
408
+ end
409
+
410
+ def array_op(target, name, args, expression)
411
+ simple = expr?(target, args)
412
+ index, value = args
413
+ if expression && !simple
414
+ @method.print @lvalue
415
+ end
416
+ target.compile(self, true)
417
+ if name == 'length'
418
+ @method.print '.length'
419
+ else
420
+ @method.print '['
421
+ index.compile(self, true)
422
+ @method.print ']'
423
+ if name == '[]='
424
+ @method.print " = "
425
+ value.compile(self, true)
426
+ end
427
+ end
428
+ unless simple && expression
429
+ @method.puts ';'
430
+ end
431
+ end
432
+
433
+ def break(node)
434
+ @loop.break
435
+ end
436
+
437
+ def next(node)
438
+ @loop.next
439
+ end
440
+
441
+ def redo(node)
442
+ @loop.redo
443
+ end
444
+
445
+ # TODO: merge cleanly with method_call logic
446
+ def super_method_call(target, call, params, expression)
447
+ simple = call.expr?(self)
448
+ method = call.method(self)
449
+ unless simple || method.actual_return_type.void?
450
+ @method.print @lvalue if expression
451
+ end
452
+ if method.constructor?
453
+ @method.print "super("
454
+ else
455
+ @method.print "super.#{method.name}("
456
+ end
457
+ params.each_with_index do |param, index|
458
+ @method.print ', ' unless index == 0
459
+ param.compile(self, true)
460
+ end
461
+ if simple && expression
462
+ @method.print ')'
463
+ else
464
+ @method.puts ');'
465
+ end
466
+ if method.actual_return_type.void? && expression
467
+ @method.print @lvalue
468
+ if method.static?
469
+ @method.puts 'null;'
470
+ else
471
+ target.compile(self, true)
472
+ @method.puts ';'
473
+ end
474
+ end
475
+
476
+ end
477
+
478
+ def method_call(target, call, params, expression)
479
+ simple = call.expr?(self)
480
+ method = call.method(self)
481
+ unless simple || method.actual_return_type.void?
482
+ @method.print @lvalue if expression
483
+ end
484
+ if method.constructor?
485
+ @method.print "new "
486
+ target.compile(self, true)
487
+ @method.print '('
488
+ else
489
+ target.compile(self, true)
490
+ @method.print ".#{method.name}("
491
+ end
492
+ params.each_with_index do |param, index|
493
+ @method.print ', ' unless index == 0
494
+ param.compile(self, true)
495
+ end
496
+ if simple && expression
497
+ @method.print ')'
498
+ else
499
+ @method.puts ');'
500
+ end
501
+ if method.actual_return_type.void? && expression
502
+ @method.print @lvalue
503
+ if method.static?
504
+ @method.puts 'null;'
505
+ else
506
+ target.compile(self, true)
507
+ @method.puts ';'
508
+ end
509
+ end
510
+
511
+ end
512
+
513
+ def temp(expression, value=nil)
514
+ assign(@method.tmp(expression.inferred_type), value || expression)
515
+ end
516
+
517
+ def empty_array(type, size)
518
+ sizevar = size.precompile(self)
519
+ @method.print "#{@lvalue unless size.expr?(self)}new #{type.name}["
520
+ sizevar.compile(self, true)
521
+ @method.print ']'
522
+ end
523
+
524
+ def import(short, long)
525
+ end
526
+
527
+ def string(value)
528
+ @method.print value.inspect
529
+ end
530
+
531
+ def boolean(value)
532
+ @method.print value ? 'true' : 'false'
533
+ end
534
+
535
+ def array(node, expression)
536
+ if expression
537
+ # create unmodifiable list from array (simplest way to do this in Java source)
538
+ @method.print "java.util.Collections.unmodifiableList(java.util.Arrays.asList("
539
+
540
+ # elements, as expressions
541
+ boolean comma = false
542
+ node.children.each do |node|
543
+ @method.print ", "# if comma
544
+ node.compile(self, true)
545
+ comma = true
546
+ end
547
+
548
+ @method.print("))")
549
+ else
550
+ # elements, as non-expressions
551
+ # TODO: ensure they're all reference types!
552
+ node.children.each do |node|
553
+ node.compile(self, false)
554
+ end
555
+ end
556
+ end
557
+
558
+ def null
559
+ @method.print 'null'
560
+ end
561
+
562
+ def compile_self
563
+ @method.print 'this'
564
+ end
565
+
566
+ def print(node)
567
+ value = node.parameters[0]
568
+ value = value && value.precompile(self)
569
+ if node.println
570
+ @method.print "System.out.println("
571
+ else
572
+ @method.print "System.out.print("
573
+ end
574
+ value.compile(self, true) if value
575
+ @method.puts ');'
576
+ end
577
+
578
+ def define_class(class_def, expression)
579
+ with(:class => class_def.inferred_type.define(@file),
580
+ :static => false) do
581
+ @class.annotate(class_def.annotations)
582
+ class_def.body.compile(self, false) if class_def.body
583
+
584
+ @class.stop
585
+ end
586
+ end
587
+
588
+ def with(vars)
589
+ orig_values = {}
590
+ begin
591
+ vars.each do |name, new_value|
592
+ name = "@#{name}"
593
+ orig_values[name] = instance_variable_get name
594
+ instance_variable_set name, new_value
595
+ end
596
+ yield
597
+ ensure
598
+ orig_values.each do |name, value|
599
+ instance_variable_set name, value
600
+ end
601
+ end
602
+ end
603
+ end
604
+ end
605
+ end