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,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,344 @@
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
+ end
173
+
174
+ class JavaStaticMethod < JavaMethod
175
+ def return_type
176
+ @return_type ||= begin
177
+ if @member.return_type
178
+ AST.type(@member.return_type)
179
+ else
180
+ Void
181
+ end
182
+ end
183
+ end
184
+
185
+ def call(compiler, ast, expression)
186
+ target = ast.target.inferred_type
187
+ convert_args(compiler, ast.parameters)
188
+ compiler.method.invokestatic(
189
+ target,
190
+ name,
191
+ [@member.return_type, *@member.argument_types])
192
+ # if expression, void static methods return null, for consistency
193
+ # TODO: inference phase needs to track that signature is void
194
+ # but actual type is null object
195
+ compiler.method.aconst_null if expression && void?
196
+ compiler.method.pop unless expression || void?
197
+ end
198
+ end
199
+
200
+ class DubyMember
201
+ attr_reader :name, :argument_types, :declaring_class, :return_type
202
+ attr_reader :exception_types
203
+
204
+ def initialize(klass, name, args, return_type, static, exceptions)
205
+ if return_type == Void
206
+ return_type = nil
207
+ end
208
+ @declaring_class = klass
209
+ @name = name
210
+ @argument_types = args
211
+ @return_type = return_type
212
+ @static = static
213
+ @exception_types = exceptions || []
214
+ end
215
+
216
+ def static?
217
+ @static
218
+ end
219
+ end
220
+
221
+ class Type
222
+ def get_method(name, args)
223
+ method = find_method(self, name, args, meta?)
224
+ unless method
225
+ # Allow constant narrowing for assignment methods
226
+ if name =~ /=$/ && args[-1].respond_to?(:narrow!)
227
+ if args[-1].narrow!
228
+ method = find_method(self, name, args, meta?)
229
+ end
230
+ end
231
+ end
232
+ method
233
+ end
234
+
235
+ def constructor(*types)
236
+ types = types.map {|type| type.jvm_type}
237
+ constructor = (jvm_type.constructor(*types) rescue nil)
238
+ return JavaConstructor.new(constructor) if constructor
239
+ raise NameError, "No constructor #{name}(#{types.join ', '})"
240
+ end
241
+
242
+ def java_method(name, *types)
243
+ intrinsic = intrinsics[name][types]
244
+ return intrinsic if intrinsic
245
+ types = types.map {|type| type.jvm_type}
246
+ method = (jvm_type.java_method(name, *types) rescue nil)
247
+ if method && method.static? == meta?
248
+ return JavaStaticMethod.new(method) if method.static?
249
+ return JavaMethod.new(method)
250
+ end
251
+ raise NameError, "No method #{self.name}.#{name}(#{types.join ', '})"
252
+ end
253
+
254
+ def declared_instance_methods
255
+ if jvm_type && !array?
256
+ methods = jvm_type.declared_instance_methods.map do |method|
257
+ JavaMethod.new(method)
258
+ end
259
+ else
260
+ methods = []
261
+ end
262
+ methods.concat((meta? ? unmeta : self).declared_intrinsics)
263
+ end
264
+
265
+ def declared_class_methods
266
+ methods = jvm_type.declared_class_methods.map do |method|
267
+ JavaStaticMethod.new(method)
268
+ end
269
+ methods.concat(meta.declared_intrinsics)
270
+ end
271
+ end
272
+
273
+ class TypeDefinition
274
+ def java_method(name, *types)
275
+ method = instance_methods[name].find {|m| m.argument_types == types}
276
+ return method if method
277
+ raise NameError, "No method #{self.name}.#{name}(#{types.join ', '})"
278
+ end
279
+
280
+ def java_static_method(name, *types)
281
+ method = static_methods[name].find {|m| m.argument_types == types}
282
+ return method if method
283
+ raise NameError, "No method #{self.name}.#{name}(#{types.join ', '})"
284
+ end
285
+
286
+ def constructor(*types)
287
+ constructor = constructors.find {|c| c.argument_types == types}
288
+ return constructor if constructor
289
+ raise NameError, "No constructo #{name}(#{types.join ', '})"
290
+ end
291
+
292
+ def declared_instance_methods
293
+ instance_methods.values.flatten
294
+ end
295
+
296
+ def declared_class_methods
297
+ static_methods.values.flatten
298
+ end
299
+
300
+ def constructors
301
+ @constructors ||= []
302
+ end
303
+
304
+ def instance_methods
305
+ @instance_methods ||= Hash.new {|h, k| h[k] = []}
306
+ end
307
+
308
+ def static_methods
309
+ @static_methods ||= Hash.new {|h, k| h[k] = []}
310
+ end
311
+
312
+ def declare_method(name, arguments, type, exceptions)
313
+ member = DubyMember.new(self, name, arguments, type, false, exceptions)
314
+ if name == 'initialize'
315
+ constructors << JavaConstructor.new(member)
316
+ else
317
+ instance_methods[name] << JavaMethod.new(member)
318
+ end
319
+ end
320
+
321
+ def declare_static_method(name, arguments, type, exceptions)
322
+ member = DubyMember.new(self, name, arguments, type, true, exceptions)
323
+ static_methods[name] << JavaStaticMethod.new(member)
324
+ end
325
+ end
326
+
327
+ class TypeDefMeta
328
+ def constructor(*args)
329
+ unmeta.constructor(*args)
330
+ end
331
+
332
+ def java_method(*args)
333
+ unmeta.java_static_method(*args)
334
+ end
335
+
336
+ def declared_instance_methods
337
+ unmeta.declared_instance_methods
338
+ end
339
+
340
+ def declared_class_methods
341
+ unmeta.declared_class_methods
342
+ end
343
+ end
344
+ end
@@ -0,0 +1,92 @@
1
+ module Duby::JVM::Types
2
+ class Number < PrimitiveType
3
+ # The type returned by arithmetic operations with this type.
4
+ def math_type
5
+ self
6
+ end
7
+
8
+ def suffix
9
+ ''
10
+ end
11
+
12
+ # Adds an intrinsic that delegates to an intrinsic in another primitive
13
+ # type. That type must support promoting the "this" argument.
14
+ def delegate_intrinsic(name, type, return_type)
15
+ args = [type]
16
+ delegate = type.intrinsics[name][args]
17
+ add_method(name, args, return_type) do |compiler, call, expression|
18
+ if expression
19
+ delegate.call(compiler, call, expression)
20
+ end
21
+ end
22
+ end
23
+
24
+ def add_delegates(name, return_type = nil)
25
+ index = TYPE_ORDERING.index(math_type)
26
+ larger_types = TYPE_ORDERING[index + 1, TYPE_ORDERING.size]
27
+ larger_types.each do |type|
28
+ delegate_intrinsic(name, return_type || type, return_type || type)
29
+ end
30
+ end
31
+
32
+ # if_cmpxx for non-ints
33
+ def jump_if(builder, op, label)
34
+ builder.send "#{prefix}cmp#{suffix}"
35
+ builder.send "if#{op}", label
36
+ end
37
+
38
+ def boolean_operator(name, op)
39
+ add_method(name, [math_type], Boolean) do |compiler, call, expression|
40
+ if expression
41
+ # Promote the target or the argument if necessary
42
+ convert_args(compiler,
43
+ [call.target, *call.parameters],
44
+ [math_type, math_type])
45
+ compiler.method.op_to_bool do |label|
46
+ jump_if(compiler.method, op, label)
47
+ end
48
+ end
49
+ end
50
+ add_delegates(name, Boolean)
51
+ end
52
+
53
+ def math_operator(name, op)
54
+ add_method(name, [math_type], math_type) do |compiler, call, expression|
55
+ if expression
56
+ # Promote the target or the argument if necessary
57
+ convert_args(compiler,
58
+ [call.target, *call.parameters],
59
+ [math_type, math_type])
60
+ compiler.method.send "#{prefix}#{op}"
61
+ end
62
+ end
63
+ add_delegates(name)
64
+ end
65
+
66
+ def unary_operator(name, op)
67
+ add_method(name, [], math_type) do |compiler, call, expression|
68
+ if expression
69
+ call.target.compile(compiler, true)
70
+ compiler.method.send("#{prefix}#{op}") if op
71
+ end
72
+ end
73
+ end
74
+
75
+ def add_intrinsics
76
+ boolean_operator('<', :lt)
77
+ boolean_operator('<=', :le)
78
+ boolean_operator('==', :eq)
79
+ boolean_operator('!=', :ne)
80
+ boolean_operator('>=', :ge)
81
+ boolean_operator('>', :gt)
82
+ math_operator('+', :add)
83
+ math_operator('-', :sub)
84
+ math_operator('*', :mul)
85
+ math_operator('/', :div)
86
+ math_operator('%', :rem)
87
+ unary_operator('-@', :neg)
88
+ unary_operator('+@', nil)
89
+ end
90
+
91
+ end
92
+ end