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,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