mirah 0.0.4-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. data/History.txt +15 -0
  2. data/README.txt +51 -0
  3. data/Rakefile +86 -0
  4. data/bin/duby +10 -0
  5. data/bin/dubyc +10 -0
  6. data/bin/dubyp +10 -0
  7. data/bin/jrubyp +36 -0
  8. data/bin/mirah +9 -0
  9. data/bin/mirah.cmd +1 -0
  10. data/bin/mirahc +9 -0
  11. data/bin/mirahc.cmd +1 -0
  12. data/bin/mirahp +9 -0
  13. data/bin/mirahp.cmd +1 -0
  14. data/examples/ant/example-build.xml +7 -0
  15. data/examples/appengine/Rakefile +19 -0
  16. data/examples/appengine/Readme +29 -0
  17. data/examples/appengine/src/org/mirah/MirahApp.mirah +57 -0
  18. data/examples/appengine/src/org/mirah/list.dhtml +15 -0
  19. data/examples/appengine/war/WEB-INF/lib/dubydatastore.jar +0 -0
  20. data/examples/bintrees.mirah +66 -0
  21. data/examples/construction.mirah +8 -0
  22. data/examples/dynamic.mirah +17 -0
  23. data/examples/edb.mirah +3 -0
  24. data/examples/fib.mirah +16 -0
  25. data/examples/fields.mirah +22 -0
  26. data/examples/fractal.mirah +55 -0
  27. data/examples/java_thing.mirah +13 -0
  28. data/examples/plugins/appengine/Rakefile +55 -0
  29. data/examples/plugins/appengine/lib/com/google/appengine/ext/duby/db/datastore.rb +375 -0
  30. data/examples/plugins/appengine/src/com/google/appengine/ext/duby/db/Model.duby +336 -0
  31. data/examples/plugins/appengine/test/com/google/appengine/ext/duby/db/ModelTest.duby +113 -0
  32. data/examples/simple_class.mirah +12 -0
  33. data/examples/sort_closure.mirah +7 -0
  34. data/examples/swing.mirah +20 -0
  35. data/examples/tak.mirah +15 -0
  36. data/examples/test.edb +9 -0
  37. data/examples/wiki/Rakefile +18 -0
  38. data/examples/wiki/src/org/mirah/wiki/MirahWiki.duby +324 -0
  39. data/examples/wiki/src/org/mirah/wiki/edit.eduby.html +42 -0
  40. data/examples/wiki/src/org/mirah/wiki/error.eduby.html +2 -0
  41. data/examples/wiki/src/org/mirah/wiki/layout.eduby.html +69 -0
  42. data/examples/wiki/src/org/mirah/wiki/parser.eduby.html +7 -0
  43. data/examples/wiki/src/org/mirah/wiki/view.eduby.html +15 -0
  44. data/examples/wiki/war/WEB-INF/classes/test/HeredocContext.class +0 -0
  45. data/examples/wiki/war/WEB-INF/classes/test/MirahParser.class +0 -0
  46. data/examples/wiki/war/WEB-INF/lib/appengine-api.jar +0 -0
  47. data/examples/wiki/war/WEB-INF/lib/dubydatastore.jar +0 -0
  48. data/examples/wiki/war/WEB-INF/lib/jmeta-runtime.jar +0 -0
  49. data/examples/wiki/war/WEB-INF/lib/pegdown-stubs.jar +0 -0
  50. data/examples/wiki/war/WEB-INF/pegdown.jar +0 -0
  51. data/examples/wiki/war/app.yaml +21 -0
  52. data/examples/wiki/war/public/favicon.ico +0 -0
  53. data/examples/wiki/war/public/images/appengine_duby.png +0 -0
  54. data/examples/wiki/war/public/images/back.gif +0 -0
  55. data/examples/wiki/war/public/images/dir.gif +0 -0
  56. data/examples/wiki/war/public/images/file.gif +0 -0
  57. data/examples/wiki/war/public/javascripts/prettify.js +61 -0
  58. data/examples/wiki/war/public/robots.txt +0 -0
  59. data/examples/wiki/war/public/stylesheets/main.css +156 -0
  60. data/examples/wiki/war/public/stylesheets/prettify.css +1 -0
  61. data/examples/wiki/war/public/stylesheets/sh_style.css +66 -0
  62. data/examples/wiki/war/public/stylesheets/source.css +21 -0
  63. data/examples/wiki/war/public/wmd/images/bg-fill.png +0 -0
  64. data/examples/wiki/war/public/wmd/images/bg.png +0 -0
  65. data/examples/wiki/war/public/wmd/images/blockquote.png +0 -0
  66. data/examples/wiki/war/public/wmd/images/bold.png +0 -0
  67. data/examples/wiki/war/public/wmd/images/code.png +0 -0
  68. data/examples/wiki/war/public/wmd/images/h1.png +0 -0
  69. data/examples/wiki/war/public/wmd/images/hr.png +0 -0
  70. data/examples/wiki/war/public/wmd/images/img.png +0 -0
  71. data/examples/wiki/war/public/wmd/images/italic.png +0 -0
  72. data/examples/wiki/war/public/wmd/images/link.png +0 -0
  73. data/examples/wiki/war/public/wmd/images/ol.png +0 -0
  74. data/examples/wiki/war/public/wmd/images/redo.png +0 -0
  75. data/examples/wiki/war/public/wmd/images/separator.png +0 -0
  76. data/examples/wiki/war/public/wmd/images/ul.png +0 -0
  77. data/examples/wiki/war/public/wmd/images/undo.png +0 -0
  78. data/examples/wiki/war/public/wmd/images/wmd-on.png +0 -0
  79. data/examples/wiki/war/public/wmd/images/wmd.png +0 -0
  80. data/examples/wiki/war/public/wmd/showdown.js +421 -0
  81. data/examples/wiki/war/public/wmd/wmd-base.js +1799 -0
  82. data/examples/wiki/war/public/wmd/wmd-plus.js +311 -0
  83. data/examples/wiki/war/public/wmd/wmd.js +73 -0
  84. data/javalib/JRubyParser.jar +0 -0
  85. data/javalib/dynalang-invoke-0.1.jar +0 -0
  86. data/javalib/mirah-bootstrap.jar +0 -0
  87. data/javalib/mirah-parser.jar +0 -0
  88. data/lib/duby.rb +2 -0
  89. data/lib/mirah.rb +338 -0
  90. data/lib/mirah/appengine_tasks.rb +146 -0
  91. data/lib/mirah/ast.rb +615 -0
  92. data/lib/mirah/ast/call.rb +307 -0
  93. data/lib/mirah/ast/class.rb +311 -0
  94. data/lib/mirah/ast/flow.rb +364 -0
  95. data/lib/mirah/ast/intrinsics.rb +470 -0
  96. data/lib/mirah/ast/literal.rb +154 -0
  97. data/lib/mirah/ast/local.rb +89 -0
  98. data/lib/mirah/ast/method.rb +360 -0
  99. data/lib/mirah/ast/scope.rb +208 -0
  100. data/lib/mirah/ast/structure.rb +226 -0
  101. data/lib/mirah/ast/type.rb +130 -0
  102. data/lib/mirah/compiler.rb +341 -0
  103. data/lib/mirah/env.rb +33 -0
  104. data/lib/mirah/jvm/base.rb +258 -0
  105. data/lib/mirah/jvm/compiler.rb +885 -0
  106. data/lib/mirah/jvm/method_lookup.rb +203 -0
  107. data/lib/mirah/jvm/source_compiler.rb +737 -0
  108. data/lib/mirah/jvm/source_generator/builder.rb +444 -0
  109. data/lib/mirah/jvm/source_generator/loops.rb +110 -0
  110. data/lib/mirah/jvm/source_generator/precompile.rb +188 -0
  111. data/lib/mirah/jvm/source_generator/typer.rb +11 -0
  112. data/lib/mirah/jvm/typer.rb +151 -0
  113. data/lib/mirah/jvm/types.rb +416 -0
  114. data/lib/mirah/jvm/types/basic_types.rb +33 -0
  115. data/lib/mirah/jvm/types/boolean.rb +17 -0
  116. data/lib/mirah/jvm/types/enumerable.rb +65 -0
  117. data/lib/mirah/jvm/types/extensions.rb +86 -0
  118. data/lib/mirah/jvm/types/factory.rb +186 -0
  119. data/lib/mirah/jvm/types/floats.rb +86 -0
  120. data/lib/mirah/jvm/types/integers.rb +171 -0
  121. data/lib/mirah/jvm/types/intrinsics.rb +376 -0
  122. data/lib/mirah/jvm/types/literals.rb +74 -0
  123. data/lib/mirah/jvm/types/methods.rb +614 -0
  124. data/lib/mirah/jvm/types/number.rb +143 -0
  125. data/lib/mirah/nbcompiler.rb +29 -0
  126. data/lib/mirah/plugin/edb.rb +29 -0
  127. data/lib/mirah/plugin/gwt.rb +173 -0
  128. data/lib/mirah/plugin/java.rb +55 -0
  129. data/lib/mirah/transform.rb +266 -0
  130. data/lib/mirah/transform2.rb +728 -0
  131. data/lib/mirah/typer.rb +407 -0
  132. data/lib/mirah_task.rb +107 -0
  133. data/test/test_ast.rb +359 -0
  134. data/test/test_compilation.rb +112 -0
  135. data/test/test_env.rb +42 -0
  136. data/test/test_gwt.rb +58 -0
  137. data/test/test_java_typer.rb +183 -0
  138. data/test/test_javac_compiler.rb +63 -0
  139. data/test/test_jvm_compiler.rb +2607 -0
  140. data/test/test_typer.rb +221 -0
  141. metadata +235 -0
@@ -0,0 +1,154 @@
1
+ module Duby::AST
2
+ class Array < Node
3
+ def initialize(parent, line_number, &block)
4
+ super(parent, line_number, &block)
5
+ end
6
+
7
+ def infer(typer)
8
+ children.each do |kid|
9
+ kid.infer(typer)
10
+ end
11
+ @inferred_type = typer.array_type
12
+ end
13
+ end
14
+
15
+ class Fixnum < Node
16
+ include Literal
17
+
18
+ def initialize(parent, line_number, literal)
19
+ super(parent, line_number)
20
+ @literal = literal
21
+ end
22
+
23
+ def infer(typer)
24
+ resolve_if(typer) {@inferred_type = typer.fixnum_type(@literal)}
25
+ end
26
+
27
+ def ==(other)
28
+ @literal == other.literal
29
+ end
30
+
31
+ def eql?(other)
32
+ self.class == other.class && @literal.eql?(other.literal)
33
+ end
34
+ end
35
+
36
+ class Float < Node
37
+ include Literal
38
+
39
+ def initialize(parent, line_number, literal)
40
+ super(parent, line_number)
41
+ @literal = literal
42
+ end
43
+
44
+ def infer(typer)
45
+ resolve_if(typer) {@inferred_type = typer.float_type(@literal)}
46
+ end
47
+ end
48
+
49
+ class Hash < Node; end
50
+
51
+ class Regexp < Node
52
+ include Literal
53
+
54
+ def initialize(parent, line_number, literal)
55
+ super(parent, line_number)
56
+ @literal = literal
57
+ end
58
+
59
+ def infer(typer)
60
+ return @inferred_type if resolved?
61
+ resolved!
62
+ @inferred_type ||= typer.regexp_type
63
+ end
64
+ end
65
+
66
+ class String < Node
67
+ include Literal
68
+ include Scoped
69
+ include Java::DubyLangCompiler.StringNode
70
+
71
+ def initialize(parent, line_number, literal)
72
+ super(parent, line_number)
73
+ @literal = literal
74
+ end
75
+
76
+ def infer(typer)
77
+ return @inferred_type if resolved?
78
+ resolved!
79
+ @inferred_type ||= typer.string_type
80
+ end
81
+
82
+ def type_reference(typer)
83
+ typer.type_reference(scope, @literal)
84
+ end
85
+
86
+ def toString
87
+ @literal
88
+ end
89
+ end
90
+
91
+ class StringConcat < Node
92
+ def initialize(parent, position, &block)
93
+ super(parent, position, &block)
94
+ end
95
+
96
+ def infer(typer)
97
+ unless resolved?
98
+ resolved = true
99
+ children.each {|node| node.infer(typer); resolved &&= node.resolved?}
100
+ resolved! if resolved
101
+ @inferred_type ||= typer.string_type
102
+ end
103
+ @inferred_type
104
+ end
105
+ end
106
+
107
+ class ToString < Node
108
+ child :body
109
+
110
+ def initialize(parent, position)
111
+ super(parent, position)
112
+ end
113
+
114
+ def infer(typer)
115
+ unless resolved?
116
+ body.infer(typer)
117
+ resolved! if body.resolved?
118
+ @inferred_type ||= typer.string_type
119
+ end
120
+ @inferred_type
121
+ end
122
+ end
123
+
124
+ class Symbol < Node; end
125
+
126
+ class Boolean < Node
127
+ include Literal
128
+
129
+ def initialize(parent, line_number, literal)
130
+ super(parent, line_number)
131
+ @literal = literal
132
+ end
133
+
134
+ def infer(typer)
135
+ return @inferred_type if resolved?
136
+ resolved!
137
+ @inferred_type ||= typer.boolean_type
138
+ end
139
+ end
140
+
141
+ class Null < Node
142
+ include Literal
143
+
144
+ def initialize(parent, line_number)
145
+ super(parent, line_number)
146
+ end
147
+
148
+ def infer(typer)
149
+ return @inferred_type if resolved?
150
+ resolved!
151
+ @inferred_type ||= typer.null_type
152
+ end
153
+ end
154
+ end
@@ -0,0 +1,89 @@
1
+ module Duby::AST
2
+ class LocalDeclaration < Node
3
+ include Named
4
+ include Typed
5
+ include Scoped
6
+
7
+ child :type_node
8
+ attr_accessor :type
9
+
10
+ def initialize(parent, line_number, name, &block)
11
+ super(parent, line_number, &block)
12
+ @name = name
13
+ end
14
+
15
+ def captured?
16
+ scope.static_scope.captured?(name)
17
+ end
18
+
19
+ def infer(typer)
20
+ resolve_if(typer) do
21
+ scope.static_scope << name
22
+ @type = type_node.type_reference(typer)
23
+ end
24
+ end
25
+
26
+ def resolved!(typer)
27
+ typer.learn_local_type(containing_scope, name, @inferred_type)
28
+ super
29
+ end
30
+ end
31
+
32
+ class LocalAssignment < Node
33
+ include Named
34
+ include Valued
35
+ include Scoped
36
+
37
+ child :value
38
+
39
+ def initialize(parent, line_number, name, &block)
40
+ super(parent, line_number, &block)
41
+ @name = name
42
+ end
43
+
44
+ def captured?
45
+ scope.static_scope.captured?(name)
46
+ end
47
+
48
+ def to_s
49
+ "LocalAssignment(name = #{name}, scope = #{scope}, captured = #{captured? == true})"
50
+ end
51
+
52
+ def infer(typer)
53
+ resolve_if(typer) do
54
+ scope.static_scope << name
55
+ typer.infer(value)
56
+ end
57
+ end
58
+
59
+ def resolved!(typer)
60
+ typer.learn_local_type(containing_scope, name, @inferred_type)
61
+ super
62
+ end
63
+ end
64
+
65
+ class Local < Node
66
+ include Named
67
+ include Scoped
68
+
69
+ def initialize(parent, line_number, name)
70
+ super(parent, line_number, [])
71
+ @name = name
72
+ end
73
+
74
+ def captured?
75
+ scope.static_scope.captured?(name)
76
+ end
77
+
78
+ def to_s
79
+ "Local(name = #{name}, scope = #{scope}, captured = #{captured? == true})"
80
+ end
81
+
82
+ def infer(typer)
83
+ resolve_if(typer) do
84
+ scope.static_scope << name
85
+ typer.local_type(containing_scope, name)
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,360 @@
1
+ module Duby::AST
2
+ class Arguments < Node
3
+ child :required
4
+ child :opt_args
5
+ child :rest_arg
6
+ child :required2
7
+ child :block_arg
8
+
9
+ def initialize(parent, line_number, &block)
10
+ super(parent, line_number, &block)
11
+ end
12
+
13
+ def infer(typer)
14
+ unless resolved?
15
+ @inferred_type = args ? args.map {|arg| typer.infer(arg)} : []
16
+ if @inferred_type.all?
17
+ resolved!
18
+ else
19
+ typer.defer(self)
20
+ end
21
+ end
22
+ @inferred_type
23
+ end
24
+
25
+ def arg_types_match(arg_node, child_index)
26
+ if RequiredArgument == arg_node && (child_index == 0 || child_index == 3)
27
+ return true
28
+ else
29
+ return OptionalArgument == arg_node && child_index == 1
30
+ end
31
+ end
32
+
33
+ def validate_child(args, child_index)
34
+ if args.kind_of?(Array)
35
+ args.each_with_index do |arg, arg_index|
36
+ if UnquotedValue === arg
37
+ actual_arg = arg.f_arg
38
+ if arg_types_match(actual_arg, child_index)
39
+ args[arg_index] = actual_arg
40
+ actual_arg.parent = self
41
+ else
42
+ args[arg_index, 1] = []
43
+ merge_args(actual_arg, child_index)
44
+ end
45
+ end
46
+ end
47
+ elsif UnquotedValue == args
48
+ @children[child_index] = nil
49
+ merge_args(args.f_arg, child_index)
50
+ end
51
+ end
52
+
53
+ def merge_args(args, child_index)
54
+ args.parent = self if Argument === args
55
+ case args
56
+ when Arguments
57
+ args.children.each_with_index {|child, i| merge_args(child, i)}
58
+ when Array
59
+ args.each {|arg| merge_args(arg, child_index)}
60
+ when RequiredArgument
61
+ if child_index > 2
62
+ self.required2 << args
63
+ else
64
+ self.required << args
65
+ end
66
+ when OptionalArgument
67
+ self.opt_args << args
68
+ when RestArgument
69
+ raise "Multiple rest args" unless rest_arg.nil?
70
+ self.rest_arg = args
71
+ when BlockArgument
72
+ raise "Multiple block args" unless block_arg.nil?
73
+ self.block_arg = args
74
+ else
75
+ raise "Unknown argument type #{args.class}"
76
+ end
77
+ end
78
+
79
+ def args
80
+ args = (required || []) + (opt_args || [])
81
+ args << block_arg if block_arg
82
+ return args
83
+ end
84
+ end
85
+
86
+ class Argument < Node
87
+ include Typed
88
+
89
+ def resolved!(typer)
90
+ typer.learn_local_type(containing_scope, name, @inferred_type)
91
+ super
92
+ end
93
+ end
94
+
95
+ class RequiredArgument < Argument
96
+ include Named
97
+ include Scoped
98
+ child :type_node
99
+
100
+ def initialize(parent, line_number, name, type=nil)
101
+ super(parent, line_number, [type])
102
+
103
+ @name = name
104
+ end
105
+
106
+ def infer(typer)
107
+ resolve_if(typer) do
108
+ scope.static_scope << name
109
+ # if not already typed, check parent of parent (MethodDefinition)
110
+ # for signature info
111
+ method_def = parent.parent
112
+ signature = method_def.signature
113
+
114
+ if type_node
115
+ signature[name.intern] = type_node.type_reference(typer)
116
+ end
117
+
118
+ # if signature, search for this argument
119
+ signature[name.intern] || typer.local_type(containing_scope, name)
120
+ end
121
+ end
122
+ end
123
+
124
+ class OptionalArgument < Argument
125
+ include Named
126
+ include Scoped
127
+ child :type_node
128
+ child :value
129
+
130
+ def initialize(parent, line_number, name, &block)
131
+ super(parent, line_number, &block)
132
+ @name = name
133
+ end
134
+
135
+ def infer(typer)
136
+ resolve_if(typer) do
137
+ scope.static_scope << name
138
+ # if not already typed, check parent of parent (MethodDefinition)
139
+ # for signature info
140
+ method_def = parent.parent
141
+ signature = method_def.signature
142
+ value_type = value.infer(typer)
143
+ declared_type = type_node.type_reference(typer) if type_node
144
+ signature[name.intern] = declared_type || value_type
145
+ end
146
+ end
147
+ end
148
+
149
+ class RestArgument < Argument
150
+ include Named
151
+ include Scoped
152
+
153
+ def initialize(parent, line_number, name)
154
+ super(parent, line_number)
155
+
156
+ @name = name
157
+ end
158
+
159
+ def infer(typer)
160
+ scope.static_scope << name
161
+ super
162
+ end
163
+ end
164
+
165
+ class BlockArgument < Argument
166
+ include Named
167
+ include Scoped
168
+ attr_accessor :optional
169
+ alias optional? optional
170
+
171
+ def initialize(parent, line_number, name)
172
+ super(parent, line_number)
173
+
174
+ @name = name
175
+ end
176
+
177
+ def infer(typer)
178
+ scope.static_scope << name
179
+ super
180
+ end
181
+ end
182
+
183
+ class MethodDefinition < Node
184
+ include Annotated
185
+ include Named
186
+ include Scope
187
+ include Scoped
188
+ include ClassScoped
189
+ include Binding
190
+
191
+ child :signature
192
+ child :arguments
193
+ child :body
194
+ # TODO change return_type to a child if we remove the 'returns' macro.
195
+ attr_accessor :return_type, :exceptions
196
+
197
+ attr_accessor :defining_class
198
+ attr_accessor :visibility
199
+ attr_accessor :abstract
200
+
201
+ def initialize(parent, line_number, name, annotations=[], &block)
202
+ @annotations = annotations
203
+ super(parent, line_number, &block)
204
+ @name = name
205
+ @visibility = (class_scope && class_scope.current_access_level) || :public
206
+ end
207
+
208
+ def name
209
+ super
210
+ end
211
+
212
+ def infer(typer)
213
+ resolve_if(typer) do
214
+ @defining_class ||= begin
215
+ static_scope.self_type = if static?
216
+ scope.static_scope.self_type.meta
217
+ else
218
+ scope.static_scope.self_type
219
+ end
220
+ end
221
+ @annotations.each {|a| a.infer(typer)} if @annotations
222
+ typer.infer(arguments)
223
+ signature[:return] = @return_type.type_reference(typer) if @return_type
224
+ if @exceptions
225
+ signature[:throws] = @exceptions.map {|e| e.type_reference(typer)}
226
+ end
227
+ typer.infer_signature(self)
228
+ forced_type = signature[:return]
229
+ inferred_type = body ? typer.infer(body) : typer.no_type
230
+
231
+ if inferred_type && arguments.inferred_type.all?
232
+ actual_type = if forced_type.nil?
233
+ inferred_type
234
+ else
235
+ forced_type
236
+ end
237
+ if actual_type.unreachable?
238
+ actual_type = typer.no_type
239
+ end
240
+
241
+ if !abstract? &&
242
+ forced_type != typer.no_type &&
243
+ !actual_type.is_parent(inferred_type)
244
+ raise Duby::Typer::InferenceError.new(
245
+ "Inferred return type %s is incompatible with declared %s" %
246
+ [inferred_type, actual_type], self)
247
+ end
248
+
249
+ signature[:return] = actual_type
250
+ end
251
+ end
252
+ end
253
+
254
+ def resolve_if(typer)
255
+ super(typer) do
256
+ actual_type = type = yield
257
+ argument_types = arguments.inferred_type
258
+ # If we know the return type go ahead and tell the typer
259
+ # even if we can't infer the body yet.
260
+ type ||= signature[:return] if argument_types && argument_types.all?
261
+ if type
262
+ argument_types ||= [Duby::AST.error_type] if type.error?
263
+ typer.learn_method_type(defining_class, name, argument_types, type, signature[:throws])
264
+
265
+ # learn the other overloads as well
266
+ args_for_opt = []
267
+ if arguments.args
268
+ arguments.args.each do |arg|
269
+ if OptionalArgument === arg
270
+ arg_types_for_opt = args_for_opt.map do |arg_for_opt|
271
+ arg_for_opt.infer(typer)
272
+ end
273
+ typer.learn_method_type(defining_class, name, arg_types_for_opt, type, signature[:throws])
274
+ end
275
+ args_for_opt << arg
276
+ end
277
+ end
278
+ end
279
+ actual_type
280
+ end
281
+ end
282
+
283
+ def abstract?
284
+ @abstract || InterfaceDeclaration === class_scope
285
+ end
286
+
287
+ def static?
288
+ scope.static_scope.self_type.meta?
289
+ end
290
+ end
291
+
292
+ class StaticMethodDefinition < MethodDefinition
293
+ def static?
294
+ true
295
+ end
296
+ end
297
+
298
+ class ConstructorDefinition < MethodDefinition
299
+ attr_accessor :delegate_args, :calls_super
300
+
301
+ def initialize(*args)
302
+ super
303
+ extract_delegate_constructor
304
+ end
305
+
306
+ def first_node
307
+ if body.kind_of? Body
308
+ body.children[0]
309
+ else
310
+ body
311
+ end
312
+ end
313
+
314
+ def first_node=(new_node)
315
+ if body.kind_of? Body
316
+ new_node.parent = body
317
+ body.children[0] = new_node
318
+ else
319
+ self.body = new_node
320
+ end
321
+ end
322
+
323
+ def extract_delegate_constructor
324
+ # TODO verify that this constructor exists during type inference.
325
+ possible_delegate = first_node
326
+ if FunctionalCall === possible_delegate &&
327
+ possible_delegate.name == 'initialize'
328
+ @delegate_args = possible_delegate.parameters
329
+ elsif Super === possible_delegate
330
+ @calls_super = true
331
+ @delegate_args = possible_delegate.parameters
332
+ unless @delegate_args
333
+ args = arguments.children.map {|x| x || []}
334
+ @delegate_args = args.flatten.map do |arg|
335
+ Local.new(self, possible_delegate.position, arg.name)
336
+ end
337
+ end
338
+ end
339
+ self.first_node = Noop.new(self, position) if @delegate_args
340
+ end
341
+
342
+ def infer(typer)
343
+ unless @inferred_type
344
+ delegate_args.each {|a| typer.infer(a)} if delegate_args
345
+ end
346
+ super
347
+ end
348
+ end
349
+
350
+ defmacro('returns') do |transformer, fcall, parent|
351
+ fcall.scope.return_type = fcall.parameters[0]
352
+ Noop.new(parent, fcall.position)
353
+ end
354
+
355
+
356
+ defmacro('throws') do |transformer, fcall, parent|
357
+ fcall.scope.exceptions = fcall.parameters
358
+ Noop.new(parent, fcall.position)
359
+ end
360
+ end