duby 0.0.2-java → 0.0.3-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 (72) hide show
  1. data/History.txt +7 -0
  2. data/README.txt +18 -7
  3. data/Rakefile +72 -0
  4. data/examples/ant/example-build.xml +7 -0
  5. data/examples/appengine/Rakefile +8 -67
  6. data/examples/appengine/Readme +4 -3
  7. data/examples/appengine/lib/duby/appengine_tasks.rb +173 -0
  8. data/examples/appengine/lib/duby/plugin/datastore.rb +92 -31
  9. data/examples/appengine/lib/duby_task.rb +61 -0
  10. data/examples/appengine/src/com/ribrdb/DubyApp.duby +32 -6
  11. data/examples/appengine/src/com/ribrdb/list.dhtml +2 -2
  12. data/examples/appengine/{config.ru → src/config.ru} +0 -0
  13. data/examples/bintrees.duby +66 -0
  14. data/examples/dynamic.duby +17 -0
  15. data/examples/fib.duby +3 -11
  16. data/examples/fields.duby +3 -3
  17. data/examples/fractal.duby +1 -3
  18. data/examples/sort_closure.duby +7 -0
  19. data/examples/swing.duby +11 -11
  20. data/javalib/duby-bootstrap.jar +0 -0
  21. data/javalib/dynalang-invoke-0.1.jar +0 -0
  22. data/lib/duby.rb +168 -35
  23. data/lib/duby/ast.rb +224 -27
  24. data/lib/duby/ast/call.rb +85 -25
  25. data/lib/duby/ast/class.rb +112 -28
  26. data/lib/duby/ast/flow.rb +65 -44
  27. data/lib/duby/ast/intrinsics.rb +223 -21
  28. data/lib/duby/ast/literal.rb +67 -16
  29. data/lib/duby/ast/local.rb +36 -40
  30. data/lib/duby/ast/method.rb +83 -67
  31. data/lib/duby/ast/structure.rb +105 -23
  32. data/lib/duby/compiler.rb +83 -28
  33. data/lib/duby/env.rb +33 -0
  34. data/lib/duby/jvm/base.rb +210 -0
  35. data/lib/duby/jvm/compiler.rb +293 -219
  36. data/lib/duby/jvm/method_lookup.rb +77 -67
  37. data/lib/duby/jvm/source_compiler.rb +250 -157
  38. data/lib/duby/jvm/source_generator/builder.rb +53 -49
  39. data/lib/duby/jvm/source_generator/loops.rb +9 -9
  40. data/lib/duby/jvm/source_generator/precompile.rb +35 -25
  41. data/lib/duby/jvm/typer.rb +19 -10
  42. data/lib/duby/jvm/types.rb +127 -68
  43. data/lib/duby/jvm/types/basic_types.rb +26 -13
  44. data/lib/duby/jvm/types/enumerable.rb +6 -4
  45. data/lib/duby/jvm/types/factory.rb +49 -13
  46. data/lib/duby/jvm/types/floats.rb +16 -0
  47. data/lib/duby/jvm/types/integers.rb +63 -2
  48. data/lib/duby/jvm/types/intrinsics.rb +43 -21
  49. data/lib/duby/jvm/types/methods.rb +326 -86
  50. data/lib/duby/jvm/types/number.rb +3 -0
  51. data/lib/duby/nbcompiler.rb +1 -1
  52. data/lib/duby/plugin/edb.rb +1 -1
  53. data/lib/duby/plugin/java.rb +10 -1
  54. data/lib/duby/transform.rb +134 -46
  55. data/lib/duby/typer.rb +75 -50
  56. data/test/test_ast.rb +106 -106
  57. data/test/test_compilation.rb +46 -32
  58. data/test/test_env.rb +42 -0
  59. data/test/test_java_typer.rb +35 -51
  60. data/test/test_javac_compiler.rb +4 -1
  61. data/test/test_jvm_compiler.rb +564 -133
  62. data/test/test_typer.rb +68 -92
  63. metadata +37 -21
  64. data/examples/README +0 -16
  65. data/lib/duby/c/compiler.rb +0 -134
  66. data/lib/duby/old/compiler_old.rb +0 -845
  67. data/lib/duby/old/declaration.rb +0 -72
  68. data/lib/duby/old/mapper.rb +0 -72
  69. data/lib/duby/old/signature.rb +0 -52
  70. data/lib/duby/old/typer_old.rb +0 -163
  71. data/lib/duby/plugin/math.rb +0 -84
  72. data/test/test_math_plugin.rb +0 -87
@@ -7,7 +7,7 @@ module Duby::JVM::Types
7
7
  end
8
8
 
9
9
  def add_enumerable_macros
10
- add_macro('all?') do |transformer, call|
10
+ all_proc = proc do |transformer, call|
11
11
  if !call.block
12
12
  # We need to create a block that just returns the item passed to it
13
13
  # First get a new temp for the block argument
@@ -39,9 +39,10 @@ module Duby::JVM::Types
39
39
  result = Duby::AST::Body.new(call.parent, call.position)
40
40
  result << forloop << transformer.eval("#{all}", '', nil, all)
41
41
  end
42
- intrinsics['all?'][[Duby::AST.block_type]] = intrinsics['all?'][[]]
42
+ add_macro('all?', &all_proc)
43
+ add_macro('all?', Duby::AST.block_type, &all_proc)
43
44
 
44
- add_macro('any?') do |transformer, call|
45
+ any_proc = proc do |transformer, call|
45
46
  if !call.block
46
47
  var = transformer.tmp
47
48
  call.block = transformer.eval("foo {|#{var}| #{var}}").block
@@ -57,7 +58,8 @@ module Duby::JVM::Types
57
58
  result = Duby::AST::Body.new(call.parent, call.position)
58
59
  result << forloop << transformer.eval("#{any}", '', nil, any)
59
60
  end
60
- intrinsics['any?'][[Duby::AST.block_type]] = intrinsics['any?'][[]]
61
+ add_macro('any?', &any_proc)
62
+ add_macro('any?', Duby::AST.block_type, &any_proc)
61
63
  end
62
64
  end
63
65
  end
@@ -1,3 +1,4 @@
1
+ require 'jruby'
1
2
  module Duby::JVM::Types
2
3
  class TypeFactory
3
4
  BASIC_TYPES = {
@@ -19,7 +20,8 @@ module Duby::JVM::Types
19
20
  "Iterable" => Iterable,
20
21
  "void" => Void,
21
22
  "notype" => Void,
22
- "null" => Null
23
+ "null" => Null,
24
+ "dynamic" => DynamicType.new
23
25
  }.freeze
24
26
 
25
27
  attr_accessor :package
@@ -39,6 +41,8 @@ module Duby::JVM::Types
39
41
  @package = File.dirname(filename).tr('/', '.')
40
42
  @package.sub! /^\.+/, ''
41
43
  @package = nil if @package.empty?
44
+ @search_packages = [@package, 'java.lang']
45
+ @mirrors = {}
42
46
  end
43
47
 
44
48
  def define_types(builder)
@@ -48,15 +52,22 @@ module Duby::JVM::Types
48
52
  end
49
53
 
50
54
  def type(name, array=false, meta=false)
55
+ if name.kind_of?(BiteScript::ASM::Type)
56
+ if name.getDescriptor[0] == ?[
57
+ return type(name.getElementType, true, meta)
58
+ else
59
+ name = name.getClassName
60
+ end
61
+ end
51
62
  type = basic_type(name)
52
63
  type = type.meta if meta
53
64
  type = type.array_type if array
54
65
  return type
55
66
  end
56
-
67
+
57
68
  def basic_type(name)
58
69
  if name.kind_of?(Type) || name.kind_of?(NarrowingType)
59
- return name.basic_type
70
+ return name.basic_type
60
71
  end
61
72
  orig = name
62
73
  if name.kind_of? Java::JavaClass
@@ -72,18 +83,27 @@ module Duby::JVM::Types
72
83
  return @known_types[name].basic_type if @known_types[name]
73
84
  raise ArgumentError, "Bad Type #{orig}" if name =~ /Java::/
74
85
  raise ArgumentError, "Bad Type #{orig.inspect}" if name == '' || name.nil?
86
+ if name.include? '.'
87
+ alt_names = []
88
+ else
89
+ alt_names = @search_packages.map {|package| "#{package}.#{name}"}
90
+ end
75
91
  full_name = name
76
92
  begin
77
- @known_types[name] = Type.new(Java::JavaClass.for_name(full_name))
93
+ @known_types[name] = Type.new(get_mirror(full_name))
78
94
  rescue NameError
79
- unless full_name.include? '.'
80
- full_name = "java.lang.#{full_name}"
95
+ unless alt_names.empty?
96
+ full_name = alt_names.shift
81
97
  retry
82
98
  end
83
99
  raise $!
84
100
  end
85
101
  end
86
102
 
103
+ def known_type(name)
104
+ basic_type(name) rescue nil
105
+ end
106
+
87
107
  def declare_type(node)
88
108
  if node.kind_of? ::String
89
109
  name = node
@@ -92,9 +112,7 @@ module Duby::JVM::Types
92
112
  name = node.name
93
113
  end
94
114
 
95
- if Duby::AST::InterfaceDeclaration === node
96
- @known_types[name] = InterfaceDefinition.new(name, node)
97
- elsif @known_types.include? name
115
+ if @known_types.include? name
98
116
  existing = @known_types[name]
99
117
  existing.node ||= node
100
118
  existing
@@ -103,26 +121,44 @@ module Duby::JVM::Types
103
121
  if !name.include?('.') && package
104
122
  full_name = "#{package}.#{name}"
105
123
  end
106
- @known_types[full_name] = TypeDefinition.new(full_name, node)
124
+ if Duby::AST::InterfaceDeclaration === node
125
+ klass = InterfaceDefinition
126
+ else
127
+ klass = TypeDefinition
128
+ end
129
+ @known_types[full_name] = klass.new(full_name, node)
107
130
  @known_types[name] = @known_types[full_name]
108
131
  end
109
132
  end
110
133
 
111
134
  def alias(from, to)
112
- @known_types[from] = type(to)
135
+ if from == '*'
136
+ @search_packages << to.sub(".*", "")
137
+ else
138
+ @known_types[from] = type(to)
139
+ end
113
140
  end
114
141
 
115
142
  def no_type
116
143
  Void
117
144
  end
118
-
145
+
119
146
  def fixnum(parent, line_number, literal)
120
147
  FixnumLiteralNode.new(parent, line_number, literal)
121
148
  end
122
-
149
+
123
150
  def float(parent, line_number, literal)
124
151
  FloatLiteralNode.new(parent, line_number, literal)
125
152
  end
153
+
154
+ def get_mirror(name)
155
+ @mirrors[name] ||= begin
156
+ classname = name.tr('.', '/') + ".class"
157
+ stream = JRuby.runtime.jruby_class_loader.getResourceAsStream(classname)
158
+ raise NameError, "Class '#{name}' not found." unless stream
159
+ BiteScript::ASM::ClassMirror.load(stream)
160
+ end
161
+ end
126
162
  end
127
163
 
128
164
  class FixnumLiteralNode < AST::Fixnum
@@ -3,6 +3,14 @@ module Duby::JVM::Types
3
3
  def prefix
4
4
  'f'
5
5
  end
6
+
7
+ def math_type
8
+ Float
9
+ end
10
+
11
+ def box_type
12
+ java.lang.Float
13
+ end
6
14
 
7
15
  def suffix
8
16
  'g'
@@ -42,6 +50,14 @@ module Duby::JVM::Types
42
50
  'd'
43
51
  end
44
52
 
53
+ def math_type
54
+ Double
55
+ end
56
+
57
+ def box_type
58
+ java.lang.Double
59
+ end
60
+
45
61
  def wide?
46
62
  true
47
63
  end
@@ -50,10 +50,49 @@ module Duby::JVM::Types
50
50
  Int
51
51
  end
52
52
 
53
+ def box_type
54
+ java.lang.Integer
55
+ end
56
+
53
57
  def jump_if(builder, op, label)
54
58
  builder.send "if_icmp#{op}", label
55
59
  end
56
60
 
61
+ def build_loop(parent, position, duby, block, first_value,
62
+ last_value, ascending, inclusive)
63
+ if ascending
64
+ comparison = "<"
65
+ op = "+="
66
+ else
67
+ comparison = ">"
68
+ op = "-="
69
+ end
70
+ comparison << "=" if inclusive
71
+ forloop = Duby::AST::Loop.new(parent, position, true, false) do |forloop|
72
+ first, last = duby.tmp, duby.tmp
73
+ init = duby.eval("#{first} = 0; #{last} = 0;")
74
+ init.children[-2].value = first_value
75
+ init.children[-1].value = last_value
76
+ forloop.init << init
77
+
78
+ var = (block.args.args || [])[0]
79
+ if var
80
+ forloop.pre << duby.eval(
81
+ "#{var.name} = #{first}", '', forloop, first, last)
82
+ end
83
+ forloop.post << duby.eval("#{first} #{op} 1")
84
+ [
85
+ Duby::AST::Condition.new(forloop, position) do |c|
86
+ [duby.eval("#{first} #{comparison} #{last}",
87
+ '', forloop, first, last)]
88
+ end,
89
+ nil
90
+ ]
91
+ end
92
+ forloop.body = block.body
93
+ forloop
94
+ end
95
+
57
96
  def add_intrinsics
58
97
  super
59
98
  math_operator('<<', 'shl')
@@ -63,14 +102,36 @@ module Duby::JVM::Types
63
102
  math_operator('&', 'and')
64
103
  math_operator('^', 'xor')
65
104
  unary_operator('~', 'not')
105
+
106
+ add_macro('downto', Int, Duby::AST.block_type) do |transformer, call|
107
+ build_loop(call.parent, call.position, transformer,
108
+ call.block, call.target, call.parameters[0], false, true)
109
+ end
110
+ add_macro('upto', Int, Duby::AST.block_type) do |transformer, call|
111
+ build_loop(call.parent, call.position, transformer,
112
+ call.block, call.target, call.parameters[0], true, true)
113
+ end
114
+ add_macro('times', Duby::AST.block_type) do |transformer, call|
115
+ build_loop(call.parent, call.position, transformer,
116
+ call.block, Duby::AST::fixnum(nil, call.position, 0),
117
+ call.target, true, false)
118
+ end
66
119
  end
67
120
  end
68
-
121
+
69
122
  class LongType < Number
70
123
  def prefix
71
124
  'l'
72
125
  end
73
126
 
127
+ def math_type
128
+ Long
129
+ end
130
+
131
+ def box_type
132
+ java.lang.Long
133
+ end
134
+
74
135
  def literal(builder, value)
75
136
  builder.ldc_long(value)
76
137
  end
@@ -107,4 +168,4 @@ module Duby::JVM::Types
107
168
  unary_operator('~', 'not')
108
169
  end
109
170
  end
110
- end
171
+ end
@@ -20,19 +20,19 @@ module Duby::JVM::Types
20
20
  def load(builder, index)
21
21
  builder.send "#{prefix}load", index
22
22
  end
23
-
23
+
24
24
  def store(builder, index)
25
25
  builder.send "#{prefix}store", index
26
26
  end
27
-
27
+
28
28
  def return(builder)
29
29
  builder.send "#{prefix}return"
30
30
  end
31
-
31
+
32
32
  def init_value(builder)
33
33
  builder.aconst_null
34
34
  end
35
-
35
+
36
36
  def intrinsics
37
37
  @intrinsics ||= begin
38
38
  @intrinsics = Hash.new {|h, k| h[k] = {}}
@@ -40,7 +40,7 @@ module Duby::JVM::Types
40
40
  @intrinsics
41
41
  end
42
42
  end
43
-
43
+
44
44
  def add_method(name, args, method_or_type=nil, &block)
45
45
  if block_given?
46
46
  method_or_type = Intrinsic.new(self, name, args,
@@ -56,15 +56,20 @@ module Duby::JVM::Types
56
56
  end
57
57
  end
58
58
 
59
- def declared_intrinsics
59
+ def declared_intrinsics(name=nil)
60
60
  methods = []
61
- intrinsics.each do |name, group|
61
+ all_intrinsics = if name.nil?
62
+ intrinsics
63
+ else
64
+ [[name, intrinsics[name]]]
65
+ end
66
+ all_intrinsics.each do |name, group|
62
67
  group.each do |args, method|
63
68
  methods << method
64
69
  end
65
70
  end
66
71
  interfaces.each do |interface|
67
- methods.concat(interface.declared_intrinsics)
72
+ methods.concat(interface.declared_intrinsics(name))
68
73
  end
69
74
  methods
70
75
  end
@@ -78,7 +83,7 @@ module Duby::JVM::Types
78
83
  end
79
84
  end
80
85
  end
81
-
86
+
82
87
  add_method('==', [Object], Boolean) do |compiler, call, expression|
83
88
  # Should this call Object.equals for consistency with Ruby?
84
89
  if expression
@@ -89,7 +94,7 @@ module Duby::JVM::Types
89
94
  end
90
95
  end
91
96
  end
92
-
97
+
93
98
  add_method('!=', [Object], Boolean) do |compiler, call, expression|
94
99
  # Should this call Object.equals for consistency with Ruby?
95
100
  if expression
@@ -102,7 +107,7 @@ module Duby::JVM::Types
102
107
  end
103
108
  end
104
109
  end
105
-
110
+
106
111
  class ArrayType
107
112
  def add_intrinsics
108
113
  super
@@ -119,7 +124,7 @@ module Duby::JVM::Types
119
124
 
120
125
  add_method('[]=',
121
126
  [Int, component_type],
122
- component_type) do |compiler, call, expression|
127
+ component_type) do |compiler, call, expression|
123
128
  call.target.compile(compiler, true)
124
129
  convert_args(compiler, call.parameters, [Int, component_type])
125
130
  component_type.astore(compiler.method)
@@ -127,24 +132,24 @@ module Duby::JVM::Types
127
132
  call.parameters[1].compile(compiler, true)
128
133
  end
129
134
  end
130
-
135
+
131
136
  add_method('length', [], Int) do |compiler, call, expression|
132
137
  call.target.compile(compiler, true)
133
- compiler.method.arraylength
138
+ compiler.method.arraylength
134
139
  end
135
-
140
+
136
141
  add_macro('each', Duby::AST.block_type) do |transformer, call|
137
142
  Duby::AST::Loop.new(call.parent,
138
143
  call.position, true, false) do |forloop|
139
144
  index = transformer.tmp
140
145
  array = transformer.tmp
141
-
146
+
142
147
  init = transformer.eval("#{index} = 0;#{array} = nil")
143
148
  array_assignment = init.children[-1]
144
149
  array_assignment.value = call.target
145
150
  call.target.parent = array_assignment
146
151
  forloop.init << init
147
-
152
+
148
153
  var = call.block.args.args[0]
149
154
  if var
150
155
  forloop.pre << transformer.eval(
@@ -163,7 +168,7 @@ module Duby::JVM::Types
163
168
  end
164
169
  end
165
170
  end
166
-
171
+
167
172
  class StringType < Type
168
173
  def add_intrinsics
169
174
  super
@@ -188,6 +193,23 @@ module Duby::JVM::Types
188
193
  compiler.method.invokevirtual String, "concat", [String, String]
189
194
  end
190
195
  end
196
+ add_method('[]', [Int], Char) do |compiler, call, expression|
197
+ if expression
198
+ call.target.compile(compiler, true)
199
+ call.parameters[0].compile(compiler, true)
200
+ compiler.method.invokevirtual String, "charAt", [Char, Int]
201
+ end
202
+ end
203
+ add_method('[]', [Int, Int], String) do |compiler, call, expression|
204
+ if expression
205
+ call.target.compile(compiler, true)
206
+ call.parameters[0].compile(compiler, true)
207
+ compiler.method.dup
208
+ call.parameters[1].compile(compiler, true)
209
+ compiler.method.iadd
210
+ compiler.method.invokevirtual String, "substring", [String, Int, Int]
211
+ end
212
+ end
191
213
  end
192
214
  end
193
215
 
@@ -199,12 +221,12 @@ module Duby::JVM::Types
199
221
  Duby::AST::Loop.new(call.parent,
200
222
  call.position, true, false) do |forloop|
201
223
  it = transformer.tmp
202
-
224
+
203
225
  assignment = transformer.eval("#{it} = foo.iterator")
204
226
  assignment.value.target = call.target
205
227
  call.target.parent = assignment.value
206
228
  forloop.init << assignment
207
-
229
+
208
230
  var = call.block.args.args[0]
209
231
  if var
210
232
  forloop.pre << transformer.eval(
@@ -221,7 +243,7 @@ module Duby::JVM::Types
221
243
  end
222
244
  end
223
245
  end
224
-
246
+
225
247
  class PrimitiveType
226
248
  # Primitives define their own intrinsics instead of getting the Object ones.
227
249
  def add_intrinsics