mirah 0.0.12-java → 0.1.0-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 (171) hide show
  1. data/History.txt +372 -0
  2. data/README.txt +4 -5
  3. data/Rakefile +178 -55
  4. data/examples/appengine/Readme +3 -3
  5. data/examples/appengine/src/org/mirah/MirahApp.mirah +1 -1
  6. data/examples/appengine/src/org/mirah/list.dhtml +1 -1
  7. data/examples/bintrees.mirah +1 -1
  8. data/examples/edb.mirah +1 -1
  9. data/examples/fib.mirah +1 -1
  10. data/examples/interfaces.mirah +1 -1
  11. data/examples/macros/{string-each-char.mirah → string_each_char.mirah} +4 -5
  12. data/examples/maven/README.txt +1 -1
  13. data/examples/maven/src/main/mirah/hello_mirah.mirah +1 -1
  14. data/examples/plugins/appengine/Rakefile +1 -1
  15. data/examples/plugins/appengine/src/com/google/appengine/ext/duby/db/MetaModel.mirah +1 -1
  16. data/examples/plugins/appengine/src/com/google/appengine/ext/duby/db/Model.duby +1 -1
  17. data/examples/plugins/appengine/test/com/google/appengine/ext/duby/db/ModelTest.duby +1 -1
  18. data/examples/rosettacode/100-doors.mirah +6 -6
  19. data/examples/rosettacode/README.txt +3 -3
  20. data/examples/rosettacode/boolean-values.mirah +1 -1
  21. data/examples/rosettacode/comments.mirah +1 -1
  22. data/examples/rosettacode/count-occurrences-of-a-substring.mirah +1 -1
  23. data/examples/rosettacode/factorial.mirah +1 -1
  24. data/examples/rosettacode/fibonacci.mirah +1 -1
  25. data/examples/rosettacode/fizz-buzz.mirah +2 -2
  26. data/examples/rosettacode/flatten-a-list.mirah +4 -4
  27. data/examples/rosettacode/guess-the-number.mirah +2 -2
  28. data/examples/rosettacode/hamming-numbers.mirah +4 -4
  29. data/examples/rosettacode/is-string-numeric.mirah +22 -22
  30. data/examples/rosettacode/palindrome.mirah +2 -2
  31. data/examples/rosettacode/random-numbers.mirah +1 -1
  32. data/examples/rosettacode/repeat-a-string.mirah +1 -1
  33. data/examples/rosettacode/reverse-a-string.mirah +1 -1
  34. data/examples/rosettacode/rot-13.mirah +5 -5
  35. data/examples/rosettacode/secure-temporary-file.mirah +2 -2
  36. data/examples/rosettacode/sleep.mirah +1 -1
  37. data/examples/rosettacode/string-length.mirah +5 -5
  38. data/examples/swing.mirah +1 -1
  39. data/examples/test.edb +1 -1
  40. data/javalib/mirah-bootstrap.jar +0 -0
  41. data/javalib/mirah-builtins.jar +0 -0
  42. data/javalib/mirah-parser.jar +0 -0
  43. data/javalib/mirah-util.jar +0 -0
  44. data/lib/duby.rb +1 -1
  45. data/lib/mirah.rb +50 -28
  46. data/lib/mirah/ast.rb +15 -605
  47. data/lib/mirah/ast/scope.rb +98 -69
  48. data/lib/mirah/commands.rb +1 -1
  49. data/lib/mirah/commands/base.rb +7 -7
  50. data/lib/mirah/commands/compile.rb +3 -3
  51. data/lib/mirah/commands/parse.rb +7 -5
  52. data/lib/mirah/commands/run.rb +12 -19
  53. data/lib/mirah/compiler.rb +15 -23
  54. data/lib/mirah/errors.rb +16 -1
  55. data/lib/mirah/generator.rb +79 -39
  56. data/lib/mirah/jvm/compiler.rb +1 -19
  57. data/lib/mirah/jvm/compiler/base.rb +233 -90
  58. data/lib/mirah/jvm/compiler/jvm_bytecode.rb +675 -363
  59. data/lib/mirah/jvm/method_lookup.rb +134 -65
  60. data/lib/mirah/jvm/typer.rb +10 -5
  61. data/lib/mirah/jvm/types.rb +10 -2
  62. data/lib/mirah/jvm/types/array_type.rb +10 -12
  63. data/lib/mirah/{compiler/type.rb → jvm/types/ast_ext.rb} +12 -8
  64. data/lib/mirah/jvm/types/basic_types.rb +26 -33
  65. data/lib/mirah/jvm/types/bitescript_ext.rb +1 -1
  66. data/lib/mirah/jvm/types/block_type.rb +15 -0
  67. data/lib/mirah/jvm/types/boolean.rb +8 -4
  68. data/lib/mirah/jvm/types/dynamic_type.rb +12 -13
  69. data/lib/mirah/jvm/types/enumerable.rb +7 -7
  70. data/lib/mirah/jvm/types/extensions.rb +11 -6
  71. data/lib/mirah/jvm/types/factory.rb +624 -94
  72. data/lib/mirah/jvm/types/floats.rb +21 -15
  73. data/lib/mirah/jvm/types/generic_type.rb +72 -0
  74. data/lib/mirah/jvm/types/implicit_nil_type.rb +29 -0
  75. data/lib/mirah/jvm/types/integers.rb +26 -71
  76. data/lib/mirah/jvm/types/interface_definition.rb +3 -3
  77. data/lib/mirah/jvm/types/intrinsics.rb +203 -168
  78. data/lib/mirah/jvm/types/literals.rb +6 -6
  79. data/lib/mirah/jvm/types/meta_type.rb +13 -4
  80. data/lib/mirah/jvm/types/methods.rb +281 -93
  81. data/lib/mirah/jvm/types/null_type.rb +17 -5
  82. data/lib/mirah/jvm/types/number.rb +10 -7
  83. data/lib/mirah/jvm/types/primitive_type.rb +17 -6
  84. data/lib/mirah/jvm/types/source_mirror.rb +12 -7
  85. data/lib/mirah/jvm/types/type.rb +107 -23
  86. data/lib/mirah/jvm/types/type_definition.rb +25 -10
  87. data/lib/mirah/jvm/types/unreachable_type.rb +1 -1
  88. data/lib/mirah/jvm/types/void_type.rb +3 -3
  89. data/lib/mirah/parser.rb +154 -16
  90. data/lib/mirah/plugin/edb.rb +1 -1
  91. data/lib/mirah/transform.rb +1 -2
  92. data/lib/mirah/transform/ast_ext.rb +24 -43
  93. data/lib/mirah/transform/transformer.rb +29 -224
  94. data/lib/mirah/typer.rb +2 -16
  95. data/lib/mirah/util/argument_processor.rb +25 -10
  96. data/lib/mirah/util/class_loader.rb +1 -1
  97. data/lib/mirah/util/compilation_state.rb +16 -17
  98. data/lib/mirah/util/delegate.rb +2 -2
  99. data/lib/mirah/util/logging.rb +110 -0
  100. data/lib/mirah/util/process_errors.rb +69 -11
  101. data/lib/mirah/version.rb +1 -1
  102. data/test/core/commands_test.rb +6 -24
  103. data/test/core/env_test.rb +5 -5
  104. data/{lib/mirah/jvm/source_generator/typer.rb → test/core/generator_test.rb} +9 -9
  105. data/test/core/typer_test.rb +196 -158
  106. data/test/core/util/argument_processor_test.rb +10 -10
  107. data/test/core/util/class_loader_test.rb +6 -5
  108. data/test/fixtures/org/foo/LowerCaseInnerClass$inner.class +0 -0
  109. data/test/fixtures/org/foo/LowerCaseInnerClass.class +0 -0
  110. data/test/fixtures/org/foo/LowerCaseInnerClass.java +7 -0
  111. data/test/jvm/annotations_test.rb +5 -5
  112. data/test/jvm/blocks_test.rb +140 -88
  113. data/test/jvm/bytecode_test_helper.rb +112 -94
  114. data/test/jvm/cast_test.rb +162 -0
  115. data/test/jvm/constructors_test.rb +18 -8
  116. data/test/jvm/enumerable_test.rb +77 -44
  117. data/test/jvm/example_test.rb +53 -0
  118. data/test/jvm/factory_test.rb +7 -1
  119. data/test/jvm/generics_test.rb +57 -0
  120. data/test/jvm/hash_test.rb +106 -0
  121. data/test/jvm/import_test.rb +81 -0
  122. data/test/jvm/interface_test.rb +73 -0
  123. data/test/jvm/java_typer_test.rb +92 -66
  124. data/{lib/mirah/typer/base.rb → test/jvm/jvm_commands_test.rb} +6 -10
  125. data/test/jvm/jvm_compiler_test.rb +170 -604
  126. data/test/jvm/list_extensions_test.rb +23 -0
  127. data/test/jvm/macros_test.rb +197 -32
  128. data/test/jvm/main_method_test.rb +4 -4
  129. data/test/jvm/numeric_extensions_test.rb +13 -0
  130. data/test/jvm/rescue_test.rb +73 -16
  131. data/test/jvm/varargs_test.rb +65 -0
  132. data/test/test_helper.rb +1 -2
  133. metadata +234 -251
  134. data/examples/SortClosure$__xform_tmp_1.class +0 -0
  135. data/examples/SortClosure$__xform_tmp_2.class +0 -0
  136. data/examples/SortClosure.class +0 -0
  137. data/examples/macros/StringEachChar$Extension1.class +0 -0
  138. data/lib/mirah/ast/call.rb +0 -345
  139. data/lib/mirah/ast/class.rb +0 -359
  140. data/lib/mirah/ast/flow.rb +0 -381
  141. data/lib/mirah/ast/intrinsics.rb +0 -563
  142. data/lib/mirah/ast/literal.rb +0 -178
  143. data/lib/mirah/ast/local.rb +0 -112
  144. data/lib/mirah/ast/method.rb +0 -408
  145. data/lib/mirah/ast/structure.rb +0 -387
  146. data/lib/mirah/ast/type.rb +0 -146
  147. data/lib/mirah/commands/base.rb~ +0 -57
  148. data/lib/mirah/compiler/call.rb +0 -45
  149. data/lib/mirah/compiler/class.rb +0 -81
  150. data/lib/mirah/compiler/flow.rb +0 -109
  151. data/lib/mirah/compiler/literal.rb +0 -130
  152. data/lib/mirah/compiler/local.rb +0 -59
  153. data/lib/mirah/compiler/method.rb +0 -44
  154. data/lib/mirah/compiler/structure.rb +0 -65
  155. data/lib/mirah/jvm/compiler/java_source.rb +0 -787
  156. data/lib/mirah/jvm/method_lookup.rb~ +0 -247
  157. data/lib/mirah/jvm/source_generator/builder.rb +0 -468
  158. data/lib/mirah/jvm/source_generator/loops.rb +0 -131
  159. data/lib/mirah/jvm/source_generator/precompile.rb +0 -210
  160. data/lib/mirah/plugin/gwt.rb +0 -189
  161. data/lib/mirah/plugin/java.rb +0 -70
  162. data/lib/mirah/transform/error.rb +0 -13
  163. data/lib/mirah/transform/helper.rb +0 -765
  164. data/lib/mirah/typer/simple.rb +0 -384
  165. data/lib/mirah/version.rb~ +0 -18
  166. data/test/core/ast_test.rb +0 -382
  167. data/test/core/compilation_test.rb +0 -130
  168. data/test/core/macros_test.rb +0 -61
  169. data/test/jvm/javac_test_helper.rb +0 -89
  170. data/test/jvm/jvm_compiler_test.rb~ +0 -2181
  171. data/test/plugins/gwt_test.rb +0 -69
@@ -1,44 +0,0 @@
1
- # Copyright (c) 2010 The Mirah project authors. All Rights Reserved.
2
- # All contributing project authors may be found in the NOTICE file.
3
- #
4
- # Licensed under the Apache License, Version 2.0 (the "License");
5
- # you may not use this file except in compliance with the License.
6
- # You may obtain a copy of the License at
7
- #
8
- # http://www.apache.org/licenses/LICENSE-2.0
9
- #
10
- # Unless required by applicable law or agreed to in writing, software
11
- # distributed under the License is distributed on an "AS IS" BASIS,
12
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- # See the License for the specific language governing permissions and
14
- # limitations under the License.
15
-
16
- module Mirah
17
- module AST
18
- class Arguments
19
- def compile(compiler, expression)
20
- # TODO: what does it mean for a method to be an expression?
21
- args.each {|arg| compiler.declare_argument(arg.name, arg.inferred_type)} if args
22
- rescue Exception => ex
23
- raise Mirah::InternalCompilerError.wrap(ex, self)
24
- end
25
- end
26
-
27
- class MethodDefinition
28
- def compile(compiler, expression)
29
- # TODO: what does it mean for a method to be an expression?
30
- compiler.define_method(self)
31
- rescue Exception => ex
32
- raise Mirah::InternalCompilerError.wrap(ex, self)
33
- end
34
- end
35
-
36
- class ConstructorDefinition
37
- def compile(compiler, expression)
38
- compiler.constructor(self)
39
- rescue Exception => ex
40
- raise Mirah::InternalCompilerError.wrap(ex, self)
41
- end
42
- end
43
- end
44
- end
@@ -1,65 +0,0 @@
1
- # Copyright (c) 2010 The Mirah project authors. All Rights Reserved.
2
- # All contributing project authors may be found in the NOTICE file.
3
- #
4
- # Licensed under the Apache License, Version 2.0 (the "License");
5
- # you may not use this file except in compliance with the License.
6
- # You may obtain a copy of the License at
7
- #
8
- # http://www.apache.org/licenses/LICENSE-2.0
9
- #
10
- # Unless required by applicable law or agreed to in writing, software
11
- # distributed under the License is distributed on an "AS IS" BASIS,
12
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- # See the License for the specific language governing permissions and
14
- # limitations under the License.
15
-
16
- module Mirah
17
- module AST
18
- class Body
19
- def compile(compiler, expression)
20
- compiler.line(line_number)
21
- compiler.body(self, expression)
22
- rescue Exception => ex
23
- raise Mirah::InternalCompilerError.wrap(ex, self)
24
- end
25
- end
26
-
27
- class ScopedBody
28
- def compile(compiler, expression)
29
- compiler.line(line_number)
30
- compiler.scoped_body(self, expression)
31
- rescue Exception => ex
32
- raise Mirah::InternalCompilerError.wrap(ex, self)
33
- end
34
- end
35
-
36
- class BindingReference
37
- def compile(compiler, expression)
38
- if expression
39
- compiler.line(line_number)
40
- compiler.binding_reference
41
- end
42
- rescue Exception => ex
43
- raise Mirah::InternalCompilerError.wrap(ex, self)
44
- end
45
- end
46
-
47
- class Script
48
- def compile(compiler, expression)
49
- # TODO: what does it mean for a script to be an expression? possible?
50
- compiler.define_main(self)
51
- rescue Exception => ex
52
- raise Mirah::InternalCompilerError.wrap(ex, self)
53
- end
54
- end
55
-
56
- class Noop
57
- def compile(compiler, expression)
58
- # TODO: what does it mean for a noop to be an expression
59
- # nothing
60
- rescue Exception => ex
61
- raise Mirah::InternalCompilerError.wrap(ex, self)
62
- end
63
- end
64
- end
65
- end
@@ -1,787 +0,0 @@
1
- # Copyright (c) 2010 The Mirah project authors. All Rights Reserved.
2
- # All contributing project authors may be found in the NOTICE file.
3
- #
4
- # Licensed under the Apache License, Version 2.0 (the "License");
5
- # you may not use this file except in compliance with the License.
6
- # You may obtain a copy of the License at
7
- #
8
- # http://www.apache.org/licenses/LICENSE-2.0
9
- #
10
- # Unless required by applicable law or agreed to in writing, software
11
- # distributed under the License is distributed on an "AS IS" BASIS,
12
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- # See the License for the specific language governing permissions and
14
- # limitations under the License.
15
-
16
- require 'mirah'
17
- require 'mirah/ast'
18
- require 'mirah/jvm/types'
19
- require 'mirah/jvm/compiler'
20
- require 'mirah/jvm/source_generator/builder'
21
- require 'mirah/jvm/source_generator/precompile'
22
- require 'mirah/jvm/source_generator/loops'
23
-
24
- class String
25
- def compile(compiler, expression)
26
- compiler.method.print self if expression
27
- end
28
- end
29
-
30
- module Mirah
31
- module JVM
32
- module Compiler
33
- class JavaSource < Base
34
- JVMTypes = Mirah::JVM::Types
35
- attr_accessor :lvalue
36
-
37
- Operators = [
38
- '+', '-', '+@', '-@', '/', '%', '*', '<',
39
- '<=', '==', '!=', '>=', '>',
40
- '<<', '>>', '>>>', '|', '&', '^', '~'
41
- ]
42
- ArrayOps = [
43
- '[]', '[]=', 'length'
44
- ]
45
-
46
- ImplicitReturn = Struct.new(:value)
47
-
48
- def initialize
49
- super
50
- end
51
-
52
- def file_builder(filename)
53
- Mirah::JavaSource::Builder.new(filename, self)
54
- end
55
-
56
- def output_type
57
- "source files"
58
- end
59
-
60
- def define_class(class_def, expression)
61
- with(:type => class_def.inferred_type,
62
- :class => class_def.inferred_type.define(@file),
63
- :static => false) do
64
- annotate(@class, class_def.annotations)
65
- class_def.body.compile(self, false) if class_def.body
66
- @class.stop unless @method && @method.name == 'main' && @class == @method.klass
67
- end
68
- end
69
-
70
- def define_method(node)
71
- base_define_method(node, false) do |method, _|
72
- with :method => method do
73
- log "Starting new method #{node.name}"
74
- @method.start
75
-
76
- prepare_binding(node) do
77
- declare_locals(node.static_scope)
78
- unless method.returns_void?
79
- self.return(ImplicitReturn.new(node.body))
80
- else
81
- node.body.compile(self, false) if node.body
82
- end
83
- end
84
-
85
- log "Method #{node.name} complete!"
86
- @method.stop
87
- end
88
- end
89
- end
90
-
91
- def annotate(node, annotations)
92
- node.annotate(annotations)
93
- end
94
-
95
- def define_optarg_chain(name, arg, return_type,
96
- args_for_opt, arg_types_for_opt)
97
- # declare all args so they get their values
98
- @method.print "return " unless method.returns_void?
99
- @method.print "this." unless @static
100
- @method.print "#{name}("
101
- @method.print args_for_opt.map(&:name).join(', ')
102
- @method.print ', 'if args_for_opt.size > 0
103
- arg.value.compile(self, true)
104
-
105
- # invoke the next one in the chain
106
- @method.print ");\n"
107
- end
108
-
109
- def constructor(node)
110
- super(node, false) do |method, _|
111
- with :method => method do
112
- @method.start
113
- if node.delegate_args
114
- delegate = if node.calls_super
115
- "super"
116
- else
117
- "this"
118
- end
119
- method.print "#{delegate}("
120
- node.delegate_args.each_with_index do |arg, index|
121
- method.print ', ' unless index == 0
122
- raise "Invalid constructor argument #{arg}" unless arg.expr?(self)
123
- arg.compile(self, true)
124
- end
125
- method.puts ");"
126
- end
127
-
128
- prepare_binding(node) do
129
- declare_locals(node.static_scope)
130
- node.body.compile(self, false) if node.body
131
- end
132
- method.stop
133
- end
134
- end
135
- end
136
-
137
- def prepare_binding(scope)
138
- if scope.has_binding?
139
- type = scope.binding_type
140
- @binding = @bindings[type]
141
- @method.puts "#{type.to_source} $binding = new #{type.to_source}();"
142
- if scope.respond_to? :arguments
143
- scope.arguments.args.each do |param|
144
- if scope.static_scope.captured?(param.name)
145
- captured_local_declare(scope, param.name, param.inferred_type)
146
- @method.puts "$binding.#{param.name} = #{param.name};"
147
- end
148
- end
149
- end
150
- end
151
- begin
152
- yield
153
- ensure
154
- if scope.has_binding?
155
- @binding.stop
156
- @binding = nil
157
- end
158
- end
159
- end
160
-
161
- def define_closure(class_def, expression)
162
- compiler = ClosureCompiler.new(@file, @type, self)
163
- compiler.define_class(class_def, expression)
164
- end
165
-
166
- def return(node)
167
- if method.returns_void?
168
- @method.puts 'return;'
169
- return
170
- end
171
- if node.value.expr?(self)
172
- @method.print 'return '
173
- node.value.compile(self, true)
174
- @method.puts ';'
175
- else
176
- store_value('return ', node.value)
177
- end
178
- end
179
-
180
- def _raise(node)
181
- if node.expr?(self)
182
- @method.print 'throw '
183
- node.compile(self, true)
184
- @method.puts ';'
185
- else
186
- store_value('throw ', node)
187
- end
188
- end
189
-
190
- def rescue(node, expression)
191
- @method.block 'try' do
192
- if node.else_node.nil?
193
- maybe_store(node.body, expression) if node.body
194
- else
195
- node.body.compile(self, false) if node.body
196
- end
197
- end
198
- node.clauses.each do |clause|
199
- clause.types.each do |type|
200
- name = scoped_local_name(clause.name || 'tmp$ex', clause.static_scope)
201
- @method.declare_local(type, name, false)
202
- @method.block "catch (#{type.to_source} #{name})" do
203
- declare_locals(clause.static_scope)
204
- maybe_store(clause.body, expression)
205
- end
206
- end
207
- end
208
- if node.else_node
209
- maybe_store(node.else_node, expression)
210
- end
211
- end
212
-
213
- def ensure(node, expression)
214
- @method.block 'try' do
215
- maybe_store(node.body, expression)
216
- end
217
- @method.block 'finally' do
218
- node.clause.compile(self, false)
219
- end
220
- end
221
-
222
- def line(num)
223
- end
224
-
225
- def declare_local(name, type)
226
- @method.declare_local(type, name)
227
- end
228
-
229
- def declare_field(name, type, annotations, static_field)
230
- @class.declare_field(name, type, @static || static_field, 'private', annotations)
231
- end
232
-
233
- def local(scope, name, type)
234
- name = scoped_local_name(name, scope)
235
- @method.print name
236
- end
237
-
238
- def field(name, type, annotations, static_field)
239
- name = name[1..-1] if name =~ /^@/
240
- declare_field(name, type, annotations, static_field)
241
- @method.print "#{this}.#{name}"
242
- end
243
-
244
- def this(method=nil)
245
- if method && method.static?
246
- method.declaring_class.name
247
- elsif @self_scope && @self_scope.self_node && @self_scope.self_node != :self
248
- scoped_local_name('self', @self_scope)
249
- else
250
- @static ? @class.class_name : 'this'
251
- end
252
- end
253
-
254
- def declare_locals(scope)
255
- scope.locals.each do |name|
256
- full_name = scoped_local_name(name, scope)
257
- unless scope.captured?(name) || method.local?(full_name)
258
- declare_local(full_name, scope.local_type(name))
259
- end
260
- end
261
- end
262
-
263
- def local_assign(scope, name, type, expression, value)
264
- simple = value.expr?(self)
265
- value = value.precompile(self)
266
- name = scoped_local_name(name, scope)
267
- if method.local?(name)
268
- if expression
269
- if simple
270
- @method.print '('
271
- else
272
- @method.print @lvalue
273
- end
274
- end
275
- @method.print "#{name} = "
276
- value.compile(self, true)
277
- if simple && expression
278
- @method.print ')'
279
- else
280
- @method.puts ';'
281
- end
282
- else
283
- @method.declare_local(type, name) do
284
- value.compile(self, true)
285
- end
286
- if expression
287
- @method.puts "#{@lvalue}#{name};"
288
- end
289
- end
290
- end
291
-
292
- def field_declare(name, type, annotations)
293
- name = name[1..-1] if name =~ /^@/
294
- declare_field(name, type, annotations)
295
- end
296
-
297
- def local_declare(scope, name, type)
298
- name = scoped_local_name(name, scope)
299
- declare_local(name, type)
300
- end
301
-
302
- def field_assign(name, type, expression, value, annotations, static_field)
303
- name = name[1..-1] if name =~ /^@/
304
- declare_field(name, type, annotations, static_field)
305
- lvalue = "#{@lvalue if expression}#{this}.#{name} = "
306
- store_value(lvalue, value)
307
- end
308
-
309
- def captured_local_declare(scope, name, type)
310
- unless declared_captures[name]
311
- declared_captures[name] = type
312
- @binding.declare_field(name, type, false, '')
313
- end
314
- end
315
-
316
- def captured_local(scope, name, type)
317
- captured_local_declare(scope, name, type)
318
- @method.print "$binding.#{name}"
319
- end
320
-
321
- def captured_local_assign(node, expression)
322
- scope, name, type = node.containing_scope, node.name, node.inferred_type
323
- captured_local_declare(scope, name, type)
324
- lvalue = "#{@lvalue if expression}$binding.#{name} = "
325
- store_value(lvalue, node.value)
326
- end
327
-
328
- def store_value(lvalue, value)
329
- if value.is_a? String
330
- @method.puts "#{lvalue}#{value};"
331
- elsif value.expr?(self)
332
- @method.print lvalue
333
- value.compile(self, true)
334
- @method.puts ';'
335
- else
336
- with :lvalue => lvalue do
337
- value.compile(self, true)
338
- end
339
- end
340
- end
341
-
342
- def assign(name, value)
343
- store_value("#{name} = ", value)
344
- name
345
- end
346
-
347
- def maybe_store(value, expression)
348
- if expression
349
- store_value(@lvalue, value)
350
- else
351
- value.compile(self, false)
352
- end
353
- end
354
-
355
- def body(body, expression)
356
- super(body, expression) do |last|
357
- maybe_store(last, expression)
358
- end
359
- end
360
-
361
- def scoped_body(scope, expression)
362
- if @method
363
- @method.block do
364
- super
365
- end
366
- else
367
- super
368
- end
369
- end
370
-
371
- def branch_expression(node)
372
- node.condition.compile(self, true)
373
- @method.print ' ? ('
374
- if node.body
375
- node.body.compile(self, true)
376
- else
377
- @method.print @method.init_value(node.inferred_type)
378
- end
379
- @method.print ') : ('
380
- if node.else
381
- node.else.compile(self, true)
382
- else
383
- @method.print @method.init_value(node.inferred_type)
384
- end
385
- @method.print ')'
386
- end
387
-
388
- def branch(node, expression)
389
- if expression && node.expr?(self)
390
- return branch_expression(node)
391
- end
392
- predicate = node.condition.predicate.precompile(self)
393
- @method.print 'if ('
394
- predicate.compile(self, true)
395
- @method.block ")" do
396
- if node.body
397
- maybe_store(node.body, expression)
398
- elsif expression
399
- store_value(@lvalue, @method.init_value(node.inferred_type))
400
- end
401
- end
402
- if node.else || expression
403
- @method.block 'else' do
404
- if node.else
405
- maybe_store(node.else, expression)
406
- else
407
- store_value(@lvalue, @method.init_value(node.inferred_type))
408
- end
409
- end
410
- end
411
- end
412
-
413
- def loop(loop, expression)
414
- if loop.redo? || loop.post || !loop.condition.predicate.expr?(self)
415
- loop = ComplexWhileLoop.new(loop, self)
416
- else
417
- loop = SimpleWhileLoop.new(loop, self)
418
- end
419
- with(:loop => loop) do
420
- loop.compile(expression)
421
- end
422
- end
423
-
424
- def expr?(target, params)
425
- !([target] + params).any? {|x| x.kind_of? Mirah::AST::TempValue}
426
- end
427
-
428
- def operator(target, op, params, expression)
429
- simple = expr?(target, params)
430
- if expression && !simple
431
- @method.print @lvalue
432
- end
433
- if params.size == 0
434
- # unary operator
435
- op = op[0,1]
436
- @method.print op
437
- target.compile(self, true)
438
- else
439
- @method.print '('
440
- other = params[0]
441
- target.compile(self, true)
442
- @method.print " #{op} "
443
- other.compile(self, true)
444
- @method.print ')'
445
- end
446
- unless expression && simple
447
- @method.puts ';'
448
- end
449
- end
450
-
451
- def precompile_nodes(nodes)
452
- if nodes.all? {|n| n.expr?(self)}
453
- nodes
454
- else
455
- nodes.map do |node|
456
- tempval = node.precompile(self)
457
- if node == tempval && !node.kind_of?(Mirah::AST::Literal)
458
- tempval = node.temp(self)
459
- end
460
- tempval
461
- end
462
- end
463
- end
464
-
465
- def compile_args(call)
466
- precompile_nodes(call.parameters)
467
- end
468
-
469
- def self_type
470
- type = AST.type(nil, @class.name.tr('/', '.'))
471
- type = type.meta if @static
472
- type
473
- end
474
-
475
- def super_call(call, expression)
476
- super_method_call(this, call, compile_args(call), expression)
477
- end
478
-
479
- def cast(call, expression)
480
- args = compile_args(call)
481
- simple = call.expr?(self)
482
- @method.print @lvalue if expression && !simple
483
- @method.print "((#{call.inferred_type.to_source})("
484
- args.each{|arg| arg.compile(self, true)}
485
- @method.print "))"
486
- @method.puts ';' unless simple && expression
487
- end
488
-
489
- def self_call(call, expression)
490
- if call.cast?
491
- cast(call, expression)
492
- else
493
- type = call.scope.static_scope.self_type
494
- type = type.meta if (@static && type == @type)
495
- params = call.parameters.map do |param|
496
- param.inferred_type
497
- end
498
- method = type.get_method(call.name, params)
499
- method_call(this(method), call, compile_args(call), expression)
500
- end
501
- end
502
-
503
- def call(call, expression)
504
- return cast(call, expression) if call.cast?
505
- if Mirah::AST::Constant === call.target || Mirah::AST::Colon2 === call.target
506
- target = call.target.inferred_type.to_source
507
- else
508
- target = call.precompile_target(self)
509
- end
510
- params = compile_args(call)
511
-
512
- if Operators.include? call.name
513
- operator(target, call.name, params, expression)
514
- elsif call.target.inferred_type.array? && ArrayOps.include?(call.name)
515
- array_op(target, call.name, params, expression)
516
- elsif call.name == 'nil?'
517
- operator(target, '==', ['null'], expression)
518
- else
519
- method_call(target, call, params, expression)
520
- end
521
- end
522
-
523
- def array_op(target, name, args, expression)
524
- simple = expr?(target, args)
525
- index, value = args
526
- if expression && !simple
527
- @method.print @lvalue
528
- end
529
- target.compile(self, true)
530
- if name == 'length'
531
- @method.print '.length'
532
- else
533
- @method.print '['
534
- index.compile(self, true)
535
- @method.print ']'
536
- if name == '[]='
537
- @method.print " = "
538
- value.compile(self, true)
539
- end
540
- end
541
- unless simple && expression
542
- @method.puts ';'
543
- end
544
- end
545
-
546
- def break(node)
547
- error("break outside of loop", node) unless @loop
548
- @loop.break
549
- end
550
-
551
- def next(node)
552
- error("next outside of loop", node) unless @loop
553
- @loop.next
554
- end
555
-
556
- def redo(node)
557
- error("redo outside of loop", node) unless @loop
558
- @loop.redo
559
- end
560
-
561
- # TODO: merge cleanly with method_call logic
562
- def super_method_call(target, call, params, expression)
563
- simple = call.expr?(self)
564
- method = call.method(self)
565
- unless simple || method.return_type.void?
566
- @method.print @lvalue if expression
567
- end
568
- if method.constructor?
569
- @method.print "super("
570
- else
571
- @method.print "super.#{method.name}("
572
- end
573
- params.each_with_index do |param, index|
574
- @method.print ', ' unless index == 0
575
- param.compile(self, true)
576
- end
577
- if simple && expression
578
- @method.print ')'
579
- else
580
- @method.puts ');'
581
- end
582
- if method.return_type.void? && expression
583
- @method.print @lvalue
584
- if method.static?
585
- @method.puts 'null;'
586
- else
587
- target.compile(self, true)
588
- @method.puts ';'
589
- end
590
- end
591
-
592
- end
593
-
594
- def method_call(target, call, params, expression)
595
- simple = call.expr?(self)
596
- method = call.method(self)
597
- unless simple || method.return_type.void?
598
- @method.print @lvalue if expression
599
- end
600
-
601
- # preamble
602
- if method.constructor?
603
- @method.print "new "
604
- target.compile(self, true)
605
- @method.print '('
606
- elsif method.field?
607
- target.compile(self, true)
608
- @method.print ".#{method.name}"
609
- if method.argument_types.size == 1
610
- @method.print " = ("
611
- end
612
- elsif Mirah::JVM::Types::Intrinsic === method
613
- method.call(self, call, expression)
614
- return
615
- else
616
- @method.print "(" if Mirah::AST::StringConcat === target
617
- target.compile(self, true)
618
- @method.print ")" if Mirah::AST::StringConcat === target
619
- @method.print ".#{method.name}("
620
- end
621
-
622
- # args
623
- params.each_with_index do |param, index|
624
- @method.print ', ' unless index == 0
625
- param.compile(self, true)
626
- end
627
-
628
- # postamble
629
- if !method.field? || (method.field? && method.argument_types.size == 1)
630
- if simple && expression
631
- @method.print ')'
632
- else
633
- @method.puts ');'
634
- end
635
- end
636
-
637
- # cleanup
638
- if method.return_type.void? && expression
639
- @method.print @lvalue
640
- if method.static?
641
- @method.puts 'null;'
642
- else
643
- target.compile(self, true)
644
- @method.puts ';'
645
- end
646
- end
647
- end
648
-
649
- def temp(expression, value=nil)
650
- value ||= expression
651
- type = value.inferred_type
652
- if value.expr?(self)
653
- @method.tmp(type) do
654
- value.compile(self, true)
655
- end
656
- else
657
- assign(@method.tmp(type), value)
658
- end
659
- end
660
-
661
- def empty_array(type, size)
662
- sizevar = size.precompile(self)
663
- @method.print "#{@lvalue unless size.expr?(self)}new #{type.name}["
664
- sizevar.compile(self, true)
665
- @method.print ']'
666
- end
667
-
668
- def string(value)
669
- @method.print value.inspect
670
- end
671
-
672
- def boolean(value)
673
- @method.print value ? 'true' : 'false'
674
- end
675
-
676
- def regexp(value, flags = 0)
677
- @method.print "java.util.regex.Pattern.compile("
678
- @method.print value.inspect
679
- @method.print ")"
680
- end
681
-
682
- def array(node, expression)
683
- if expression
684
- # create unmodifiable list from array (simplest way to do this in Java source)
685
- @method.print "java.util.Collections.unmodifiableList(java.util.Arrays.asList("
686
-
687
- # elements, as expressions
688
- comma = false
689
- node.children.each do |n|
690
- @method.print ", " if comma
691
- n.compile(self, true)
692
- comma = true
693
- end
694
-
695
- @method.print("))")
696
- else
697
- # elements, as non-expressions
698
- # TODO: ensure they're all reference types!
699
- node.children.each do |n|
700
- n.compile(self, false)
701
- end
702
- end
703
- end
704
-
705
- def build_string(orig_nodes, expression)
706
- if expression
707
- nodes = precompile_nodes(orig_nodes)
708
- simple = nodes.equal?(orig_nodes)
709
-
710
- unless simple
711
- @method.print(lvalue)
712
- end
713
-
714
- @method.print '"" + ' unless nodes.first.kind_of?(Mirah::AST::String)
715
-
716
- nodes.first.compile(self, true)
717
-
718
- nodes[1..-1].each do |node|
719
- @method.print ' + '
720
- node.compile(self, true)
721
- end
722
- unless simple
723
- @method.puts ';'
724
- end
725
- else
726
- orig_nodes.each {|n| n.compile(self, false)}
727
- end
728
- end
729
-
730
- def to_string(body, expression)
731
- body.compile(self, expression)
732
- end
733
-
734
- def null
735
- @method.print 'null'
736
- end
737
-
738
- def binding_reference
739
- @method.print '$binding'
740
- end
741
-
742
- def real_self
743
- @method.print 'this'
744
- end
745
-
746
- def print(node)
747
- value = node.parameters[0]
748
- value = value && value.precompile(self)
749
- if node.println
750
- @method.print "System.out.println("
751
- else
752
- @method.print "System.out.print("
753
- end
754
- value.compile(self, true) if value
755
- @method.puts ');'
756
- end
757
-
758
- class ClosureCompiler < JavaSource
759
- def initialize(file, type, parent)
760
- @file = file
761
- @type = type
762
- @parent = parent
763
- end
764
-
765
- def prepare_binding(scope)
766
- if scope.has_binding?
767
- type = scope.binding_type
768
- @binding = @parent.get_binding(type)
769
- @method.puts("#{type.to_source} $binding = this.binding;")
770
- end
771
- begin
772
- yield
773
- ensure
774
- if scope.has_binding?
775
- @binding = nil
776
- end
777
- end
778
- end
779
-
780
- def declared_captures
781
- @parent.declared_captures(@binding)
782
- end
783
- end
784
- end
785
- end
786
- end
787
- end