mirah 0.0.4-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (141) hide show
  1. data/History.txt +15 -0
  2. data/README.txt +51 -0
  3. data/Rakefile +86 -0
  4. data/bin/duby +10 -0
  5. data/bin/dubyc +10 -0
  6. data/bin/dubyp +10 -0
  7. data/bin/jrubyp +36 -0
  8. data/bin/mirah +9 -0
  9. data/bin/mirah.cmd +1 -0
  10. data/bin/mirahc +9 -0
  11. data/bin/mirahc.cmd +1 -0
  12. data/bin/mirahp +9 -0
  13. data/bin/mirahp.cmd +1 -0
  14. data/examples/ant/example-build.xml +7 -0
  15. data/examples/appengine/Rakefile +19 -0
  16. data/examples/appengine/Readme +29 -0
  17. data/examples/appengine/src/org/mirah/MirahApp.mirah +57 -0
  18. data/examples/appengine/src/org/mirah/list.dhtml +15 -0
  19. data/examples/appengine/war/WEB-INF/lib/dubydatastore.jar +0 -0
  20. data/examples/bintrees.mirah +66 -0
  21. data/examples/construction.mirah +8 -0
  22. data/examples/dynamic.mirah +17 -0
  23. data/examples/edb.mirah +3 -0
  24. data/examples/fib.mirah +16 -0
  25. data/examples/fields.mirah +22 -0
  26. data/examples/fractal.mirah +55 -0
  27. data/examples/java_thing.mirah +13 -0
  28. data/examples/plugins/appengine/Rakefile +55 -0
  29. data/examples/plugins/appengine/lib/com/google/appengine/ext/duby/db/datastore.rb +375 -0
  30. data/examples/plugins/appengine/src/com/google/appengine/ext/duby/db/Model.duby +336 -0
  31. data/examples/plugins/appengine/test/com/google/appengine/ext/duby/db/ModelTest.duby +113 -0
  32. data/examples/simple_class.mirah +12 -0
  33. data/examples/sort_closure.mirah +7 -0
  34. data/examples/swing.mirah +20 -0
  35. data/examples/tak.mirah +15 -0
  36. data/examples/test.edb +9 -0
  37. data/examples/wiki/Rakefile +18 -0
  38. data/examples/wiki/src/org/mirah/wiki/MirahWiki.duby +324 -0
  39. data/examples/wiki/src/org/mirah/wiki/edit.eduby.html +42 -0
  40. data/examples/wiki/src/org/mirah/wiki/error.eduby.html +2 -0
  41. data/examples/wiki/src/org/mirah/wiki/layout.eduby.html +69 -0
  42. data/examples/wiki/src/org/mirah/wiki/parser.eduby.html +7 -0
  43. data/examples/wiki/src/org/mirah/wiki/view.eduby.html +15 -0
  44. data/examples/wiki/war/WEB-INF/classes/test/HeredocContext.class +0 -0
  45. data/examples/wiki/war/WEB-INF/classes/test/MirahParser.class +0 -0
  46. data/examples/wiki/war/WEB-INF/lib/appengine-api.jar +0 -0
  47. data/examples/wiki/war/WEB-INF/lib/dubydatastore.jar +0 -0
  48. data/examples/wiki/war/WEB-INF/lib/jmeta-runtime.jar +0 -0
  49. data/examples/wiki/war/WEB-INF/lib/pegdown-stubs.jar +0 -0
  50. data/examples/wiki/war/WEB-INF/pegdown.jar +0 -0
  51. data/examples/wiki/war/app.yaml +21 -0
  52. data/examples/wiki/war/public/favicon.ico +0 -0
  53. data/examples/wiki/war/public/images/appengine_duby.png +0 -0
  54. data/examples/wiki/war/public/images/back.gif +0 -0
  55. data/examples/wiki/war/public/images/dir.gif +0 -0
  56. data/examples/wiki/war/public/images/file.gif +0 -0
  57. data/examples/wiki/war/public/javascripts/prettify.js +61 -0
  58. data/examples/wiki/war/public/robots.txt +0 -0
  59. data/examples/wiki/war/public/stylesheets/main.css +156 -0
  60. data/examples/wiki/war/public/stylesheets/prettify.css +1 -0
  61. data/examples/wiki/war/public/stylesheets/sh_style.css +66 -0
  62. data/examples/wiki/war/public/stylesheets/source.css +21 -0
  63. data/examples/wiki/war/public/wmd/images/bg-fill.png +0 -0
  64. data/examples/wiki/war/public/wmd/images/bg.png +0 -0
  65. data/examples/wiki/war/public/wmd/images/blockquote.png +0 -0
  66. data/examples/wiki/war/public/wmd/images/bold.png +0 -0
  67. data/examples/wiki/war/public/wmd/images/code.png +0 -0
  68. data/examples/wiki/war/public/wmd/images/h1.png +0 -0
  69. data/examples/wiki/war/public/wmd/images/hr.png +0 -0
  70. data/examples/wiki/war/public/wmd/images/img.png +0 -0
  71. data/examples/wiki/war/public/wmd/images/italic.png +0 -0
  72. data/examples/wiki/war/public/wmd/images/link.png +0 -0
  73. data/examples/wiki/war/public/wmd/images/ol.png +0 -0
  74. data/examples/wiki/war/public/wmd/images/redo.png +0 -0
  75. data/examples/wiki/war/public/wmd/images/separator.png +0 -0
  76. data/examples/wiki/war/public/wmd/images/ul.png +0 -0
  77. data/examples/wiki/war/public/wmd/images/undo.png +0 -0
  78. data/examples/wiki/war/public/wmd/images/wmd-on.png +0 -0
  79. data/examples/wiki/war/public/wmd/images/wmd.png +0 -0
  80. data/examples/wiki/war/public/wmd/showdown.js +421 -0
  81. data/examples/wiki/war/public/wmd/wmd-base.js +1799 -0
  82. data/examples/wiki/war/public/wmd/wmd-plus.js +311 -0
  83. data/examples/wiki/war/public/wmd/wmd.js +73 -0
  84. data/javalib/JRubyParser.jar +0 -0
  85. data/javalib/dynalang-invoke-0.1.jar +0 -0
  86. data/javalib/mirah-bootstrap.jar +0 -0
  87. data/javalib/mirah-parser.jar +0 -0
  88. data/lib/duby.rb +2 -0
  89. data/lib/mirah.rb +338 -0
  90. data/lib/mirah/appengine_tasks.rb +146 -0
  91. data/lib/mirah/ast.rb +615 -0
  92. data/lib/mirah/ast/call.rb +307 -0
  93. data/lib/mirah/ast/class.rb +311 -0
  94. data/lib/mirah/ast/flow.rb +364 -0
  95. data/lib/mirah/ast/intrinsics.rb +470 -0
  96. data/lib/mirah/ast/literal.rb +154 -0
  97. data/lib/mirah/ast/local.rb +89 -0
  98. data/lib/mirah/ast/method.rb +360 -0
  99. data/lib/mirah/ast/scope.rb +208 -0
  100. data/lib/mirah/ast/structure.rb +226 -0
  101. data/lib/mirah/ast/type.rb +130 -0
  102. data/lib/mirah/compiler.rb +341 -0
  103. data/lib/mirah/env.rb +33 -0
  104. data/lib/mirah/jvm/base.rb +258 -0
  105. data/lib/mirah/jvm/compiler.rb +885 -0
  106. data/lib/mirah/jvm/method_lookup.rb +203 -0
  107. data/lib/mirah/jvm/source_compiler.rb +737 -0
  108. data/lib/mirah/jvm/source_generator/builder.rb +444 -0
  109. data/lib/mirah/jvm/source_generator/loops.rb +110 -0
  110. data/lib/mirah/jvm/source_generator/precompile.rb +188 -0
  111. data/lib/mirah/jvm/source_generator/typer.rb +11 -0
  112. data/lib/mirah/jvm/typer.rb +151 -0
  113. data/lib/mirah/jvm/types.rb +416 -0
  114. data/lib/mirah/jvm/types/basic_types.rb +33 -0
  115. data/lib/mirah/jvm/types/boolean.rb +17 -0
  116. data/lib/mirah/jvm/types/enumerable.rb +65 -0
  117. data/lib/mirah/jvm/types/extensions.rb +86 -0
  118. data/lib/mirah/jvm/types/factory.rb +186 -0
  119. data/lib/mirah/jvm/types/floats.rb +86 -0
  120. data/lib/mirah/jvm/types/integers.rb +171 -0
  121. data/lib/mirah/jvm/types/intrinsics.rb +376 -0
  122. data/lib/mirah/jvm/types/literals.rb +74 -0
  123. data/lib/mirah/jvm/types/methods.rb +614 -0
  124. data/lib/mirah/jvm/types/number.rb +143 -0
  125. data/lib/mirah/nbcompiler.rb +29 -0
  126. data/lib/mirah/plugin/edb.rb +29 -0
  127. data/lib/mirah/plugin/gwt.rb +173 -0
  128. data/lib/mirah/plugin/java.rb +55 -0
  129. data/lib/mirah/transform.rb +266 -0
  130. data/lib/mirah/transform2.rb +728 -0
  131. data/lib/mirah/typer.rb +407 -0
  132. data/lib/mirah_task.rb +107 -0
  133. data/test/test_ast.rb +359 -0
  134. data/test/test_compilation.rb +112 -0
  135. data/test/test_env.rb +42 -0
  136. data/test/test_gwt.rb +58 -0
  137. data/test/test_java_typer.rb +183 -0
  138. data/test/test_javac_compiler.rb +63 -0
  139. data/test/test_jvm_compiler.rb +2607 -0
  140. data/test/test_typer.rb +221 -0
  141. metadata +235 -0
@@ -0,0 +1,171 @@
1
+ class BiteScript::MethodBuilder
2
+ def inot
3
+ iconst_m1
4
+ ixor
5
+ end
6
+
7
+ def lnot
8
+ # TODO would any of these be faster?
9
+ # iconst_m1; i2l
10
+ # lconst_1; lneg
11
+ ldc_long(-1)
12
+ ixor
13
+ end
14
+ end
15
+
16
+ module Duby::JVM::Types
17
+ class IntegerType < Number
18
+ def literal(builder, value)
19
+ builder.push_int(value)
20
+ end
21
+
22
+ def init_value(builder)
23
+ builder.iconst_0
24
+ end
25
+
26
+ def load(builder, index)
27
+ builder.iload(index)
28
+ end
29
+
30
+ def widen(builder, type)
31
+ case type
32
+ when Byte, Short, Int
33
+ # do nothing
34
+ when Long
35
+ builder.i2l
36
+ when Float
37
+ builder.i2f
38
+ when Double
39
+ builder.i2d
40
+ else
41
+ raise ArgumentError, "Invalid widening conversion from #{name} to #{type}"
42
+ end
43
+ end
44
+
45
+ def prefix
46
+ 'i'
47
+ end
48
+
49
+ def math_type
50
+ Int
51
+ end
52
+
53
+ def box_type
54
+ java.lang.Integer
55
+ end
56
+
57
+ def jump_if(builder, op, label)
58
+ builder.send "if_icmp#{op}", label
59
+ end
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
+
96
+ def add_intrinsics
97
+ super
98
+ math_operator('<<', 'shl')
99
+ math_operator('>>', 'shr')
100
+ math_operator('>>>', 'ushr')
101
+ math_operator('|', 'or')
102
+ math_operator('&', 'and')
103
+ math_operator('^', 'xor')
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
119
+ end
120
+ end
121
+
122
+ class LongType < Number
123
+ def prefix
124
+ 'l'
125
+ end
126
+
127
+ def math_type
128
+ Long
129
+ end
130
+
131
+ def box_type
132
+ java.lang.Long
133
+ end
134
+
135
+ def literal(builder, value)
136
+ builder.ldc_long(value)
137
+ end
138
+
139
+ def init_value(builder)
140
+ builder.lconst_0
141
+ end
142
+
143
+ def wide?
144
+ true
145
+ end
146
+
147
+ def widen(builder, type)
148
+ case type
149
+ when Long
150
+ # do nothing
151
+ when Float
152
+ builder.l2f
153
+ when Double
154
+ builder.l2d
155
+ else
156
+ raise ArgumentError, "Invalid widening conversion from Int to #{type}"
157
+ end
158
+ end
159
+
160
+ def add_intrinsics
161
+ super
162
+ math_operator('<<', 'shl')
163
+ math_operator('>>', 'shr')
164
+ math_operator('>>>', 'ushr')
165
+ math_operator('|', 'or')
166
+ math_operator('&', 'and')
167
+ math_operator('^', 'xor')
168
+ unary_operator('~', 'not')
169
+ end
170
+ end
171
+ end
@@ -0,0 +1,376 @@
1
+ require 'bitescript'
2
+ require 'mirah/jvm/types/enumerable'
3
+
4
+ class BiteScript::MethodBuilder
5
+ def op_to_bool
6
+ done_label = label
7
+ true_label = label
8
+
9
+ yield(true_label)
10
+ iconst_0
11
+ goto(done_label)
12
+ true_label.set!
13
+ iconst_1
14
+ done_label.set!
15
+ end
16
+ end
17
+
18
+ module Duby::JVM::Types
19
+ class Type
20
+
21
+ def load(builder, index)
22
+ builder.send "#{prefix}load", index
23
+ end
24
+
25
+ def store(builder, index)
26
+ builder.send "#{prefix}store", index
27
+ end
28
+
29
+ def return(builder)
30
+ builder.send "#{prefix}return"
31
+ end
32
+
33
+ def init_value(builder)
34
+ builder.aconst_null
35
+ end
36
+
37
+ def intrinsics
38
+ @intrinsics ||= begin
39
+ @intrinsics = Hash.new {|h, k| h[k] = {}}
40
+ add_intrinsics
41
+ @intrinsics
42
+ end
43
+ end
44
+
45
+ def add_method(name, args, method_or_type=nil, &block)
46
+ if block_given?
47
+ method_or_type = Intrinsic.new(self, name, args,
48
+ method_or_type, &block)
49
+ end
50
+ intrinsics[name][args] = method_or_type
51
+ end
52
+
53
+ def add_macro(name, *args, &block)
54
+ type = Duby::AST::InlineCode.new(&block)
55
+ intrinsics[name][args] = Intrinsic.new(self, name, args, type) do
56
+ raise "Macro should be expanded, no called!"
57
+ end
58
+ end
59
+
60
+ def add_compiled_macro(klass, name, arg_types)
61
+ add_macro(name, *arg_types) do |duby, call|
62
+ expander = klass.constructors[0].newInstance(duby, call)
63
+ ast = expander.expand
64
+ if ast
65
+ if call.target
66
+ body = Duby::AST::ScopedBody.new(call.parent, call.position)
67
+ body.static_scope.self_type = call.target.inferred_type!
68
+ body.static_scope.self_node = call.target
69
+ body << ast
70
+ body
71
+ else
72
+ ast
73
+ end
74
+ else
75
+ Duby::AST::Noop.new(call.parent, call.position)
76
+ end
77
+ end
78
+ end
79
+
80
+ def declared_intrinsics(name=nil)
81
+ methods = []
82
+ all_intrinsics = if name.nil?
83
+ intrinsics
84
+ else
85
+ [[name, intrinsics[name]]]
86
+ end
87
+ all_intrinsics.each do |name, group|
88
+ group.each do |args, method|
89
+ methods << method
90
+ end
91
+ end
92
+ interfaces.each do |interface|
93
+ methods.concat(interface.declared_intrinsics(name))
94
+ end
95
+ methods
96
+ end
97
+
98
+ def load_extensions(klass=nil)
99
+ mirror = nil
100
+ if klass
101
+ factory = Duby::AST.type_factory
102
+ mirror = factory.get_mirror(klass.getName)
103
+ elsif jvm_type
104
+ mirror = jvm_type
105
+ end
106
+ if mirror
107
+ extensions = mirror.getDeclaredAnnotation('duby.anno.Extensions')
108
+ return self if extensions.nil?
109
+ macros = extensions['macros']
110
+ return self if macros.nil?
111
+ macros.each do |macro|
112
+ macro_name = macro['name']
113
+ class_name = macro['class']
114
+ types = BiteScript::ASM::Type.get_argument_types(macro['signature'])
115
+ args = types.map do |type|
116
+ if type.class_name == 'duby.lang.compiler.Block'
117
+ Duby::AST::TypeReference::BlockType
118
+ else
119
+ Duby::AST.type(nil, type)
120
+ end
121
+ end
122
+ klass = JRuby.runtime.jruby_class_loader.loadClass(class_name)
123
+ add_compiled_macro(klass, macro_name, args)
124
+ end
125
+ end
126
+ self
127
+ end
128
+
129
+ def add_intrinsics
130
+ add_method('nil?', [], Boolean) do |compiler, call, expression|
131
+ if expression
132
+ call.target.compile(compiler, true)
133
+ compiler.method.op_to_bool do |target|
134
+ compiler.method.ifnull(target)
135
+ end
136
+ end
137
+ end
138
+
139
+ add_method('==', [Object], Boolean) do |compiler, call, expression|
140
+ # Should this call Object.equals for consistency with Ruby?
141
+ if expression
142
+ call.target.compile(compiler, true)
143
+ call.parameters[0].compile(compiler, true)
144
+ compiler.method.op_to_bool do |target|
145
+ compiler.method.if_acmpeq(target)
146
+ end
147
+ end
148
+ end
149
+
150
+ add_method('!=', [Object], Boolean) do |compiler, call, expression|
151
+ # Should this call Object.equals for consistency with Ruby?
152
+ if expression
153
+ call.target.compile(compiler, true)
154
+ call.parameters[0].compile(compiler, true)
155
+ compiler.method.op_to_bool do |target|
156
+ compiler.method.if_acmpne(target)
157
+ end
158
+ end
159
+ end
160
+
161
+ add_macro('kind_of?', ClassType) do |transformer, call|
162
+ klass, object = call.parameters[0], call.target
163
+ Duby::AST::Call.new(call.parent, call.position, 'isInstance') do |call2|
164
+ klass.parent = object.parent = call2
165
+ [
166
+ klass,
167
+ [object]
168
+ ]
169
+ end
170
+ end
171
+
172
+ add_method('kind_of?', [Object.meta], Boolean) do |compiler, call, expression|
173
+ call.target.compile(compiler, expression)
174
+ if expression
175
+ klass = call.parameters[0].inferred_type!
176
+ compiler.method.instanceof(klass.unmeta)
177
+ end
178
+ end
179
+ end
180
+ end
181
+
182
+ class ArrayType
183
+ def add_intrinsics
184
+ super
185
+ add_enumerable_macros
186
+
187
+ add_method(
188
+ '[]', [Int], component_type) do |compiler, call, expression|
189
+ if expression
190
+ call.target.compile(compiler, true)
191
+ call.parameters[0].compile(compiler, true)
192
+ component_type.aload(compiler.method)
193
+ end
194
+ end
195
+
196
+ add_method('[]=',
197
+ [Int, component_type],
198
+ component_type) do |compiler, call, expression|
199
+ call.target.compile(compiler, true)
200
+ convert_args(compiler, call.parameters, [Int, component_type])
201
+ component_type.astore(compiler.method)
202
+ if expression
203
+ call.parameters[1].compile(compiler, true)
204
+ end
205
+ end
206
+
207
+ add_method('length', [], Int) do |compiler, call, expression|
208
+ call.target.compile(compiler, true)
209
+ compiler.method.arraylength
210
+ end
211
+
212
+ add_macro('each', Duby::AST.block_type) do |transformer, call|
213
+ Duby::AST::Loop.new(call.parent,
214
+ call.position, true, false) do |forloop|
215
+ index = transformer.tmp
216
+ array = transformer.tmp
217
+
218
+ init = transformer.eval("#{index} = 0;#{array} = nil")
219
+ array_assignment = init.children[-1]
220
+ array_assignment.value = call.target
221
+ call.target.parent = array_assignment
222
+ forloop.init << init
223
+
224
+ var = call.block.args.args[0]
225
+ if var
226
+ forloop.pre << transformer.eval(
227
+ "#{var.name} = #{array}[#{index}]", '', forloop, index, array)
228
+ end
229
+ forloop.post << transformer.eval("#{index} += 1")
230
+ call.block.body.parent = forloop if call.block.body
231
+ [
232
+ Duby::AST::Condition.new(forloop, call.position) do |c|
233
+ [transformer.eval("#{index} < #{array}.length",
234
+ '', forloop, index, array)]
235
+ end,
236
+ call.block.body
237
+ ]
238
+ end
239
+ end
240
+ end
241
+ end
242
+
243
+ class MetaType
244
+ def add_intrinsics
245
+ add_method('class', [], ClassType) do |compiler, call, expression|
246
+ if expression
247
+ compiler.method.ldc_class(unmeta)
248
+ end
249
+ end
250
+ end
251
+ end
252
+
253
+ class ArrayMetaType
254
+ def add_intrinsics
255
+ super
256
+ add_macro('cast', Object) do |transformer, call|
257
+ call.cast = true
258
+ call.resolve_if(nil) { unmeta }
259
+ call
260
+ end
261
+ end
262
+ end
263
+
264
+ class StringType < Type
265
+ def add_intrinsics
266
+ super
267
+ add_method('+', [String], String) do |compiler, call, expression|
268
+ if expression
269
+ java_method('concat', String).call(compiler, call, expression)
270
+ end
271
+ end
272
+ add_method('+', [Boolean], String) do |compiler, call, expression|
273
+ if expression
274
+ call.target.compile(compiler, true)
275
+ call.parameters[0].compile(compiler, true)
276
+ compiler.method.invokestatic String, "valueOf", [String, Boolean]
277
+ compiler.method.invokevirtual String, "concat", [String, String]
278
+ end
279
+ end
280
+ add_method('+', [Char], String) do |compiler, call, expression|
281
+ if expression
282
+ call.target.compile(compiler, true)
283
+ call.parameters[0].compile(compiler, true)
284
+ compiler.method.invokestatic String, "valueOf", [String, Char]
285
+ compiler.method.invokevirtual String, "concat", [String, String]
286
+ end
287
+ end
288
+ add_method('+', [Int], String) do |compiler, call, expression|
289
+ if expression
290
+ call.target.compile(compiler, true)
291
+ call.parameters[0].compile(compiler, true)
292
+ compiler.method.invokestatic String, "valueOf", [String, Int]
293
+ compiler.method.invokevirtual String, "concat", [String, String]
294
+ end
295
+ end
296
+ add_method('+', [Long], String) do |compiler, call, expression|
297
+ if expression
298
+ call.target.compile(compiler, true)
299
+ call.parameters[0].compile(compiler, true)
300
+ compiler.method.invokestatic String, "valueOf", [String, Long]
301
+ compiler.method.invokevirtual String, "concat", [String, String]
302
+ end
303
+ end
304
+ add_method('+', [Float], String) do |compiler, call, expression|
305
+ if expression
306
+ call.target.compile(compiler, true)
307
+ call.parameters[0].compile(compiler, true)
308
+ compiler.method.invokestatic String, "valueOf", [String, Float]
309
+ compiler.method.invokevirtual String, "concat", [String, String]
310
+ end
311
+ end
312
+ add_method('+', [Double], String) do |compiler, call, expression|
313
+ if expression
314
+ call.target.compile(compiler, true)
315
+ call.parameters[0].compile(compiler, true)
316
+ compiler.method.invokestatic String, "valueOf", [String, Double]
317
+ compiler.method.invokevirtual String, "concat", [String, String]
318
+ end
319
+ end
320
+ add_method('[]', [Int], Char) do |compiler, call, expression|
321
+ if expression
322
+ call.target.compile(compiler, true)
323
+ call.parameters[0].compile(compiler, true)
324
+ compiler.method.invokevirtual String, "charAt", [Char, Int]
325
+ end
326
+ end
327
+ add_method('[]', [Int, Int], String) do |compiler, call, expression|
328
+ if expression
329
+ call.target.compile(compiler, true)
330
+ call.parameters[0].compile(compiler, true)
331
+ compiler.method.dup
332
+ call.parameters[1].compile(compiler, true)
333
+ compiler.method.iadd
334
+ compiler.method.invokevirtual String, "substring", [String, Int, Int]
335
+ end
336
+ end
337
+ end
338
+ end
339
+
340
+ class IterableType < Type
341
+ def add_intrinsics
342
+ super
343
+ add_enumerable_macros
344
+ add_macro('each', Duby::AST.block_type) do |transformer, call|
345
+ Duby::AST::Loop.new(call.parent,
346
+ call.position, true, false) do |forloop|
347
+ it = transformer.tmp
348
+
349
+ assignment = transformer.eval("#{it} = foo.iterator")
350
+ assignment.value.target = call.target
351
+ call.target.parent = assignment.value
352
+ forloop.init << assignment
353
+
354
+ var = call.block.args.args[0]
355
+ if var
356
+ forloop.pre << transformer.eval(
357
+ "#{var.name} = #{it}.next", '', forloop, it)
358
+ end
359
+ call.block.body.parent = forloop if call.block.body
360
+ [
361
+ Duby::AST::Condition.new(forloop, call.position) do |c|
362
+ [transformer.eval("#{it}.hasNext", '', forloop, it)]
363
+ end,
364
+ call.block.body
365
+ ]
366
+ end
367
+ end
368
+ end
369
+ end
370
+
371
+ class PrimitiveType
372
+ # Primitives define their own intrinsics instead of getting the Object ones.
373
+ def add_intrinsics
374
+ end
375
+ end
376
+ end