mirah 0.0.4-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 (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