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,82 @@
1
+ require 'delegate'
2
+
3
+ module Duby::JVM::Types
4
+
5
+ # Represents a literal number that can be represented
6
+ # in multiple types
7
+ class NarrowingType < DelegateClass(PrimitiveType)
8
+ def initialize(default_type, narrowed_type)
9
+ super(default_type)
10
+ @narrowed = default_type != narrowed_type && narrowed_type
11
+ end
12
+
13
+ def hash
14
+ __getobj__.hash
15
+ end
16
+
17
+ # Changes this type to the smallest type that will hold
18
+ # its literal value.
19
+ def narrow!
20
+ if @narrowed
21
+ __setobj__(@narrowed)
22
+ true
23
+ end
24
+ end
25
+ end
26
+
27
+ class FixnumLiteral < NarrowingType
28
+ def self.range(type)
29
+ type::MIN_VALUE .. type::MAX_VALUE
30
+ end
31
+
32
+ BYTE_RANGE = range(java.lang.Byte)
33
+ SHORT_RANGE = range(java.lang.Short)
34
+ INT_RANGE = range(java.lang.Integer)
35
+ LONG_RANGE = range(java.lang.Long)
36
+
37
+ def initialize(literal)
38
+ default_type = case literal
39
+ when INT_RANGE
40
+ Int
41
+ else
42
+ Long
43
+ end
44
+
45
+ # TODO chars?
46
+ # There's not really any way to tell if we should narrow to a char
47
+ # or a byte/short. I suppose we could try both, but that seems ugly.
48
+ # Maybe it's the right thing to do though?
49
+ narrowed_type = case literal
50
+ when BYTE_RANGE
51
+ Byte
52
+ when SHORT_RANGE
53
+ Short
54
+ when INT_RANGE
55
+ Int
56
+ else
57
+ Long
58
+ end
59
+
60
+ super(default_type, narrowed_type)
61
+ end
62
+ end
63
+
64
+ class FloatLiteral < NarrowingType
65
+ FLOAT_RANGE = java.lang.Float::MIN_VALUE .. java.lang.Float::MAX_VALUE
66
+ NaN = java.lang.Float::NaN
67
+ POSITIVE_INFINITY = java.lang.Float::POSITIVE_INFINITY
68
+ NEGATIVE_INFINITY = java.lang.Float::NEGATIVE_INFINITY
69
+
70
+ def initialize(literal)
71
+ narrowed_type = case literal
72
+ when FLOAT_RANGE, NaN, POSITIVE_INFINITY, NEGATIVE_INFINITY
73
+ Float
74
+ else
75
+ Double
76
+ end
77
+
78
+ # TODO Double should be default once it supports operators
79
+ super(narrowed_type, narrowed_type)
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,381 @@
1
+ require 'duby/jvm/types'
2
+
3
+ class Java::JavaMethod
4
+ def static?
5
+ java.lang.reflect.Modifier.static?(modifiers)
6
+ end
7
+ end
8
+
9
+ module Duby::JVM::Types
10
+ AST ||= Duby::AST
11
+
12
+ module ArgumentConversion
13
+ def convert_args(compiler, values, types=nil)
14
+ # TODO boxing/unboxing
15
+ # TODO varargs
16
+ types ||= argument_types
17
+ values.zip(types).each do |value, type|
18
+ value.compile(compiler, true)
19
+ if type.primitive? && type != value.inferred_type
20
+ value.inferred_type.widen(compiler.method, type)
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ Type.send :include, ArgumentConversion
27
+
28
+ class Intrinsic
29
+ include ArgumentConversion
30
+ attr_reader :name, :argument_types, :return_type
31
+
32
+ def initialize(klass, name, args, type, &block)
33
+ raise ArgumentError, "Block required" unless block_given?
34
+ @class = klass
35
+ @name = name
36
+ @argument_types = args
37
+ @return_type = type
38
+ @block = block
39
+ end
40
+
41
+ def call(builder, ast, expression)
42
+ @block.call(builder, ast, expression)
43
+ end
44
+
45
+ def declaring_class
46
+ @class
47
+ end
48
+
49
+ def constructor?
50
+ false
51
+ end
52
+
53
+ def exceptions
54
+ []
55
+ end
56
+
57
+ def actual_return_type
58
+ return_type
59
+ end
60
+ end
61
+
62
+ class JavaConstructor
63
+ include ArgumentConversion
64
+ def initialize(member)
65
+ @member = member
66
+ end
67
+
68
+ def name
69
+ @name ||= @member.name
70
+ end
71
+
72
+ def argument_types
73
+ @argument_types ||= @member.argument_types.map do |arg|
74
+ AST.type(arg) if arg
75
+ end
76
+ end
77
+
78
+ def return_type
79
+ declaring_class
80
+ end
81
+
82
+ def actual_return_type
83
+ return_type
84
+ end
85
+
86
+ def exceptions
87
+ @member.exception_types.map do |exception|
88
+ AST.type(exception.name)
89
+ end
90
+ end
91
+
92
+ def declaring_class
93
+ AST.type(@member.declaring_class)
94
+ end
95
+
96
+ def call(compiler, ast, expression)
97
+ target = ast.target.inferred_type
98
+ compiler.method.new target
99
+ compiler.method.dup if expression
100
+ convert_args(compiler, ast.parameters)
101
+ compiler.method.invokespecial(
102
+ target,
103
+ "<init>",
104
+ [nil, *@member.argument_types])
105
+ end
106
+
107
+ def constructor?
108
+ true
109
+ end
110
+ end
111
+
112
+ class JavaMethod < JavaConstructor
113
+ def return_type
114
+ @return_type ||= begin
115
+ if @member.return_type
116
+ AST.type(@member.return_type)
117
+ else
118
+ declaring_class
119
+ end
120
+ end
121
+ end
122
+
123
+ def actual_return_type
124
+ if @member.return_type
125
+ return_type
126
+ else
127
+ Void
128
+ end
129
+ end
130
+
131
+ def static?
132
+ @member.static?
133
+ end
134
+
135
+ def void?
136
+ @member.return_type.nil?
137
+ end
138
+
139
+ def constructor?
140
+ false
141
+ end
142
+
143
+ def call(compiler, ast, expression)
144
+ target = ast.target.inferred_type
145
+ ast.target.compile(compiler, true)
146
+
147
+ # if expression, void methods return the called object,
148
+ # for consistency and chaining
149
+ # TODO: inference phase needs to track that signature is
150
+ # void but actual type is callee
151
+ if expression && void?
152
+ compiler.method.dup
153
+ end
154
+
155
+ convert_args(compiler, ast.parameters)
156
+ if target.interface?
157
+ compiler.method.invokeinterface(
158
+ target,
159
+ name,
160
+ [@member.return_type, *@member.argument_types])
161
+ else
162
+ compiler.method.invokevirtual(
163
+ target,
164
+ name,
165
+ [@member.return_type, *@member.argument_types])
166
+ end
167
+
168
+ unless expression || void?
169
+ compiler.method.pop
170
+ end
171
+ end
172
+
173
+ def call_special(compiler, ast, expression)
174
+ target = ast.target.inferred_type
175
+ ast.target.compile(compiler, true)
176
+
177
+ # if expression, void methods return the called object,
178
+ # for consistency and chaining
179
+ # TODO: inference phase needs to track that signature is
180
+ # void but actual type is callee
181
+ if expression && void?
182
+ compiler.method.dup
183
+ end
184
+
185
+ convert_args(compiler, ast.parameters)
186
+ if target.interface?
187
+ raise "interfaces should not receive call_special"
188
+ else
189
+ compiler.method.invokespecial(
190
+ target,
191
+ name,
192
+ [@member.return_type, *@member.argument_types])
193
+ end
194
+
195
+ unless expression || void?
196
+ compiler.method.pop
197
+ end
198
+ end
199
+ end
200
+
201
+ class JavaStaticMethod < JavaMethod
202
+ def return_type
203
+ @return_type ||= begin
204
+ if @member.return_type
205
+ AST.type(@member.return_type)
206
+ else
207
+ Void
208
+ end
209
+ end
210
+ end
211
+
212
+ def call(compiler, ast, expression)
213
+ target = ast.target.inferred_type
214
+ convert_args(compiler, ast.parameters)
215
+ compiler.method.invokestatic(
216
+ target,
217
+ name,
218
+ [@member.return_type, *@member.argument_types])
219
+ # if expression, void static methods return null, for consistency
220
+ # TODO: inference phase needs to track that signature is void
221
+ # but actual type is null object
222
+ compiler.method.aconst_null if expression && void?
223
+ compiler.method.pop unless expression || void?
224
+ end
225
+ end
226
+
227
+ class DubyMember
228
+ attr_reader :name, :argument_types, :declaring_class, :return_type
229
+ attr_reader :exception_types
230
+
231
+ def initialize(klass, name, args, return_type, static, exceptions)
232
+ if return_type == Void
233
+ return_type = nil
234
+ end
235
+ @declaring_class = klass
236
+ @name = name
237
+ @argument_types = args
238
+ @return_type = return_type
239
+ @static = static
240
+ @exception_types = exceptions || []
241
+ end
242
+
243
+ def static?
244
+ @static
245
+ end
246
+ end
247
+
248
+ class Type
249
+ def get_method(name, args)
250
+ method = find_method(self, name, args, meta?)
251
+ unless method
252
+ # Allow constant narrowing for assignment methods
253
+ if name =~ /=$/ && args[-1].respond_to?(:narrow!)
254
+ if args[-1].narrow!
255
+ method = find_method(self, name, args, meta?)
256
+ end
257
+ end
258
+ end
259
+ method
260
+ end
261
+
262
+ def constructor(*types)
263
+ types = types.map {|type| type.jvm_type}
264
+ constructor = (jvm_type.constructor(*types) rescue nil)
265
+ return JavaConstructor.new(constructor) if constructor
266
+ raise NameError, "No constructor #{name}(#{types.join ', '})"
267
+ end
268
+
269
+ def java_method(name, *types)
270
+ intrinsic = intrinsics[name][types]
271
+ return intrinsic if intrinsic
272
+ types = types.map {|type| type.jvm_type}
273
+ method = (jvm_type.java_method(name, *types) rescue nil)
274
+ if method && method.static? == meta?
275
+ return JavaStaticMethod.new(method) if method.static?
276
+ return JavaMethod.new(method)
277
+ end
278
+ raise NameError, "No method #{self.name}.#{name}(#{types.join ', '})"
279
+ end
280
+
281
+ def declared_instance_methods
282
+ if jvm_type && !array?
283
+ methods = jvm_type.declared_instance_methods.map do |method|
284
+ JavaMethod.new(method)
285
+ end
286
+ else
287
+ methods = []
288
+ end
289
+ methods.concat((meta? ? unmeta : self).declared_intrinsics)
290
+ end
291
+
292
+ def declared_class_methods
293
+ methods = jvm_type.declared_class_methods.map do |method|
294
+ JavaStaticMethod.new(method)
295
+ end
296
+ methods.concat(meta.declared_intrinsics)
297
+ end
298
+
299
+ def declared_constructors
300
+ jvm_type.declared_constructors.map do |method|
301
+ JavaConstructor.new(method)
302
+ end
303
+ end
304
+ end
305
+
306
+ class TypeDefinition
307
+ def java_method(name, *types)
308
+ method = instance_methods[name].find {|m| m.argument_types == types}
309
+ return method if method
310
+ raise NameError, "No method #{self.name}.#{name}(#{types.join ', '})"
311
+ end
312
+
313
+ def java_static_method(name, *types)
314
+ method = static_methods[name].find {|m| m.argument_types == types}
315
+ return method if method
316
+ raise NameError, "No method #{self.name}.#{name}(#{types.join ', '})"
317
+ end
318
+
319
+ def constructor(*types)
320
+ constructor = constructors.find {|c| c.argument_types == types}
321
+ return constructor if constructor
322
+ raise NameError, "No constructor #{name}(#{types.join ', '})"
323
+ end
324
+
325
+ def declared_instance_methods
326
+ instance_methods.values.flatten
327
+ end
328
+
329
+ def declared_class_methods
330
+ static_methods.values.flatten
331
+ end
332
+
333
+ def declared_constructors
334
+ constructors
335
+ end
336
+
337
+ def constructors
338
+ @constructors ||= []
339
+ end
340
+
341
+ def instance_methods
342
+ @instance_methods ||= Hash.new {|h, k| h[k] = []}
343
+ end
344
+
345
+ def static_methods
346
+ @static_methods ||= Hash.new {|h, k| h[k] = []}
347
+ end
348
+
349
+ def declare_method(name, arguments, type, exceptions)
350
+ member = DubyMember.new(self, name, arguments, type, false, exceptions)
351
+ if name == 'initialize'
352
+ constructors << JavaConstructor.new(member)
353
+ else
354
+ instance_methods[name] << JavaMethod.new(member)
355
+ end
356
+ end
357
+
358
+ def declare_static_method(name, arguments, type, exceptions)
359
+ member = DubyMember.new(self, name, arguments, type, true, exceptions)
360
+ static_methods[name] << JavaStaticMethod.new(member)
361
+ end
362
+ end
363
+
364
+ class TypeDefMeta
365
+ def constructor(*args)
366
+ unmeta.constructor(*args)
367
+ end
368
+
369
+ def java_method(*args)
370
+ unmeta.java_static_method(*args)
371
+ end
372
+
373
+ def declared_instance_methods
374
+ unmeta.declared_instance_methods
375
+ end
376
+
377
+ def declared_class_methods
378
+ unmeta.declared_class_methods
379
+ end
380
+ end
381
+ end