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
@@ -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