mirah 0.0.7-java → 0.0.8-java

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,63 @@
1
+ module Mirah
2
+ module AST
3
+ begin
4
+ java_import 'mirah.impl.MirahParser'
5
+ rescue NameError
6
+ $CLASSPATH << File.dirname(__FILE__) + '/../../../javalib/mirah-parser.jar'
7
+ java_import 'mirah.impl.MirahParser'
8
+ end
9
+ java_import 'jmeta.ErrorHandler'
10
+
11
+ class MirahErrorHandler
12
+ include ErrorHandler
13
+ def warning(messages, positions)
14
+ print "Warning: "
15
+ messages.each_with_index do |message, i|
16
+ jpos = positions[i]
17
+ if jpos
18
+ dpos = Mirah::Transform::Transformer::JMetaPosition.new(jpos, jpos)
19
+ print "#{message} at "
20
+ Mirah.print_error("", dpos)
21
+ else
22
+ print message
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ def parse(src, filename='dash_e', raise_errors=false, transformer=nil)
29
+ ast = parse_ruby(src, filename)
30
+ transformer ||= Transform::Transformer.new(Mirah::Util::CompilationState.new)
31
+ transformer.filename = filename
32
+ ast = transformer.transform(ast, nil)
33
+ if raise_errors
34
+ transformer.errors.each do |e|
35
+ raise e.cause || e
36
+ end
37
+ end
38
+ ast
39
+ end
40
+ module_function :parse
41
+
42
+ def parse_ruby(src, filename='-')
43
+ raise ArgumentError if src.nil?
44
+ parser = MirahParser.new
45
+ parser.filename = filename
46
+ parser.errorHandler = MirahErrorHandler.new
47
+ begin
48
+ parser.parse(src)
49
+ rescue => ex
50
+ if ex.cause.kind_of? Java::Jmeta::SyntaxError
51
+ ex = SyntaxError.wrap ex.cause, nil
52
+ end
53
+
54
+ if ex.cause.respond_to? :position
55
+ position = ex.cause.position
56
+ Mirah.print_error(ex.cause.message, position)
57
+ end
58
+ raise ex
59
+ end
60
+ end
61
+ module_function :parse_ruby
62
+ end
63
+ end
@@ -0,0 +1,13 @@
1
+ module Mirah
2
+ module Transform
3
+ class Error < Mirah::MirahError
4
+ attr_reader :position
5
+ def initialize(msg, position, cause=nil)
6
+ position = position.position if position.respond_to? :position
7
+ super(msg, position)
8
+ self.cause = cause
9
+ end
10
+ end
11
+ end
12
+ TransformError = Transform::Error
13
+ end
@@ -0,0 +1,761 @@
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 Transform
18
+ class Helper
19
+ java_import 'jmeta.Ast'
20
+ def initialize(transformer)
21
+ @mirah = transformer
22
+ end
23
+
24
+ def position(node)
25
+ @mirah.position(node)
26
+ end
27
+
28
+ def transformer
29
+ @mirah
30
+ end
31
+
32
+ def transform(node, parent)
33
+ @mirah.transform(node, parent)
34
+ end
35
+
36
+ def transform_script(node, parent)
37
+ Mirah::AST::Script.new(parent, position(node)) do |script|
38
+ script.filename = transformer.filename
39
+ [@mirah.transform(node.children[0], script)]
40
+ end
41
+ end
42
+
43
+ def transform_fixnum(node, parent)
44
+ Mirah::AST::fixnum(parent, position(node), node[1])
45
+ end
46
+
47
+ def transform_float(node, parent)
48
+ Mirah::AST::float(parent, position(node), node[1])
49
+ end
50
+
51
+ def transform_true(node, parent)
52
+ Mirah::AST::Boolean.new(parent, position(node), true)
53
+ end
54
+
55
+ def transform_false(node, parent)
56
+ Mirah::AST::Boolean.new(parent, position(node), false)
57
+ end
58
+
59
+ def transform_nil(node, parent)
60
+ Mirah::AST::Null.new(parent, position(node))
61
+ end
62
+
63
+ def transform_self(node, parent)
64
+ Mirah::AST::Self.new(parent, position(node))
65
+ end
66
+
67
+ def transform_string(node, parent)
68
+ Mirah::AST::String.new(parent, position(node), node[1])
69
+ end
70
+
71
+ def transform_symbol(node, parent)
72
+ Mirah::AST::String.new(parent, position(node), node[1])
73
+ end
74
+
75
+ def transform_body(node, parent)
76
+ Mirah::AST::Body.new(parent, position(node)) do |body|
77
+ node.children.map {|child| @mirah.transform(child, body)}
78
+ end
79
+ end
80
+
81
+ def transform_begin(node, parent)
82
+ @mirah.transform(node[1], parent)
83
+ end
84
+
85
+ def transform_break(node, parent)
86
+ Mirah::AST::Break.new(parent, position(node))
87
+ end
88
+
89
+ def transform_arguments(node, parent)
90
+ Mirah::AST::Arguments.new(parent, position(node)) do |args_node|
91
+ node.children.map do |child|
92
+ if child.nil?
93
+ nil
94
+ elsif child.kind_of?(Ast)
95
+ @mirah.transform(child, args_node)
96
+ else
97
+ child.map {|x| @mirah.transform(x, args_node)}
98
+ end
99
+ end
100
+ end
101
+ end
102
+
103
+ def transform_required_argument(node, parent)
104
+ name = node[1]
105
+ name = transform(name, nil) unless name.kind_of?(::String)
106
+ type = node[2]
107
+ type_node = transform(type, parent) if type
108
+ if Mirah::AST::Unquote === name && type.nil?
109
+ name
110
+ else
111
+ Mirah::AST::RequiredArgument.new(parent, position(node), name, type_node)
112
+ end
113
+ end
114
+
115
+ def transform_opt_arg(node, parent)
116
+ name = node[1]
117
+ name = transform(name, nil) unless name.kind_of?(::String)
118
+ type = node[2]
119
+ value = node[3]
120
+ Mirah::AST::OptionalArgument.new(parent, position(node), name) do |optarg|
121
+ [
122
+ type ? transform(type, optarg) : nil,
123
+ transform(value, optarg),
124
+ ]
125
+ end
126
+ end
127
+
128
+ def transform_rest_arg(node, parent)
129
+ name = node[1]
130
+ name = transform(name, nil) unless name.kind_of?(::String)
131
+ type = node[2]
132
+ Mirah::AST::RestArgument.new(parent, position(node), name) do |restarg|
133
+ [type ? transform(type, restarg) : nil]
134
+ end
135
+ end
136
+
137
+ def transform_block_arg(node, parent)
138
+ name = node[1]
139
+ name = transform(name, nil) unless name.kind_of?(::String)
140
+ type = node[2]
141
+ Mirah::AST::BlockArgument.new(parent, position(node), name) do |blkarg|
142
+ [type ? transform(type, blkarg) : nil]
143
+ end
144
+ end
145
+
146
+ def transform_opt_block_arg(node, parent)
147
+ block_arg = transform_block_arg(node, parent)
148
+ block_arg.optional = true
149
+ return block_arg
150
+ end
151
+
152
+ # TODO UnnamedRestArg
153
+
154
+ def transform_sclass(node, parent)
155
+ Mirah::AST::ClassAppendSelf.new(parent, position(node)) do |class_append_self|
156
+ raise "Singleton class not supported" unless node[1][0] == 'Self'
157
+
158
+ [transformer.transform(node[2], class_append_self)]
159
+ end
160
+ end
161
+
162
+ def transform_array(node, parent)
163
+ Mirah::AST::Array.new(parent, position(node)) do |array|
164
+ node.children.map {|child| transformer.transform(child, array)}
165
+ end
166
+ end
167
+
168
+ def transform_attr_assign(node, parent)
169
+ name = node[1]
170
+ target = node[2]
171
+ args = node[3] + [node[4]]
172
+ position = position(node)
173
+ case name
174
+ when '[]='
175
+ Mirah::AST::Call.new(parent, position, name) do |call|
176
+ [
177
+ transformer.transform(target, call),
178
+ args.map {|arg| transformer.transform(arg, call)},
179
+ nil
180
+ ]
181
+ end
182
+ else
183
+ new_name = name[0..-2] + '_set'
184
+ Mirah::AST::Call.new(parent, position, new_name) do |call|
185
+ [
186
+ transformer.transform(target, call),
187
+ args.map {|arg| transformer.transform(arg, call)},
188
+ nil
189
+ ]
190
+ end
191
+ end
192
+ end
193
+
194
+ def transform_class(node, parent)
195
+ cpath = node[1]
196
+ body_node = node[2]
197
+ super_node = node[3]
198
+ if cpath[0] == 'Constant'
199
+ name = cpath[1]
200
+ elsif cpath[0] == 'Unquote'
201
+ name = cpath
202
+ else
203
+ raise "Unsupported class name #{cpath[0]}"
204
+ end
205
+ name = transform(name, nil) unless name.kind_of?(::String)
206
+ Mirah::AST::ClassDefinition.new(parent, position(node),
207
+ name,
208
+ transformer.annotations) do |class_def|
209
+ [
210
+ super_node ? transform(super_node, class_def) : nil,
211
+ body_node ? transform(body_node, class_def) : nil
212
+ ]
213
+ end
214
+ end
215
+
216
+ def transform_def(node, parent)
217
+ name, args_node, type_node, body_node = node[1], node[2], node[3], node[4]
218
+ name = transform(name, nil) unless name.kind_of?(::String)
219
+ position = position(node)
220
+ actual_name = name
221
+ if name =~ /=$/ && name != '[]='
222
+ actual_name = name[0..-2] + '_set'
223
+ end
224
+ if name == 'initialize'
225
+ klass = Mirah::AST::ConstructorDefinition
226
+ else
227
+ klass = Mirah::AST::MethodDefinition
228
+ end
229
+ klass.new(parent,
230
+ position,
231
+ actual_name,
232
+ transformer.annotations) do |defn|
233
+ defn.signature = signature = {:return => nil}
234
+ defn.return_type = transform(type_node, defn) if type_node
235
+ [
236
+ signature,
237
+ args_node ? transformer.transform(args_node, defn) : nil,
238
+ body_node ? transformer.transform(body_node, defn) : nil,
239
+ ]
240
+ end
241
+ end
242
+
243
+ def transform_def_static(node, parent)
244
+ name, args_node, type_node, body_node = node[1], node[2], node[3], node[4]
245
+ name = transform(name, nil) unless name.kind_of?(::String)
246
+ position = position(node)
247
+ actual_name = name
248
+ if name =~ /=$/
249
+ actual_name = name[0..-2] + '_set'
250
+ end
251
+ Mirah::AST::StaticMethodDefinition.new(parent,
252
+ position,
253
+ actual_name,
254
+ transformer.annotations) do |defn|
255
+ defn.signature = signature = {:return => nil}
256
+ defn.return_type = transform(type_node, defn) if type_node
257
+ [
258
+ signature,
259
+ args_node ? transformer.transform(args_node, defn) : nil,
260
+ body_node ? transformer.transform(body_node, defn) : nil,
261
+ ]
262
+ end
263
+ end
264
+
265
+ def transform_fcall(node, parent)
266
+ if node.respond_to?(:declaration?) && node.declaration?
267
+ return Mirah::AST::Noop.new(parent, position(node))
268
+ end
269
+
270
+ name = node[1]
271
+ name = transform(name, nil) unless name.kind_of?(::String)
272
+ args = node[2]
273
+ iter_node = node[3]
274
+ fcall = Mirah::AST::FunctionalCall.new(parent, position(node), name) do |call|
275
+ [
276
+ args ? args.map {|arg| transformer.transform(arg, call)} : [],
277
+ iter_node ? transformer.transform(iter_node, call) : nil
278
+ ]
279
+ end
280
+ macro = Mirah::AST.macro(name)
281
+ if macro
282
+ transformer.expand(fcall, parent, &macro)
283
+ else
284
+ fcall
285
+ end
286
+ end
287
+
288
+ def transform_call(node, parent)
289
+ name = node[1]
290
+ name = transform(name, nil) unless name.kind_of?(::String)
291
+ target = node[2]
292
+ args = node[3]
293
+ args = [args] if args && args[0].kind_of?(String)
294
+ iter_node = node[4]
295
+ position = position(node)
296
+
297
+ actual_name = name
298
+ case actual_name
299
+ when '[]'
300
+ # could be array instantiation
301
+ case target[0]
302
+ when 'Identifier'
303
+ case target[1]
304
+ when 'boolean', 'byte', 'short', 'char', 'int', 'long', 'float', 'double'
305
+ if args.nil? || args.size == 0
306
+ constant = Mirah::AST::Constant.new(parent, position, target[1])
307
+ constant.array = true
308
+ return constant
309
+ elsif args && args.size == 1
310
+ return Mirah::AST::EmptyArray.new(parent, position) do |array|
311
+ [transform(target, array), transform(args[0], array)]
312
+ end
313
+ end
314
+ # TODO look for imported, lower case class names
315
+ end
316
+ when 'Constant'
317
+ if args.nil? || args.size == 0
318
+ constant = Mirah::AST::Constant.new(parent, position, target[1])
319
+ constant.array = true
320
+ return constant
321
+ elsif args && args.size == 1
322
+ return Mirah::AST::EmptyArray.new(parent, position) do |array|
323
+ [transform(target, array), transform(args[0], array)]
324
+ end
325
+ end
326
+ end
327
+ when /=$/
328
+ if name.size > 2 || name =~ /^\w/
329
+ actual_name = name[0..-2] + '_set'
330
+ end
331
+ end
332
+
333
+ Mirah::AST::Call.new(parent, position, actual_name) do |call|
334
+ [
335
+ transformer.transform(target, call),
336
+ args ? args.map {|arg| transformer.transform(arg, call)} : [],
337
+ iter_node ? transformer.transform(iter_node, call) : nil
338
+ ]
339
+ end
340
+ end
341
+
342
+ def transform_constant(node, parent)
343
+ Mirah::AST::Constant.new(parent, position(node), node[1])
344
+ end
345
+
346
+ def transform_colon2const(node, parent)
347
+ name = node[2]
348
+ name = transform(name, nil) unless name.kind_of?(::String)
349
+ target = node[1]
350
+ Mirah::AST::Colon2.new(parent, position(node), name) do |colon2|
351
+ [ transform(target, colon2) ]
352
+ end
353
+ end
354
+
355
+ def transform_identifier(node, parent)
356
+ name = node[1]
357
+ position = position(node)
358
+ if name == 'raise'
359
+ Mirah::AST::Raise.new(parent, position) do
360
+ []
361
+ end
362
+ elsif name == 'null'
363
+ Mirah::AST::Null.new(parent, position)
364
+ elsif ['public', 'private', 'protected'].include?(name)
365
+ Mirah::AST::AccessLevel.new(parent, position, name)
366
+ else
367
+ macro = Mirah::AST.macro(name)
368
+ fcall = Mirah::AST::FunctionalCall.new(parent, position, name) do |call|
369
+ [
370
+ [],
371
+ nil
372
+ ]
373
+ end
374
+ if macro
375
+ transformer.expand(fcall, parent, &macro)
376
+ else
377
+ fcall
378
+ end
379
+ end
380
+ end
381
+
382
+ def transform_local_assign(node, parent)
383
+ name = node[1]
384
+ value_node = node[2]
385
+ position = position(node)
386
+ case value_node[0]
387
+ when 'Symbol', 'Constant'
388
+ Mirah::AST::LocalDeclaration.new(parent, position, name) {|local_decl| [transform(value_node, local_decl)]}
389
+ else
390
+ Mirah::AST::LocalAssignment.new(parent, position, name) {|local| [transform(value_node, local)]}
391
+ end
392
+ end
393
+
394
+ def transform_local(node, parent)
395
+ name = node[1]
396
+ Mirah::AST::Local.new(parent, position(node), name)
397
+ end
398
+
399
+ def transform_iter(node, parent)
400
+ args = node[1]
401
+ body = node[2]
402
+ Mirah::AST::Block.new(parent, position(node)) do |block|
403
+ [
404
+ args ? transformer.transform(args, block) : Mirah::AST::Arguments.new(block, position(node)),
405
+ body ? transformer.transform(body, block) : nil,
406
+ ]
407
+ end
408
+ end
409
+
410
+ def transform_inst_var(node, parent)
411
+ name = node[1]
412
+ name = transform(name, nil) unless name.kind_of?(::String)
413
+ Mirah::AST::Field.new(parent, position(node), name, transformer.annotations)
414
+ end
415
+
416
+ def transform_inst_var_assign(node, parent)
417
+ name = node[1]
418
+ name = transform(name, nil) unless name.kind_of?(::String)
419
+ value_node = node[2]
420
+ position = position(node)
421
+ case value_node[0]
422
+ when 'Symbol', 'Constant'
423
+ Mirah::AST::FieldDeclaration.new(parent, position,
424
+ name, transformer.annotations) do |field_decl|
425
+ [transform(value_node, field_decl)]
426
+ end
427
+ else
428
+ Mirah::AST::FieldAssignment.new(parent, position, name, transformer.annotations) {|field| [transformer.transform(value_node, field)]}
429
+ end
430
+ end
431
+
432
+ def transform_class_var(node, parent)
433
+ name = node[1]
434
+ name = transform(name, nil) unless name.kind_of?(::String)
435
+ Mirah::AST::Field.new(parent, position(node), name, transformer.annotations, true)
436
+ end
437
+
438
+ def transform_class_var_assign(node, parent)
439
+ name = node[1]
440
+ name = transform(name, nil) unless name.kind_of?(::String)
441
+ value_node = node[2]
442
+ position = position(node)
443
+ case value_node[0]
444
+ when 'Symbol', 'Constant'
445
+ Mirah::AST::FieldDeclaration.new(parent, position,
446
+ name, transformer.annotations, true) do |field_decl|
447
+ [transform(value_node, field_decl)]
448
+ end
449
+ else
450
+ Mirah::AST::FieldAssignment.new(parent, position, name, transformer.annotations, true) {|field| [transformer.transform(value_node, field)]}
451
+ end
452
+ end
453
+
454
+ def transform_if(node, parent)
455
+ condition = node[1]
456
+ then_body = node[2]
457
+ else_body = node[3]
458
+ Mirah::AST::If.new(parent, position(node)) do |iff|
459
+ [
460
+ Mirah::AST::Condition.new(iff, position(condition)) {|cond| [transformer.transform(condition, cond)]},
461
+ then_body ? transformer.transform(then_body, iff) : nil,
462
+ else_body ? transformer.transform(else_body, iff) : nil
463
+ ]
464
+ end
465
+ end
466
+
467
+ def transform_zsuper(node, parent)
468
+ Mirah::AST::Super.new(parent, position(node))
469
+ end
470
+
471
+ def transform_super(node, parent)
472
+ args = node[1]
473
+ iter = node[2]
474
+ Mirah::AST::Super.new(parent, position(node)) do |s|
475
+ [args ? args.map {|arg| transformer.transform(arg, s)} : []]
476
+ end
477
+ end
478
+
479
+ def transform_return(node, parent)
480
+ value_node = node[1] if node.size > 1
481
+ Mirah::AST::Return.new(parent, position(node)) do |ret|
482
+ [value_node ? transform(value_node, ret) : nil]
483
+ end
484
+ end
485
+
486
+ def transform_dstring(node, parent)
487
+ Mirah::AST::StringConcat.new(parent, position(node)) do |p|
488
+ node.children.map{|n| transform(n, p)}
489
+ end
490
+ end
491
+
492
+ def transform_ev_string(node, parent)
493
+ Mirah::AST::ToString.new(parent, position(node)) do |p|
494
+ [transform(node[1], p)]
495
+ end
496
+ end
497
+
498
+ def transform_and(node, parent)
499
+ first_node = node[1]
500
+ second_node = node[2]
501
+ Mirah::AST::If.new(parent, position(node)) do |iff|
502
+ [
503
+ Mirah::AST::Condition.new(iff, position(first_node)) {|cond| [transform(first_node, cond)]},
504
+ transform(second_node, iff),
505
+ nil
506
+ ]
507
+ end
508
+ end
509
+
510
+ def transform_or(node, parent)
511
+ first_node = node[1]
512
+ second_node = node[2]
513
+ Mirah::AST::Body.new(parent, position(node)) do |block|
514
+ temp = transformer.tmp
515
+ [
516
+ Mirah::AST::LocalAssignment.new(block, position(first_node), temp) do |l|
517
+ [transform(first_node, l)]
518
+ end,
519
+ Mirah::AST::If.new(parent, position(node)) do |iff|
520
+ [
521
+ Mirah::AST::Condition.new(iff, position(first_node)) do |cond|
522
+ [Mirah::AST::Local.new(cond, position(first_node), temp)]
523
+ end,
524
+ Mirah::AST::Local.new(iff, position(first_node), temp),
525
+ transform(second_node, iff)
526
+ ]
527
+ end
528
+ ]
529
+ end
530
+ end
531
+
532
+ def transform_next(node, parent)
533
+ Mirah::AST::Next.new(parent, position(node))
534
+ end
535
+
536
+ def transform_not(node, parent)
537
+ # TODO it's probably better to keep a not node
538
+ # and actually implement compiling it properly.
539
+ # Bonus points for optimizing branches that use Not's.
540
+ Mirah::AST::If.new(parent, position(node)) do |iff|
541
+ [
542
+ Mirah::AST::Condition.new(iff, position(node)) do |cond|
543
+ [ transform(node[1], cond) ]
544
+ end,
545
+ Mirah::AST::Boolean.new(iff, position(node), false),
546
+ Mirah::AST::Boolean.new(iff, position(node), true)
547
+ ]
548
+ end
549
+ end
550
+
551
+ def transform_redo(node, parent)
552
+ Mirah::AST::Redo.new(parent, position(node))
553
+ end
554
+
555
+ def transform_regex(node, parent)
556
+ contents = node[1]
557
+ modifiers = node[2]
558
+ if contents.size == 1 && contents[0][0] == 'String'
559
+ value = contents[0][1]
560
+ Mirah::AST::Regexp.new(parent, position(node), value)
561
+ else
562
+ raise "Unsupported regex #{node}"
563
+ end
564
+ end
565
+
566
+ def transform_ensure(node, parent)
567
+ Mirah::AST::Ensure.new(parent, position(node)) do |n|
568
+ node.children.map {|c| transform(c, n)}
569
+ end
570
+ end
571
+
572
+ def evaluate_at_start?(node)
573
+ if node[0] =~ /Mod$/ && node[2] && node[2][0] == 'Begin'
574
+ false
575
+ else
576
+ true
577
+ end
578
+ end
579
+
580
+ def transform_while(node, parent)
581
+ condition_node = node[1]
582
+ body_node = node[2]
583
+ Mirah::AST::Loop.new(parent, position(node), evaluate_at_start?(node), false) do |loop|
584
+ [
585
+ Mirah::AST::Condition.new(loop, position(condition_node)) {|cond| [transform(condition_node, cond)]},
586
+ transform(body_node, loop)
587
+ ]
588
+ end
589
+ end
590
+ def transform_while_mod(node, parent)
591
+ transform_while(node, parent)
592
+ end
593
+
594
+ def transform_until(node, parent)
595
+ condition_node = node[1]
596
+ body_node = node[2]
597
+ Mirah::AST::Loop.new(parent, position(node), evaluate_at_start?(node), true) do |loop|
598
+ [
599
+ Mirah::AST::Condition.new(loop, position(condition_node)) {|cond| [transform(condition_node, cond)]},
600
+ transform(body_node, loop)
601
+ ]
602
+ end
603
+ end
604
+ def transform_until_mod(node, parent)
605
+ transform_until(node, parent)
606
+ end
607
+
608
+ def transform_for(node, parent)
609
+ var_node = node[1]
610
+ body_node = node[2]
611
+ iter_node = node[3]
612
+ Mirah::AST::Call.new(parent, position(node), 'each') do |each|
613
+ [
614
+ transformer.transform(iter_node, each),
615
+ [],
616
+ Mirah::AST::Block.new(each, position(body_node)) do |block|
617
+ [
618
+ Mirah::AST::Arguments.new(block, position(var_node)) do |args|
619
+ [
620
+ # TODO support for multiple assignment?
621
+ [Mirah::AST::RequiredArgument.new(args,
622
+ position(var_node),
623
+ var_node[1])
624
+ ]
625
+ ]
626
+ end,
627
+ transformer.transform(body_node, block)
628
+ ]
629
+ end
630
+ ]
631
+ end
632
+ end
633
+
634
+ def transform_rescue(node, parent)
635
+ body_node = node[1]
636
+ clauses = node[2]
637
+ else_node = node[3]
638
+ Mirah::AST::Rescue.new(parent, position(node)) do |node|
639
+ [
640
+ transformer.transform(body_node, node),
641
+ clauses.map {|clause| transformer.transform(clause, node)},
642
+ transformer.transform(else_node, node)
643
+ ]
644
+ end
645
+ end
646
+
647
+ def transform_rescue_clause(node, parent)
648
+ exceptions = node[1]
649
+ var_name = node[2]
650
+ name = transform(var_name, nil) unless var_name.nil? || var_name.kind_of?(::String)
651
+ body = node[3]
652
+ Mirah::AST::RescueClause.new(parent, position(node)) do |clause|
653
+ clause.name = var_name if var_name
654
+ [
655
+ if exceptions.size == 0
656
+ [Mirah::AST::String.new(clause, position(node), 'java.lang.Exception')]
657
+ else
658
+ exceptions.map {|name| Mirah::AST::Constant.new(clause, position(node), name)}
659
+ end,
660
+ body ? transformer.transform(body, clause) : Mirah::AST::Null.new(clause, position(node))
661
+ ]
662
+ end
663
+ end
664
+
665
+ def transform_hash(node, parent)
666
+ Mirah::AST::Call.new(parent, position(node), 'new_hash') do |call|
667
+ [
668
+ Mirah::AST::Builtin.new(call, position(node)),
669
+ [
670
+ Mirah::AST::Array.new(call, position(node)) do |array|
671
+ values = []
672
+ node.children.each do |assoc|
673
+ assoc.children.each do |child|
674
+ values << transform(child, array)
675
+ end
676
+ end
677
+ values
678
+ end
679
+ ]
680
+ ]
681
+ end
682
+ end
683
+
684
+ def transform_op_assign(node, parent)
685
+ target = node[1]
686
+ attribute = node[2]
687
+ op = node[3]
688
+ value = node[4]
689
+ temp = transformer.tmp
690
+ tempval = transformer.tmp
691
+ position = position(node)
692
+ setter = "#{attribute}="
693
+ getter = attribute
694
+ Mirah::AST::Body.new(parent, position) do |body|
695
+ [
696
+ Mirah::AST::LocalAssignment.new(body, position, temp) {|l| transform(target, l)},
697
+ Mirah::AST::LocalAssignment.new(body, position, tempval) do |l|
698
+ Mirah::AST::Call.new(l, position, op) do |op_call|
699
+ [
700
+ Mirah::AST::Call.new(op_call, position, getter) do |get_call|
701
+ [
702
+ Mirah::AST::Local.new(get_call, position, temp),
703
+ []
704
+ ]
705
+ end,
706
+ [transform(value, op_call)],
707
+ ]
708
+ end
709
+ end,
710
+ Mirah::AST::Call.new(body, position, setter) do |set_call|
711
+ [
712
+ Mirah::AST::Local.new(set_call, position, temp),
713
+ [ Mirah::AST::Local.new(set_call, position, tempval) ],
714
+ ]
715
+ end,
716
+ Mirah::AST::Local.new(body, position, tempval),
717
+ ]
718
+ end
719
+ end
720
+
721
+ def transform_unquote(node, parent)
722
+ Mirah::AST::Unquote.new(parent, position(node)) do |unquote|
723
+ [transform(node[1], unquote)]
724
+ end
725
+ end
726
+
727
+ def transform_unquote_assign(node, parent)
728
+ name, value = node[1], node[2]
729
+ Mirah::AST::UnquoteAssign.new(parent, position(node)) do |unquote|
730
+ [transform(name, unquote), transform(value, unquote)]
731
+ end
732
+ end
733
+
734
+ def transform_block_pass(node, parent)
735
+ Mirah::AST::BlockPass.new(parent, position(node)) do |blockpass|
736
+ [transform(node[1], blockpass)]
737
+ end
738
+ end
739
+
740
+ def transform_annotation(node, parent)
741
+ classname = node[1]
742
+ values = if node[2]
743
+ node[2].children
744
+ else
745
+ []
746
+ end
747
+ annotation = Mirah::AST::Annotation.new(parent, position(node)) do |anno|
748
+ [Mirah::AST::String.new(anno, position(node), classname)]
749
+ end
750
+ values.each do |assoc|
751
+ key = assoc[1]
752
+ value = assoc[2]
753
+ name = key[1]
754
+ annotation[name] = transform(value, annotation)
755
+ end
756
+ transformer.add_annotation(annotation)
757
+ return Mirah::AST::Noop.new(parent, position(node))
758
+ end
759
+ end
760
+ end
761
+ end