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,14 @@
1
+
2
+ def reverse(s:string)
3
+ StringBuilder.new(s).reverse.toString()
4
+ end
5
+
6
+ def palindrome?(s:string)
7
+ s.equals(reverse(s))
8
+ end
9
+
10
+ puts palindrome?("anna") # ==> true
11
+ puts palindrome?("Erik") # ==> false
12
+ puts palindrome?("palindroom-moordnilap") # ==> true
13
+ puts nil # ==> null
14
+
@@ -0,0 +1,9 @@
1
+ x = ""
2
+
3
+ 5.times do
4
+ x = x + "ha"
5
+ end
6
+
7
+ puts x # ==> "hahahahaha"
8
+
9
+
@@ -0,0 +1,6 @@
1
+
2
+ def reverse(s:string)
3
+ StringBuilder.new(s).reverse
4
+ end
5
+
6
+ puts reverse('reversed')
@@ -0,0 +1,20 @@
1
+
2
+
3
+ def rot13 (value:string)
4
+ result = ""
5
+ d = ' '.toCharArray[0]
6
+ value.toCharArray.each do |c|
7
+ testChar = Character.toLowerCase(c)
8
+ if testChar <= 'm'.toCharArray[0] && testChar >= 'a'.toCharArray[0] then
9
+ d = char(c + 13)
10
+ end
11
+ if testChar <= 'z'.toCharArray[0] && testChar >= 'n'.toCharArray[0] then
12
+ d = char(c - 13)
13
+ end
14
+ result += d
15
+ end
16
+ result
17
+ end
18
+
19
+
20
+ puts rot13("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
@@ -0,0 +1,4 @@
1
+
2
+ s = System.console.readLine()
3
+
4
+ puts s
@@ -18,5 +18,5 @@ import java.util.ArrayList
18
18
 
19
19
  list = ArrayList.new [9,5,2,6,8,5,0,3,6,1,8,3,6,4,7,5,0,8,5,6,7,2,3]
20
20
  puts "unsorted: #{list}"
21
- Collections.sort(list) {|a,b| Integer(a).compareTo(b)}
21
+ Collections.sort(list) {|a,b| Integer(a).compareTo(Integer(b))}
22
22
  puts "sorted: #{list}"
Binary file
Binary file
@@ -22,31 +22,26 @@ require 'mirah/typer'
22
22
  require 'mirah/compiler'
23
23
  require 'mirah/env'
24
24
  require 'mirah/errors'
25
- require 'mirah/class_loader'
26
- begin
27
- require 'bitescript'
28
- rescue LoadError
29
- $: << File.dirname(__FILE__) + '/../../bitescript/lib'
30
- require 'bitescript'
31
- end
25
+ require 'bitescript'
26
+
32
27
  require 'mirah/jvm/compiler'
33
28
  require 'mirah/jvm/typer'
34
29
  Dir[File.dirname(__FILE__) + "/mirah/plugin/*"].each {|file| require "#{file}" if file =~ /\.rb$/}
35
- require 'mirah/impl'
36
- require 'mirah/compilation_state'
37
30
  require 'jruby'
38
31
 
32
+ require 'mirah/commands'
33
+
39
34
  module Mirah
40
35
  def self.run(*args)
41
- Impl.new.run(*args)
36
+ Mirah::Commands::Run.new(args).execute
42
37
  end
43
38
 
44
39
  def self.compile(*args)
45
- Impl.new.compile(*args)
40
+ Mirah::Commands::Compile.new(args).execute
46
41
  end
47
42
 
48
43
  def self.parse(*args)
49
- Impl.new.parse(*args)
44
+ Mirah::Commands::Parse.new(args).execute
50
45
  end
51
46
 
52
47
  def self.plugins
@@ -89,7 +84,3 @@ module Mirah
89
84
  end
90
85
  end
91
86
  end
92
-
93
- if __FILE__ == $0
94
- Mirah.run(ARGV[0], *ARGV[1..-1])
95
- end
@@ -37,6 +37,10 @@ module Mirah
37
37
  attr_accessor :newline
38
38
  attr_accessor :inferred_type
39
39
 
40
+ # defines children of a node by name,
41
+ # respecting call order.
42
+ #
43
+ # @param [Symbol] name the name of the child node
40
44
  def self.child(name)
41
45
  @children ||= []
42
46
  index = @children.size
@@ -60,6 +64,13 @@ module Mirah
60
64
  java.util.ArrayList.new(@children)
61
65
  end
62
66
 
67
+ #
68
+ # @param [Mirah::AST::Node] parent the parent node
69
+ # @param [JMetaPosition] position the location in the source code of the node
70
+ # @param [Array] children the list of child nodes
71
+ # @yield [self] yields the node being initialized, expects the list of children as the result.
72
+ # takes priority over the `children` argument.
73
+ #
63
74
  def initialize(parent, position, children = [])
64
75
  JRuby.reference(self.class).setRubyClassAllocator(JRuby.reference(self.class).reified_class)
65
76
  unless parent.nil? || Mirah::AST::Node === parent
@@ -271,6 +282,10 @@ module Mirah
271
282
  end
272
283
  inferred_type
273
284
  end
285
+
286
+ def top_level?
287
+ false
288
+ end
274
289
  end
275
290
 
276
291
 
@@ -356,99 +371,9 @@ module Mirah
356
371
  end
357
372
  end
358
373
 
359
- class Constant < Node
360
- include Named
361
- include Scoped
362
- attr_accessor :array
363
-
364
- def initialize(parent, position, name)
365
- self.name = name
366
- super(parent, position, [])
367
- end
368
-
369
- def infer(typer, expression)
370
- @inferred_type ||= begin
371
- # TODO lookup constant, inline if we're supposed to.
372
- typer.type_reference(scope, name, @array, true)
373
- end
374
- end
375
-
376
- def type_reference(typer)
377
- typer.type_reference(scope, @name, @array)
378
- end
379
- end
380
-
381
- class Self < Node
382
- include Scoped
383
- def infer(typer, expression)
384
- @inferred_type ||= scope.static_scope.self_type
385
- end
386
- end
387
-
388
- class Annotation < Node
389
- attr_reader :values
390
- attr_accessor :runtime
391
- alias runtime? runtime
392
-
393
- child :name_node
394
-
395
- def initialize(parent, position, name=nil, &block)
396
- super(parent, position, &block)
397
- if name
398
- @name = if name.respond_to?(:class_name)
399
- name.class_name
400
- else
401
- name.name
402
- end
403
- end
404
- @values = {}
405
- end
406
-
407
- def name
408
- @name
409
- end
410
-
411
- def type
412
- BiteScript::ASM::Type.getObjectType(@name.tr('.', '/'))
413
- end
414
-
415
- def []=(name, value)
416
- @values[name] = value
417
- end
418
-
419
- def [](name)
420
- @values[name]
421
- end
422
-
423
- def infer(typer, expression)
424
- @inferred ||= begin
425
- @name = name_node.type_reference(typer).name if name_node
426
- @values.each do |name, value|
427
- if Node === value
428
- @values[name] = annotation_value(value, typer)
429
- end
430
- end
431
- true
432
- end
433
- end
434
-
435
- def annotation_value(node, typer)
436
- case node
437
- when String
438
- java.lang.String.new(node.literal)
439
- when Array
440
- node.children.map {|node| annotation_value(node, typer)}
441
- else
442
- # TODO Support other types
443
- ref = value.type_refence(typer)
444
- desc = BiteScript::Signature.class_id(ref)
445
- BiteScript::ASM::Type.getType(desc)
446
- end
447
- end
448
- end
449
-
450
374
  class NodeProxy < DelegateClass(Node)
451
375
  include Java::DubyLangCompiler::Node
376
+ include Java::DubyLangCompiler.Call
452
377
  def __inline__(node)
453
378
  node.parent = parent
454
379
  __setobj__(node)
@@ -646,7 +571,12 @@ module Mirah
646
571
  end
647
572
 
648
573
  def self.unreachable_type
649
- TypeReference::UnreachableType
574
+ factory = type_factory
575
+ if factory
576
+ factory.unreachable_type
577
+ else
578
+ TypeReference::UnreachableType
579
+ end
650
580
  end
651
581
 
652
582
  def self.block_type
@@ -50,11 +50,12 @@ module Mirah::AST
50
50
  def validate_parameters
51
51
  parameters.each_with_index do |child, i|
52
52
  if UnquotedValue === child
53
- child = child.node
54
- child.parent = self
55
- parameters[i] = child
53
+ children = child.nodes
54
+ children.each {|c| c.parent = self}
55
+ parameters[i] = children
56
56
  end
57
57
  end
58
+ parameters.flatten!
58
59
  end
59
60
 
60
61
  def infer(typer, expression)
@@ -169,6 +170,21 @@ module Mirah::AST
169
170
  parameter_types << Mirah::AST.block_type if block
170
171
 
171
172
  unless should_defer
173
+ class_name, array = self.type_name(true)
174
+ if class_name && parameters.size == 1 && typer.known_type(scope, class_name)
175
+ # Support casts to fully-qualified names and inner classes.
176
+ begin
177
+ type = inferred_type = typer.type_reference(scope, class_name, array)
178
+ @inferred_type = type unless (type && type.error?)
179
+ if @inferred_type
180
+ # cast operation
181
+ resolved!
182
+ self.cast = true
183
+ return @inferred_type
184
+ end
185
+ rescue
186
+ end
187
+ end
172
188
  @inferred_type = typer.method_type(receiver_type, name,
173
189
  parameter_types)
174
190
  if @inferred_type.kind_of? InlineCode
@@ -203,6 +219,14 @@ module Mirah::AST
203
219
  end
204
220
 
205
221
  def type_reference(typer)
222
+ class_name, array = type_name
223
+ typer.type_reference(scope, class_name, array)
224
+ end
225
+
226
+ def type_name(force=false)
227
+ if !force && parameters && !parameters.empty?
228
+ return nil
229
+ end
206
230
  if name == "[]"
207
231
  # array type, top should be a constant; find the rest
208
232
  array = true
@@ -216,19 +240,27 @@ module Mirah::AST
216
240
  while !receiver.eql?(old_receiver)
217
241
  old_receiver = receiver
218
242
  case receiver
219
- when Constant, FunctionalCall, Local, Annotation
243
+ when Constant, Local, Annotation
220
244
  elements.unshift(receiver.name)
245
+ when FunctionalCall
246
+ if receiver.parameters.nil? || receiver.parameters.empty?
247
+ elements.unshift(receiver.name)
248
+ else
249
+ return nil, nil
250
+ end
221
251
  when Call
222
- elements.unshift(receiver.name)
223
- receiver = receiver.target
252
+ if receiver.parameters.nil? || receiver.parameters.empty?
253
+ elements.unshift(receiver.name)
254
+ receiver = receiver.target
255
+ else
256
+ return nil, nil
257
+ end
224
258
  when String
225
259
  elements.unshift(receiver.literal)
226
260
  end
227
261
  end
228
262
 
229
- # join and load
230
- class_name = elements.join(".")
231
- typer.type_reference(scope, class_name, array)
263
+ return elements.join("."), array
232
264
  end
233
265
  end
234
266
 
@@ -54,13 +54,13 @@ module Mirah::AST
54
54
  node
55
55
  end
56
56
 
57
- def define_method(position, name, type, *args)
58
- append_node(_define_method(MethodDefinition, position, name, type, args))
57
+ def define_method(position, name, type, *args, &block)
58
+ append_node(_define_method(MethodDefinition, position, name, type, args, &block))
59
59
  end
60
60
 
61
- def define_static_method(position, name, type, *args)
61
+ def define_static_method(position, name, type, *args, &block)
62
62
  append_node(
63
- _define_method(StaticMethodDefinition, position, name, type, args))
63
+ _define_method(StaticMethodDefinition, position, name, type, args, &block))
64
64
  end
65
65
 
66
66
  def define_constructor(position, *args, &block)
@@ -122,6 +122,10 @@ module Mirah::AST
122
122
  end
123
123
  end
124
124
  end
125
+
126
+ def top_level?
127
+ true
128
+ end
125
129
  end
126
130
 
127
131
  defmacro('implements') do |transformer, fcall, parent|
@@ -159,6 +163,10 @@ module Mirah::AST
159
163
  def superclass_node
160
164
  nil
161
165
  end
166
+
167
+ def top_level?
168
+ true
169
+ end
162
170
  end
163
171
 
164
172
  class ClosureDefinition < ClassDefinition
@@ -307,8 +315,6 @@ module Mirah::AST
307
315
  the_scope.self_type = the_scope.self_type.include(typeref)
308
316
  end
309
317
  end
310
-
311
- def compile(compiler, expression); end
312
318
  end
313
319
 
314
320
  defmacro("include") do |transformer, fcall, parent|
@@ -320,4 +326,26 @@ module Mirah::AST
320
326
  end
321
327
  end
322
328
  end
329
+
330
+ class Constant < Node
331
+ include Named
332
+ include Scoped
333
+ attr_accessor :array
334
+
335
+ def initialize(parent, position, name)
336
+ self.name = name
337
+ super(parent, position, [])
338
+ end
339
+
340
+ def infer(typer, expression)
341
+ @inferred_type ||= begin
342
+ # TODO lookup constant, inline if we're supposed to.
343
+ typer.type_reference(scope, name, @array, true)
344
+ end
345
+ end
346
+
347
+ def type_reference(typer)
348
+ typer.type_reference(scope, @name, @array)
349
+ end
350
+ end
323
351
  end
@@ -235,7 +235,7 @@ module Mirah
235
235
  typer.defer(self)
236
236
  return
237
237
  end
238
- if throwable.assignable_from?(arg_type) && !arg_type.meta?
238
+ if throwable.compatible?(arg_type) && !arg_type.meta?
239
239
  resolved!
240
240
  return @inferred_type
241
241
  end
@@ -245,7 +245,7 @@ module Mirah
245
245
  if arg_types.any? {|c| c.nil?}
246
246
  typer.defer(self)
247
247
  else
248
- if arg_types[0] && throwable.assignable_from?(arg_types[0])
248
+ if arg_types[0] && throwable.compatible?(arg_types[0])
249
249
  klass = children.shift
250
250
  else
251
251
  klass = Constant.new(self, position, 'RuntimeException')
@@ -315,20 +315,32 @@ module Mirah
315
315
  class Rescue < Node
316
316
  child :body
317
317
  child :clauses
318
+ child :else_node
319
+
318
320
  def initialize(parent, position, &block)
319
321
  super(parent, position, &block)
320
- @body, @clauses = children
321
322
  end
322
323
 
323
324
  def infer(typer, expression)
324
325
  unless resolved?
325
- types = [typer.infer(body, true )] + clauses.map {|c| typer.infer(c, true)}
326
+ types = []
327
+ body_type = typer.infer(body, else_node.nil?) if body
328
+ else_type = typer.infer(else_node, true) if else_node
329
+ if else_node
330
+ types << else_type
331
+ elsif body
332
+ types << body_type
333
+ end
334
+ types += clauses.map {|c| typer.infer(c, true)}
326
335
  if types.any? {|t| t.nil?}
327
336
  typer.defer(self)
328
337
  else
329
338
  # TODO check types for compatibility (maybe only if an expression)
330
339
  resolved!
331
- @inferred_type = types[0]
340
+ types.each do |type|
341
+ @inferred_type ||= type unless type.unreachable?
342
+ end
343
+ @inferred_type ||= types[0]
332
344
  end
333
345
  end
334
346
  @inferred_type