mirah 0.0.7-java → 0.0.8-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 (182) hide show
  1. data/History.txt +181 -0
  2. data/README.txt +6 -10
  3. data/Rakefile +86 -9
  4. data/bin/mirah +2 -0
  5. data/bin/mirahc +2 -0
  6. data/bin/mirahp +2 -0
  7. data/{bin/dubyp → examples/interfaces.mirah} +16 -9
  8. data/examples/macros/square.mirah +12 -0
  9. data/examples/macros/square_int.mirah +12 -0
  10. data/examples/macros/string-each-char.mirah +14 -0
  11. data/examples/maven/README.txt +2 -0
  12. data/examples/maven/pom.xml +23 -0
  13. data/examples/maven/src/main/mirah/hello_mirah.mirah +9 -0
  14. data/examples/rosettacode/100-doors.mirah +44 -0
  15. data/examples/rosettacode/99-bottles-of-beer.mirah +13 -0
  16. data/examples/rosettacode/README.txt +9 -0
  17. data/examples/rosettacode/boolean-values.mirah +29 -0
  18. data/examples/rosettacode/comments.mirah +2 -0
  19. data/examples/rosettacode/copy-a-string.mirah +10 -0
  20. data/examples/rosettacode/count-occurrences-of-a-substring.mirah +40 -0
  21. data/examples/rosettacode/create-a-file.mirah +6 -0
  22. data/examples/rosettacode/empty-string.mirah +9 -0
  23. data/examples/rosettacode/factorial.mirah +10 -0
  24. data/examples/rosettacode/fibonacci.mirah +21 -0
  25. data/examples/rosettacode/file-size.mirah +5 -0
  26. data/examples/rosettacode/fizz-buzz.mirah +21 -0
  27. data/examples/rosettacode/flatten-a-list.mirah +24 -0
  28. data/examples/rosettacode/guess-the-number.mirah +21 -0
  29. data/examples/rosettacode/is-string-numeric.mirah +127 -0
  30. data/examples/rosettacode/palindrome.mirah +14 -0
  31. data/examples/rosettacode/repeat-a-string.mirah +9 -0
  32. data/examples/rosettacode/reverse-a-string.mirah +6 -0
  33. data/examples/rosettacode/rot-13.mirah +20 -0
  34. data/examples/rosettacode/user-input.mirah +4 -0
  35. data/examples/sort_closure.mirah +1 -1
  36. data/javalib/dynalink-0.2.jar +0 -0
  37. data/javalib/mirah-bootstrap.jar +0 -0
  38. data/lib/mirah.rb +7 -16
  39. data/lib/mirah/ast.rb +22 -92
  40. data/lib/mirah/ast/call.rb +41 -9
  41. data/lib/mirah/ast/class.rb +34 -6
  42. data/lib/mirah/ast/flow.rb +17 -5
  43. data/lib/mirah/ast/intrinsics.rb +50 -8
  44. data/lib/mirah/ast/literal.rb +7 -0
  45. data/lib/mirah/ast/local.rb +9 -1
  46. data/lib/mirah/ast/method.rb +21 -8
  47. data/lib/mirah/ast/scope.rb +1 -1
  48. data/lib/mirah/ast/structure.rb +81 -15
  49. data/lib/mirah/ast/type.rb +4 -0
  50. data/{bin/dubyc → lib/mirah/commands.rb} +4 -11
  51. data/lib/mirah/commands/base.rb +54 -0
  52. data/lib/mirah/commands/compile.rb +39 -0
  53. data/{examples/wiki/Rakefile → lib/mirah/commands/parse.rb} +18 -17
  54. data/lib/mirah/commands/run.rb +73 -0
  55. data/lib/mirah/compiler.rb +37 -417
  56. data/lib/mirah/compiler/call.rb +45 -0
  57. data/lib/mirah/compiler/class.rb +81 -0
  58. data/lib/mirah/compiler/flow.rb +109 -0
  59. data/lib/mirah/compiler/literal.rb +130 -0
  60. data/lib/mirah/compiler/local.rb +59 -0
  61. data/lib/mirah/compiler/method.rb +44 -0
  62. data/lib/mirah/compiler/structure.rb +65 -0
  63. data/lib/mirah/compiler/type.rb +27 -0
  64. data/lib/mirah/env.rb +4 -6
  65. data/lib/mirah/generator.rb +61 -0
  66. data/lib/mirah/jvm/compiler.rb +8 -867
  67. data/lib/mirah/jvm/compiler/base.rb +270 -0
  68. data/lib/mirah/jvm/compiler/java_source.rb +779 -0
  69. data/lib/mirah/jvm/compiler/jvm_bytecode.rb +851 -0
  70. data/lib/mirah/jvm/method_lookup.rb +21 -2
  71. data/lib/mirah/jvm/source_generator/builder.rb +10 -13
  72. data/lib/mirah/jvm/source_generator/loops.rb +99 -93
  73. data/lib/mirah/jvm/source_generator/precompile.rb +3 -2
  74. data/lib/mirah/jvm/typer.rb +3 -3
  75. data/lib/mirah/jvm/types.rb +10 -426
  76. data/lib/mirah/jvm/types/array_type.rb +62 -0
  77. data/lib/mirah/jvm/types/basic_types.rb +1 -0
  78. data/lib/mirah/jvm/types/dynamic_type.rb +46 -0
  79. data/lib/mirah/jvm/types/factory.rb +23 -5
  80. data/lib/mirah/jvm/types/interface_definition.rb +20 -0
  81. data/lib/mirah/jvm/types/intrinsics.rb +15 -3
  82. data/lib/mirah/jvm/types/meta_type.rb +45 -0
  83. data/lib/mirah/jvm/types/methods.rb +12 -5
  84. data/lib/mirah/jvm/types/null_type.rb +27 -0
  85. data/lib/mirah/jvm/types/primitive_type.rb +38 -0
  86. data/lib/mirah/jvm/types/source_mirror.rb +266 -0
  87. data/lib/mirah/jvm/types/type.rb +173 -0
  88. data/lib/mirah/jvm/types/type_definition.rb +55 -0
  89. data/lib/mirah/jvm/types/unreachable_type.rb +27 -0
  90. data/lib/mirah/jvm/types/void_type.rb +19 -0
  91. data/lib/mirah/parser.rb +90 -0
  92. data/lib/mirah/plugin/gwt.rb +5 -5
  93. data/lib/mirah/plugin/java.rb +1 -1
  94. data/lib/mirah/transform.rb +4 -321
  95. data/lib/mirah/transform/ast_ext.rb +63 -0
  96. data/lib/mirah/transform/error.rb +13 -0
  97. data/lib/mirah/transform/helper.rb +761 -0
  98. data/lib/mirah/transform/transformer.rb +255 -0
  99. data/lib/mirah/typer.rb +2 -383
  100. data/{bin/duby → lib/mirah/typer/base.rb} +12 -10
  101. data/lib/mirah/typer/simple.rb +377 -0
  102. data/lib/mirah/util/argument_processor.rb +114 -0
  103. data/lib/mirah/util/class_loader.rb +37 -0
  104. data/lib/mirah/util/compilation_state.rb +51 -0
  105. data/lib/mirah/util/process_errors.rb +33 -0
  106. data/lib/mirah/version.rb +1 -1
  107. data/lib/mirah_task.rb +3 -2
  108. data/test/{test_ast.rb → core/test_ast.rb} +6 -0
  109. data/test/{test_compilation.rb → core/test_compilation.rb} +0 -0
  110. data/test/{test_env.rb → core/test_env.rb} +24 -25
  111. data/test/{test_macros.rb → core/test_macros.rb} +2 -4
  112. data/test/{test_typer.rb → core/test_typer.rb} +0 -3
  113. data/test/jvm/bytecode_test_helper.rb +181 -0
  114. data/test/{test_javac_compiler.rb → jvm/javac_test_helper.rb} +38 -22
  115. data/test/jvm/test_enumerable.rb +304 -0
  116. data/test/{test_java_typer.rb → jvm/test_java_typer.rb} +2 -4
  117. data/test/{test_jvm_compiler.rb → jvm/test_jvm_compiler.rb} +146 -443
  118. data/test/jvm/test_macros.rb +147 -0
  119. data/test/jvm/test_main_method.rb +15 -0
  120. data/test/{test_gwt.rb → plugins/test_gwt.rb} +0 -2
  121. metadata +103 -91
  122. data/bin/jrubyp +0 -52
  123. data/examples/wiki/src/org/mirah/wiki/MirahWiki.duby +0 -339
  124. data/examples/wiki/src/org/mirah/wiki/edit.eduby.html +0 -42
  125. data/examples/wiki/src/org/mirah/wiki/error.eduby.html +0 -2
  126. data/examples/wiki/src/org/mirah/wiki/layout.eduby.html +0 -69
  127. data/examples/wiki/src/org/mirah/wiki/parser.eduby.html +0 -7
  128. data/examples/wiki/src/org/mirah/wiki/view.eduby.html +0 -15
  129. data/examples/wiki/war/WEB-INF/classes/test/HeredocContext.class +0 -0
  130. data/examples/wiki/war/WEB-INF/classes/test/MirahParser.class +0 -0
  131. data/examples/wiki/war/WEB-INF/lib/appengine-api.jar +0 -0
  132. data/examples/wiki/war/WEB-INF/lib/dubydatastore.jar +0 -0
  133. data/examples/wiki/war/WEB-INF/lib/jmeta-runtime.jar +0 -0
  134. data/examples/wiki/war/WEB-INF/lib/pegdown-stubs.jar +0 -0
  135. data/examples/wiki/war/WEB-INF/pegdown.jar +0 -0
  136. data/examples/wiki/war/app.yaml +0 -21
  137. data/examples/wiki/war/public/favicon.ico +0 -0
  138. data/examples/wiki/war/public/images/appengine_duby.png +0 -0
  139. data/examples/wiki/war/public/images/back.gif +0 -0
  140. data/examples/wiki/war/public/images/dir.gif +0 -0
  141. data/examples/wiki/war/public/images/file.gif +0 -0
  142. data/examples/wiki/war/public/javascripts/prettify.js +0 -61
  143. data/examples/wiki/war/public/robots.txt +0 -0
  144. data/examples/wiki/war/public/stylesheets/main.css +0 -156
  145. data/examples/wiki/war/public/stylesheets/prettify.css +0 -1
  146. data/examples/wiki/war/public/stylesheets/sh_style.css +0 -66
  147. data/examples/wiki/war/public/stylesheets/source.css +0 -21
  148. data/examples/wiki/war/public/wmd/images/bg-fill.png +0 -0
  149. data/examples/wiki/war/public/wmd/images/bg.png +0 -0
  150. data/examples/wiki/war/public/wmd/images/blockquote.png +0 -0
  151. data/examples/wiki/war/public/wmd/images/bold.png +0 -0
  152. data/examples/wiki/war/public/wmd/images/code.png +0 -0
  153. data/examples/wiki/war/public/wmd/images/h1.png +0 -0
  154. data/examples/wiki/war/public/wmd/images/hr.png +0 -0
  155. data/examples/wiki/war/public/wmd/images/img.png +0 -0
  156. data/examples/wiki/war/public/wmd/images/italic.png +0 -0
  157. data/examples/wiki/war/public/wmd/images/link.png +0 -0
  158. data/examples/wiki/war/public/wmd/images/ol.png +0 -0
  159. data/examples/wiki/war/public/wmd/images/redo.png +0 -0
  160. data/examples/wiki/war/public/wmd/images/separator.png +0 -0
  161. data/examples/wiki/war/public/wmd/images/ul.png +0 -0
  162. data/examples/wiki/war/public/wmd/images/undo.png +0 -0
  163. data/examples/wiki/war/public/wmd/images/wmd-on.png +0 -0
  164. data/examples/wiki/war/public/wmd/images/wmd.png +0 -0
  165. data/examples/wiki/war/public/wmd/showdown.js +0 -421
  166. data/examples/wiki/war/public/wmd/wmd-base.js +0 -1799
  167. data/examples/wiki/war/public/wmd/wmd-plus.js +0 -311
  168. data/examples/wiki/war/public/wmd/wmd.js +0 -73
  169. data/examples/wiki/war/src/org/mirah/wiki/MirahWiki.duby +0 -339
  170. data/examples/wiki/war/src/org/mirah/wiki/edit.eduby.html +0 -42
  171. data/examples/wiki/war/src/org/mirah/wiki/error.eduby.html +0 -2
  172. data/examples/wiki/war/src/org/mirah/wiki/layout.eduby.html +0 -69
  173. data/examples/wiki/war/src/org/mirah/wiki/parser.eduby.html +0 -7
  174. data/examples/wiki/war/src/org/mirah/wiki/view.eduby.html +0 -15
  175. data/javalib/dynalink-0.1.jar +0 -0
  176. data/javalib/jsr292-mock.jar +0 -0
  177. data/lib/mirah/class_loader.rb +0 -35
  178. data/lib/mirah/compilation_state.rb +0 -28
  179. data/lib/mirah/impl.rb +0 -273
  180. data/lib/mirah/jvm/base.rb +0 -267
  181. data/lib/mirah/jvm/source_compiler.rb +0 -760
  182. data/lib/mirah/transform2.rb +0 -752
@@ -1,267 +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 Compiler
18
- class JVMCompilerBase
19
- attr_accessor :filename, :method, :static, :class
20
-
21
- class CompilationError < Mirah::NodeError
22
- end
23
-
24
- def initialize
25
- @jump_scope = []
26
- @bindings = Hash.new {|h, type| h[type] = type.define(@file)}
27
- @captured_locals = Hash.new {|h, binding| h[binding] = {}}
28
- @self_scope = nil
29
- end
30
-
31
- def error(message, node)
32
- raise CompilationError.new(message, node)
33
- end
34
-
35
- def compile(ast, expression = false)
36
- begin
37
- ast.compile(self, expression)
38
- rescue => ex
39
- raise Mirah::InternalCompilerError.wrap(ex, ast)
40
- end
41
- log "Compilation successful!"
42
- end
43
-
44
- def log(message); JVM.log(message); end
45
-
46
- def toplevel_class
47
- @class = @type.define(@file)
48
- end
49
-
50
- def generate
51
- log "Generating #{output_type}..."
52
- @file.generate do |filename, builder|
53
- log " #{builder.class_name}"
54
- if block_given?
55
- yield filename, builder
56
- else
57
- File.open(filename, 'wb') {|f| f.write(builder.generate)}
58
- end
59
- end
60
- log "...done!"
61
- end
62
-
63
- def define_main(script)
64
- @static = true
65
- @filename = File.basename(script.filename)
66
- classname = JVM.classname_from_filename(@filename)
67
- @type = AST.type(script, classname)
68
- @file = file_builder(@filename)
69
- body = script.body
70
- body = body[0] if body.children.size == 1
71
- if body.class != AST::ClassDefinition
72
- @class = @type.define(@file)
73
- with :method => @class.main do
74
- log "Starting main method"
75
-
76
- @method.start
77
- @current_scope = script.static_scope
78
- declare_locals(@current_scope)
79
- begin_main
80
-
81
- prepare_binding(script) do
82
- body.compile(self, false)
83
- end
84
-
85
- finish_main
86
- @method.stop
87
- end
88
- @class.stop
89
- else
90
- body.compile(self, false)
91
- end
92
-
93
- log "Main method complete!"
94
- end
95
-
96
- def begin_main; end
97
- def finish_main; end
98
-
99
- # arg_types must be an Array
100
- def create_method_builder(name, node, static, exceptions, return_type, arg_types)
101
- @class.build_method(name.to_s, node.visibility, static,
102
- exceptions, return_type, *arg_types)
103
- end
104
-
105
- def base_define_method(node, args_are_types)
106
- name, signature, args = node.name, node.signature, node.arguments.args
107
- if name == "initialize" && node.static?
108
- name = "<clinit>"
109
- end
110
- if args_are_types
111
- arg_types = args.map { |arg| arg.inferred_type } if args
112
- else
113
- arg_types = args
114
- end
115
- arg_types ||= []
116
- return_type = signature[:return]
117
- exceptions = signature[:throws]
118
-
119
- with :static => @static || node.static?, :current_scope => node.static_scope do
120
- method = create_method_builder(name, node, @static, exceptions,
121
- return_type, arg_types)
122
- annotate(method, node.annotations)
123
- yield method, arg_types
124
- end
125
-
126
- arg_types_for_opt = []
127
- args_for_opt = []
128
- if args
129
- args.each do |arg|
130
- if AST::OptionalArgument === arg
131
- new_args = if args_are_types
132
- arg_types_for_opt
133
- else
134
- args_for_opt
135
- end
136
- method = create_method_builder(name, node, @static, exceptions,
137
- return_type, new_args)
138
- with :method => method do
139
- log "Starting new method #{name}(#{arg_types_for_opt})"
140
-
141
- annotate(method, node.annotations)
142
- @method.start
143
-
144
- define_optarg_chain(name, arg,
145
- return_type,
146
- args_for_opt,
147
- arg_types_for_opt)
148
-
149
- @method.stop
150
- end
151
- end
152
- arg_types_for_opt << arg.inferred_type
153
- args_for_opt << arg
154
- end
155
- end
156
- end
157
-
158
- def constructor(node, args_are_types)
159
- args = node.arguments.args || []
160
- arg_types = if args_are_types
161
- args.map { |arg| arg.inferred_type }
162
- else
163
- args
164
- end
165
- exceptions = node.signature[:throws]
166
- method = @class.build_constructor(node.visibility, exceptions, *arg_types)
167
- annotate(method, node.annotations)
168
- with :current_scope => node.static_scope do
169
- yield(method, args)
170
- end
171
- end
172
-
173
- def define_class(class_def, expression)
174
- with(:type => class_def.inferred_type,
175
- :class => class_def.inferred_type.define(@file),
176
- :static => false) do
177
- annotate(@class, class_def.annotations)
178
- class_def.body.compile(self, false) if class_def.body
179
- @class.stop
180
- end
181
- end
182
-
183
- def declare_argument(name, type)
184
- # declare local vars for arguments here
185
- end
186
-
187
- def body(body, expression)
188
- saved_self = @self_scope
189
- if body.kind_of?(Mirah::AST::ScopedBody)
190
- scope = body.static_scope
191
- declare_locals(scope)
192
- if scope != @self_scope
193
- if scope.self_node && scope.self_node != :self
194
- # FIXME This is a horrible hack!
195
- # Instead we should eliminate unused self's.
196
- unless scope.self_type.name == 'mirah.impl.Builtin'
197
- local_assign(
198
- scope, 'self', scope.self_type, false, scope.self_node)
199
- end
200
- end
201
- @self_scope = scope
202
- end
203
- end
204
- # all except the last element in a body of code is treated as a statement
205
- i, last = 0, body.children.size - 1
206
- while i < last
207
- body.children[i].compile(self, false)
208
- i += 1
209
- end
210
- yield body.children[last] if last >= 0
211
- @self_scope = saved_self
212
- end
213
-
214
- def scoped_body(scope, expression)
215
- body(scope, expression)
216
- end
217
-
218
- def scoped_local_name(name, scope=nil)
219
- if scope.nil? || scope == @current_scope
220
- name
221
- else
222
- "#{name}$#{scope.object_id}"
223
- end
224
- end
225
-
226
- def import(short, long)
227
- end
228
-
229
- def fixnum(type, value)
230
- type.literal(method, value)
231
- end
232
- alias float fixnum
233
-
234
- def compile_self
235
- if @self_scope && @self_scope.self_node && @self_scope.self_node != :self
236
- local(@self_scope, 'self', @self_scope.self_type)
237
- else
238
- real_self
239
- end
240
- end
241
-
242
- def get_binding(type)
243
- @bindings[type]
244
- end
245
-
246
- def declared_captures(binding=nil)
247
- @captured_locals[binding || @binding]
248
- end
249
-
250
- def with(vars)
251
- orig_values = {}
252
- begin
253
- vars.each do |name, new_value|
254
- name = "@#{name}"
255
- orig_values[name] = instance_variable_get name
256
- instance_variable_set name, new_value
257
- end
258
- yield
259
- ensure
260
- orig_values.each do |name, value|
261
- instance_variable_set name, value
262
- end
263
- end
264
- end
265
- end
266
- end
267
- end
@@ -1,760 +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 Compiler
32
- class JavaSource < JVMCompilerBase
33
- JVMTypes = Mirah::JVM::Types
34
- attr_accessor :lvalue
35
-
36
- Operators = [
37
- '+', '-', '+@', '-@', '/', '%', '*', '<',
38
- '<=', '==', '!=', '>=', '>',
39
- '<<', '>>', '>>>', '|', '&', '^', '~'
40
- ]
41
- ArrayOps = [
42
- '[]', '[]=', 'length'
43
- ]
44
-
45
- ImplicitReturn = Struct.new(:value)
46
-
47
- def initialize
48
- super
49
- end
50
-
51
- def file_builder(filename)
52
- Mirah::JavaSource::Builder.new(filename, self)
53
- end
54
-
55
- def output_type
56
- "source files"
57
- end
58
-
59
- def define_method(node)
60
- base_define_method(node, false) do |method, _|
61
- with :method => method do
62
- log "Starting new method #{node.name}"
63
- @method.start
64
-
65
- prepare_binding(node) do
66
- declare_locals(node.static_scope)
67
- unless @method.type.nil? || @method.type.void?
68
- self.return(ImplicitReturn.new(node.body))
69
- else
70
- node.body.compile(self, false) if node.body
71
- end
72
- end
73
-
74
- log "Method #{node.name} complete!"
75
- @method.stop
76
- end
77
- end
78
- end
79
-
80
- def annotate(node, annotations)
81
- node.annotate(annotations)
82
- end
83
-
84
- def define_optarg_chain(name, arg, return_type,
85
- args_for_opt, arg_types_for_opt)
86
- # declare all args so they get their values
87
- @method.print "return " unless @method.type.nil? || @method.type.void?
88
- @method.print "this." unless @static
89
- @method.print "#{name}("
90
- @method.print args_for_opt.map(&:name).join(', ')
91
- @method.print ', 'if args_for_opt.size > 0
92
- arg.value.compile(self, true)
93
-
94
- # invoke the next one in the chain
95
- @method.print ");\n"
96
- end
97
-
98
- def constructor(node)
99
- super(node, false) do |method, _|
100
- with :method => method do
101
- @method.start
102
- if node.delegate_args
103
- delegate = if node.calls_super
104
- "super"
105
- else
106
- "this"
107
- end
108
- method.print "#{delegate}("
109
- node.delegate_args.each_with_index do |arg, index|
110
- method.print ', ' unless index == 0
111
- raise "Invalid constructor argument #{arg}" unless arg.expr?(self)
112
- arg.compile(self, true)
113
- end
114
- method.puts ");"
115
- end
116
-
117
- prepare_binding(node) do
118
- declare_locals(node.static_scope)
119
- node.body.compile(self, false) if node.body
120
- end
121
- method.stop
122
- end
123
- end
124
- end
125
-
126
- def prepare_binding(scope)
127
- if scope.has_binding?
128
- type = scope.binding_type
129
- @binding = @bindings[type]
130
- @method.puts "#{type.to_source} $binding = new #{type.to_source}();"
131
- if scope.respond_to? :arguments
132
- scope.arguments.args.each do |param|
133
- if scope.static_scope.captured?(param.name)
134
- captured_local_declare(scope, param.name, param.inferred_type)
135
- @method.puts "$binding.#{param.name} = #{param.name};"
136
- end
137
- end
138
- end
139
- end
140
- begin
141
- yield
142
- ensure
143
- if scope.has_binding?
144
- @binding.stop
145
- @binding = nil
146
- end
147
- end
148
- end
149
-
150
- def define_closure(class_def, expression)
151
- compiler = ClosureCompiler.new(@file, @type, self)
152
- compiler.define_class(class_def, expression)
153
- end
154
-
155
- def return(node)
156
- if @method.type.nil? || @method.type.void?
157
- @method.puts 'return;'
158
- return
159
- end
160
- if node.value.expr?(self)
161
- @method.print 'return '
162
- node.value.compile(self, true)
163
- @method.puts ';'
164
- else
165
- store_value('return ', node.value)
166
- end
167
- end
168
-
169
- def _raise(node)
170
- if node.expr?(self)
171
- @method.print 'throw '
172
- node.compile(self, true)
173
- @method.puts ';'
174
- else
175
- store_value('throw ', node)
176
- end
177
- end
178
-
179
- def rescue(node, expression)
180
- @method.block 'try' do
181
- maybe_store(node.body, expression)
182
- end
183
- node.clauses.each do |clause|
184
- clause.types.each do |type|
185
- name = scoped_local_name(clause.name || 'tmp$ex', clause.static_scope)
186
- @method.declare_local(type, name, false)
187
- @method.block "catch (#{type.to_source} #{name})" do
188
- declare_locals(clause.static_scope)
189
- maybe_store(clause.body, expression)
190
- end
191
- end
192
- end
193
- end
194
-
195
- def ensure(node, expression)
196
- @method.block 'try' do
197
- maybe_store(node.body, expression)
198
- end
199
- @method.block 'finally' do
200
- node.clause.compile(self, false)
201
- end
202
- end
203
-
204
- def line(num)
205
- end
206
-
207
- def declare_local(name, type)
208
- @method.declare_local(type, name)
209
- end
210
-
211
- def declare_field(name, type, annotations, static_field)
212
- @class.declare_field(name, type, @static || static_field, 'private', annotations)
213
- end
214
-
215
- def local(scope, name, type)
216
- name = scoped_local_name(name, scope)
217
- @method.print name
218
- end
219
-
220
- def field(name, type, annotations, static_field)
221
- name = name[1..-1] if name =~ /^@/
222
- declare_field(name, type, annotations, static_field)
223
- @method.print "#{this}.#{name}"
224
- end
225
-
226
- def this(method=nil)
227
- if method && method.static?
228
- method.declaring_class.name
229
- elsif @self_scope && @self_scope.self_node && @self_scope.self_node != :self
230
- scoped_local_name('self', @self_scope)
231
- else
232
- @static ? @class.class_name : 'this'
233
- end
234
- end
235
-
236
- def declare_locals(scope)
237
- scope.locals.each do |name|
238
- full_name = scoped_local_name(name, scope)
239
- unless scope.captured?(name) || method.local?(full_name)
240
- declare_local(full_name, scope.local_type(name))
241
- end
242
- end
243
- end
244
-
245
- def local_assign(scope, name, type, expression, value)
246
- simple = value.expr?(self)
247
- value = value.precompile(self)
248
- name = scoped_local_name(name, scope)
249
- if method.local?(name)
250
- if expression
251
- if simple
252
- @method.print '('
253
- else
254
- @method.print @lvalue
255
- end
256
- end
257
- @method.print "#{name} = "
258
- value.compile(self, true)
259
- if simple && expression
260
- @method.print ')'
261
- else
262
- @method.puts ';'
263
- end
264
- else
265
- @method.declare_local(type, name) do
266
- value.compile(self, true)
267
- end
268
- if expression
269
- @method.puts "#{@lvalue}#{name};"
270
- end
271
- end
272
- end
273
-
274
- def field_declare(name, type, annotations)
275
- name = name[1..-1] if name =~ /^@/
276
- declare_field(name, type, annotations)
277
- end
278
-
279
- def local_declare(scope, name, type)
280
- name = scoped_local_name(name, scope)
281
- declare_local(name, type)
282
- end
283
-
284
- def field_assign(name, type, expression, value, annotations, static_field)
285
- name = name[1..-1] if name =~ /^@/
286
- declare_field(name, type, annotations, static_field)
287
- lvalue = "#{@lvalue if expression}#{this}.#{name} = "
288
- store_value(lvalue, value)
289
- end
290
-
291
- def captured_local_declare(scope, name, type)
292
- unless declared_captures[name]
293
- declared_captures[name] = type
294
- @binding.declare_field(name, type, false, '')
295
- end
296
- end
297
-
298
- def captured_local(scope, name, type)
299
- captured_local_declare(scope, name, type)
300
- @method.print "$binding.#{name}"
301
- end
302
-
303
- def captured_local_assign(node, expression)
304
- scope, name, type = node.containing_scope, node.name, node.inferred_type
305
- captured_local_declare(scope, name, type)
306
- lvalue = "#{@lvalue if expression}$binding.#{name} = "
307
- store_value(lvalue, node.value)
308
- end
309
-
310
- def store_value(lvalue, value)
311
- if value.is_a? String
312
- @method.puts "#{lvalue}#{value};"
313
- elsif value.expr?(self)
314
- @method.print lvalue
315
- value.compile(self, true)
316
- @method.puts ';'
317
- else
318
- with :lvalue => lvalue do
319
- value.compile(self, true)
320
- end
321
- end
322
- end
323
-
324
- def assign(name, value)
325
- store_value("#{name} = ", value)
326
- name
327
- end
328
-
329
- def maybe_store(value, expression)
330
- if expression
331
- store_value(@lvalue, value)
332
- else
333
- value.compile(self, false)
334
- end
335
- end
336
-
337
- def body(body, expression)
338
- super(body, expression) do |last|
339
- maybe_store(last, expression)
340
- end
341
- end
342
-
343
- def scoped_body(scope, expression)
344
- @method.block do
345
- super
346
- end
347
- end
348
-
349
- def branch_expression(node)
350
- node.condition.compile(self, true)
351
- @method.print ' ? ('
352
- if node.body
353
- node.body.compile(self, true)
354
- else
355
- @method.print @method.init_value(node.inferred_type)
356
- end
357
- @method.print ') : ('
358
- if node.else
359
- node.else.compile(self, true)
360
- else
361
- @method.print @method.init_value(node.inferred_type)
362
- end
363
- @method.print ')'
364
- end
365
-
366
- def branch(node, expression)
367
- if expression && node.expr?(self)
368
- return branch_expression(node)
369
- end
370
- predicate = node.condition.predicate.precompile(self)
371
- @method.print 'if ('
372
- predicate.compile(self, true)
373
- @method.block ")" do
374
- if node.body
375
- maybe_store(node.body, expression)
376
- elsif expression
377
- store_value(@lvalue, @method.init_value(node.inferred_type))
378
- end
379
- end
380
- if node.else || expression
381
- @method.block 'else' do
382
- if node.else
383
- maybe_store(node.else, expression)
384
- else
385
- store_value(@lvalue, @method.init_value(node.inferred_type))
386
- end
387
- end
388
- end
389
- end
390
-
391
- def loop(loop, expression)
392
- if loop.redo? || loop.post || !loop.condition.predicate.expr?(self)
393
- loop = ComplexWhileLoop.new(loop, self)
394
- else
395
- loop = SimpleWhileLoop.new(loop, self)
396
- end
397
- with(:loop => loop) do
398
- loop.compile(expression)
399
- end
400
- end
401
-
402
- def expr?(target, params)
403
- !([target] + params).any? {|x| x.kind_of? Mirah::AST::TempValue}
404
- end
405
-
406
- def operator(target, op, params, expression)
407
- simple = expr?(target, params)
408
- if expression && !simple
409
- @method.print @lvalue
410
- end
411
- if params.size == 0
412
- # unary operator
413
- op = op[0,1]
414
- @method.print op
415
- target.compile(self, true)
416
- else
417
- @method.print '('
418
- other = params[0]
419
- target.compile(self, true)
420
- @method.print " #{op} "
421
- other.compile(self, true)
422
- @method.print ')'
423
- end
424
- unless expression && simple
425
- @method.puts ';'
426
- end
427
- end
428
-
429
- def precompile_nodes(nodes)
430
- if nodes.all? {|n| n.expr?(self)}
431
- nodes
432
- else
433
- nodes.map do |node|
434
- tempval = node.precompile(self)
435
- if node == tempval && !node.kind_of?(Mirah::AST::Literal)
436
- tempval = node.temp(self)
437
- end
438
- tempval
439
- end
440
- end
441
- end
442
-
443
- def compile_args(call)
444
- precompile_nodes(call.parameters)
445
- end
446
-
447
- def self_type
448
- type = AST.type(nil, @class.name.tr('/', '.'))
449
- type = type.meta if @static
450
- type
451
- end
452
-
453
- def super_call(call, expression)
454
- super_method_call(this, call, compile_args(call), expression)
455
- end
456
-
457
- def cast(call, expression)
458
- args = compile_args(call)
459
- simple = call.expr?(self)
460
- @method.print @lvalue if expression && !simple
461
- @method.print "((#{call.inferred_type.to_source})("
462
- args.each{|arg| arg.compile(self, true)}
463
- @method.print "))"
464
- @method.puts ';' unless simple && expression
465
- end
466
-
467
- def self_call(call, expression)
468
- if call.cast?
469
- cast(call, expression)
470
- else
471
- type = call.scope.static_scope.self_type
472
- type = type.meta if (@static && type == @type)
473
- params = call.parameters.map do |param|
474
- param.inferred_type
475
- end
476
- method = type.get_method(call.name, params)
477
- method_call(this(method), call, compile_args(call), expression)
478
- end
479
- end
480
-
481
- def call(call, expression)
482
- return cast(call, expression) if call.cast?
483
- if Mirah::AST::Constant === call.target || Mirah::AST::Colon2 === call.target
484
- target = call.target.inferred_type.to_source
485
- else
486
- target = call.precompile_target(self)
487
- end
488
- params = compile_args(call)
489
-
490
- if Operators.include? call.name
491
- operator(target, call.name, params, expression)
492
- elsif call.target.inferred_type.array? && ArrayOps.include?(call.name)
493
- array_op(target, call.name, params, expression)
494
- elsif call.name == 'nil?'
495
- operator(target, '==', ['null'], expression)
496
- else
497
- method_call(target, call, params, expression)
498
- end
499
- end
500
-
501
- def array_op(target, name, args, expression)
502
- simple = expr?(target, args)
503
- index, value = args
504
- if expression && !simple
505
- @method.print @lvalue
506
- end
507
- target.compile(self, true)
508
- if name == 'length'
509
- @method.print '.length'
510
- else
511
- @method.print '['
512
- index.compile(self, true)
513
- @method.print ']'
514
- if name == '[]='
515
- @method.print " = "
516
- value.compile(self, true)
517
- end
518
- end
519
- unless simple && expression
520
- @method.puts ';'
521
- end
522
- end
523
-
524
- def break(node)
525
- error("break outside of loop", node) unless @loop
526
- @loop.break
527
- end
528
-
529
- def next(node)
530
- error("next outside of loop", node) unless @loop
531
- @loop.next
532
- end
533
-
534
- def redo(node)
535
- error("redo outside of loop", node) unless @loop
536
- @loop.redo
537
- end
538
-
539
- # TODO: merge cleanly with method_call logic
540
- def super_method_call(target, call, params, expression)
541
- simple = call.expr?(self)
542
- method = call.method(self)
543
- unless simple || method.return_type.void?
544
- @method.print @lvalue if expression
545
- end
546
- if method.constructor?
547
- @method.print "super("
548
- else
549
- @method.print "super.#{method.name}("
550
- end
551
- params.each_with_index do |param, index|
552
- @method.print ', ' unless index == 0
553
- param.compile(self, true)
554
- end
555
- if simple && expression
556
- @method.print ')'
557
- else
558
- @method.puts ');'
559
- end
560
- if method.return_type.void? && expression
561
- @method.print @lvalue
562
- if method.static?
563
- @method.puts 'null;'
564
- else
565
- target.compile(self, true)
566
- @method.puts ';'
567
- end
568
- end
569
-
570
- end
571
-
572
- def method_call(target, call, params, expression)
573
- simple = call.expr?(self)
574
- method = call.method(self)
575
- unless simple || method.return_type.void?
576
- @method.print @lvalue if expression
577
- end
578
-
579
- # preamble
580
- if method.constructor?
581
- @method.print "new "
582
- target.compile(self, true)
583
- @method.print '('
584
- elsif method.field?
585
- target.compile(self, true)
586
- @method.print ".#{method.name}"
587
- if method.argument_types.size == 1
588
- @method.print " = ("
589
- end
590
- elsif Mirah::JVM::Types::Intrinsic === method
591
- method.call(self, call, expression)
592
- return
593
- else
594
- target.compile(self, true)
595
- @method.print ".#{method.name}("
596
- end
597
-
598
- # args
599
- params.each_with_index do |param, index|
600
- @method.print ', ' unless index == 0
601
- param.compile(self, true)
602
- end
603
-
604
- # postamble
605
- if !method.field? || (method.field? && method.argument_types.size == 1)
606
- if simple && expression
607
- @method.print ')'
608
- else
609
- @method.puts ');'
610
- end
611
- end
612
-
613
- # cleanup
614
- if method.return_type.void? && expression
615
- @method.print @lvalue
616
- if method.static?
617
- @method.puts 'null;'
618
- else
619
- target.compile(self, true)
620
- @method.puts ';'
621
- end
622
- end
623
- end
624
-
625
- def temp(expression, value=nil)
626
- value ||= expression
627
- type = value.inferred_type
628
- if value.expr?(self)
629
- @method.tmp(type) do
630
- value.compile(self, true)
631
- end
632
- else
633
- assign(@method.tmp(type), value)
634
- end
635
- end
636
-
637
- def empty_array(type, size)
638
- sizevar = size.precompile(self)
639
- @method.print "#{@lvalue unless size.expr?(self)}new #{type.name}["
640
- sizevar.compile(self, true)
641
- @method.print ']'
642
- end
643
-
644
- def string(value)
645
- @method.print value.inspect
646
- end
647
-
648
- def boolean(value)
649
- @method.print value ? 'true' : 'false'
650
- end
651
-
652
- def regexp(value, flags = 0)
653
- @method.print "java.util.regex.Pattern.compile("
654
- @method.print value.inspect
655
- @method.print ")"
656
- end
657
-
658
- def array(node, expression)
659
- if expression
660
- # create unmodifiable list from array (simplest way to do this in Java source)
661
- @method.print "java.util.Collections.unmodifiableList(java.util.Arrays.asList("
662
-
663
- # elements, as expressions
664
- comma = false
665
- node.children.each do |n|
666
- @method.print ", " if comma
667
- n.compile(self, true)
668
- comma = true
669
- end
670
-
671
- @method.print("))")
672
- else
673
- # elements, as non-expressions
674
- # TODO: ensure they're all reference types!
675
- node.children.each do |n|
676
- n.compile(self, false)
677
- end
678
- end
679
- end
680
-
681
- def build_string(orig_nodes, expression)
682
- if expression
683
- nodes = precompile_nodes(orig_nodes)
684
- simple = nodes.equal?(orig_nodes)
685
- if !simple
686
- @method.print(lvalue)
687
- end
688
- first = true
689
- unless nodes[0].kind_of?(Mirah::AST::String)
690
- @method.print '""'
691
- first = false
692
- end
693
- nodes.each do |node|
694
- @method.print ' + ' unless first
695
- first = false
696
- node.compile(self, true)
697
- end
698
- @method.puts ';' unless simple
699
- else
700
- orig_nodes.each {|n| n.compile(self, false)}
701
- end
702
- end
703
-
704
- def to_string(body, expression)
705
- body.compile(self, expression)
706
- end
707
-
708
- def null
709
- @method.print 'null'
710
- end
711
-
712
- def binding_reference
713
- @method.print '$binding'
714
- end
715
-
716
- def real_self
717
- @method.print 'this'
718
- end
719
-
720
- def print(node)
721
- value = node.parameters[0]
722
- value = value && value.precompile(self)
723
- if node.println
724
- @method.print "System.out.println("
725
- else
726
- @method.print "System.out.print("
727
- end
728
- value.compile(self, true) if value
729
- @method.puts ');'
730
- end
731
-
732
- class ClosureCompiler < JavaSource
733
- def initialize(file, type, parent)
734
- @file = file
735
- @type = type
736
- @parent = parent
737
- end
738
-
739
- def prepare_binding(scope)
740
- if scope.has_binding?
741
- type = scope.binding_type
742
- @binding = @parent.get_binding(type)
743
- @method.puts("#{type.to_source} $binding = this.binding;")
744
- end
745
- begin
746
- yield
747
- ensure
748
- if scope.has_binding?
749
- @binding = nil
750
- end
751
- end
752
- end
753
-
754
- def declared_captures
755
- @parent.declared_captures(@binding)
756
- end
757
- end
758
- end
759
- end
760
- end