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.
- data/History.txt +8 -0
- data/README.txt +39 -0
- data/Rakefile +13 -0
- data/bin/duby +9 -0
- data/bin/dubyc +9 -0
- data/bin/dubyp +9 -0
- data/examples/README +16 -0
- data/examples/appengine/Rakefile +72 -0
- data/examples/appengine/Readme +27 -0
- data/examples/appengine/config.ru +7 -0
- data/examples/appengine/lib/duby/plugin/datastore.rb +171 -0
- data/examples/appengine/src/com/google/appengine/ext/duby/db/Model.duby +132 -0
- data/examples/appengine/src/com/ribrdb/DubyApp.duby +28 -0
- data/examples/appengine/src/com/ribrdb/list.dhtml +15 -0
- data/examples/construction.duby +8 -0
- data/examples/edb.duby +3 -0
- data/examples/fib.duby +24 -0
- data/examples/fields.duby +22 -0
- data/examples/fractal.duby +57 -0
- data/examples/java_thing.duby +13 -0
- data/examples/simple_class.duby +12 -0
- data/examples/swing.duby +20 -0
- data/examples/tak.duby +15 -0
- data/examples/test.edb +9 -0
- data/javalib/JRubyParser.jar +0 -0
- data/lib/duby.rb +168 -0
- data/lib/duby/ast.rb +386 -0
- data/lib/duby/ast/call.rb +145 -0
- data/lib/duby/ast/class.rb +154 -0
- data/lib/duby/ast/flow.rb +332 -0
- data/lib/duby/ast/intrinsics.rb +56 -0
- data/lib/duby/ast/literal.rb +97 -0
- data/lib/duby/ast/local.rb +92 -0
- data/lib/duby/ast/method.rb +244 -0
- data/lib/duby/ast/structure.rb +62 -0
- data/lib/duby/ast/type.rb +93 -0
- data/lib/duby/c/compiler.rb +134 -0
- data/lib/duby/compiler.rb +282 -0
- data/lib/duby/jvm/compiler.rb +766 -0
- data/lib/duby/jvm/method_lookup.rb +193 -0
- data/lib/duby/jvm/source_compiler.rb +605 -0
- data/lib/duby/jvm/source_generator/builder.rb +387 -0
- data/lib/duby/jvm/source_generator/loops.rb +110 -0
- data/lib/duby/jvm/source_generator/precompile.rb +170 -0
- data/lib/duby/jvm/source_generator/typer.rb +11 -0
- data/lib/duby/jvm/typer.rb +131 -0
- data/lib/duby/jvm/types.rb +331 -0
- data/lib/duby/jvm/types/basic_types.rb +19 -0
- data/lib/duby/jvm/types/boolean.rb +11 -0
- data/lib/duby/jvm/types/enumerable.rb +63 -0
- data/lib/duby/jvm/types/factory.rb +155 -0
- data/lib/duby/jvm/types/floats.rb +70 -0
- data/lib/duby/jvm/types/integers.rb +110 -0
- data/lib/duby/jvm/types/intrinsics.rb +230 -0
- data/lib/duby/jvm/types/literals.rb +82 -0
- data/lib/duby/jvm/types/methods.rb +381 -0
- data/lib/duby/jvm/types/number.rb +92 -0
- data/lib/duby/nbcompiler.rb +29 -0
- data/lib/duby/old/compiler_old.rb +845 -0
- data/lib/duby/old/declaration.rb +72 -0
- data/lib/duby/old/mapper.rb +72 -0
- data/lib/duby/old/signature.rb +52 -0
- data/lib/duby/old/typer_old.rb +163 -0
- data/lib/duby/plugin/edb.rb +25 -0
- data/lib/duby/plugin/java.rb +42 -0
- data/lib/duby/plugin/math.rb +84 -0
- data/lib/duby/transform.rb +1028 -0
- data/lib/duby/typer.rb +369 -0
- data/test/TestUser.class +0 -0
- data/test/test_ast.rb +391 -0
- data/test/test_compilation.rb +98 -0
- data/test/test_java_typer.rb +199 -0
- data/test/test_javac_compiler.rb +58 -0
- data/test/test_jvm_compiler.rb +1770 -0
- data/test/test_math_plugin.rb +87 -0
- data/test/test_typer.rb +246 -0
- 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
|