duby 0.0.2-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.
- data/History.txt +8 -0
- data/README.txt +39 -0
- data/Rakefile +13 -0
- data/bin/duby +9 -0
- data/bin/dubyc +9 -0
- data/bin/dubyp +9 -0
- data/examples/README +16 -0
- data/examples/appengine/Rakefile +72 -0
- data/examples/appengine/Readme +27 -0
- data/examples/appengine/config.ru +7 -0
- data/examples/appengine/lib/duby/plugin/datastore.rb +171 -0
- data/examples/appengine/src/com/google/appengine/ext/duby/db/Model.duby +132 -0
- data/examples/appengine/src/com/ribrdb/DubyApp.duby +28 -0
- data/examples/appengine/src/com/ribrdb/list.dhtml +15 -0
- data/examples/construction.duby +8 -0
- data/examples/edb.duby +3 -0
- data/examples/fib.duby +24 -0
- data/examples/fields.duby +22 -0
- data/examples/fractal.duby +57 -0
- data/examples/java_thing.duby +13 -0
- data/examples/simple_class.duby +12 -0
- data/examples/swing.duby +20 -0
- data/examples/tak.duby +15 -0
- data/examples/test.edb +9 -0
- data/javalib/JRubyParser.jar +0 -0
- data/lib/duby.rb +168 -0
- data/lib/duby/ast.rb +386 -0
- data/lib/duby/ast/call.rb +145 -0
- data/lib/duby/ast/class.rb +154 -0
- data/lib/duby/ast/flow.rb +332 -0
- data/lib/duby/ast/intrinsics.rb +56 -0
- data/lib/duby/ast/literal.rb +97 -0
- data/lib/duby/ast/local.rb +92 -0
- data/lib/duby/ast/method.rb +244 -0
- data/lib/duby/ast/structure.rb +62 -0
- data/lib/duby/ast/type.rb +93 -0
- data/lib/duby/c/compiler.rb +134 -0
- data/lib/duby/compiler.rb +282 -0
- data/lib/duby/jvm/compiler.rb +766 -0
- data/lib/duby/jvm/method_lookup.rb +193 -0
- data/lib/duby/jvm/source_compiler.rb +605 -0
- data/lib/duby/jvm/source_generator/builder.rb +387 -0
- data/lib/duby/jvm/source_generator/loops.rb +110 -0
- data/lib/duby/jvm/source_generator/precompile.rb +170 -0
- data/lib/duby/jvm/source_generator/typer.rb +11 -0
- data/lib/duby/jvm/typer.rb +131 -0
- data/lib/duby/jvm/types.rb +331 -0
- data/lib/duby/jvm/types/basic_types.rb +19 -0
- data/lib/duby/jvm/types/boolean.rb +11 -0
- data/lib/duby/jvm/types/enumerable.rb +63 -0
- data/lib/duby/jvm/types/factory.rb +155 -0
- data/lib/duby/jvm/types/floats.rb +70 -0
- data/lib/duby/jvm/types/integers.rb +110 -0
- data/lib/duby/jvm/types/intrinsics.rb +230 -0
- data/lib/duby/jvm/types/literals.rb +82 -0
- data/lib/duby/jvm/types/methods.rb +381 -0
- data/lib/duby/jvm/types/number.rb +92 -0
- data/lib/duby/nbcompiler.rb +29 -0
- data/lib/duby/old/compiler_old.rb +845 -0
- data/lib/duby/old/declaration.rb +72 -0
- data/lib/duby/old/mapper.rb +72 -0
- data/lib/duby/old/signature.rb +52 -0
- data/lib/duby/old/typer_old.rb +163 -0
- data/lib/duby/plugin/edb.rb +25 -0
- data/lib/duby/plugin/java.rb +42 -0
- data/lib/duby/plugin/math.rb +84 -0
- data/lib/duby/transform.rb +1028 -0
- data/lib/duby/typer.rb +369 -0
- data/test/TestUser.class +0 -0
- data/test/test_ast.rb +391 -0
- data/test/test_compilation.rb +98 -0
- data/test/test_java_typer.rb +199 -0
- data/test/test_javac_compiler.rb +58 -0
- data/test/test_jvm_compiler.rb +1770 -0
- data/test/test_math_plugin.rb +87 -0
- data/test/test_typer.rb +246 -0
- metadata +156 -0
@@ -0,0 +1,145 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
|
3
|
+
module Duby::AST
|
4
|
+
class NodeProxy < DelegateClass(Node)
|
5
|
+
def __inline__(node)
|
6
|
+
node.parent = parent
|
7
|
+
__setobj__(node)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class FunctionalCall < Node
|
12
|
+
include Named
|
13
|
+
attr_accessor :parameters, :block, :cast, :inlined, :proxy
|
14
|
+
alias cast? cast
|
15
|
+
|
16
|
+
def self.new(*args, &block)
|
17
|
+
real_node = super
|
18
|
+
real_node.proxy = NodeProxy.new(real_node)
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize(parent, line_number, name, &kids)
|
22
|
+
super(parent, line_number, &kids)
|
23
|
+
@parameters, @block = children
|
24
|
+
@name = name
|
25
|
+
@cast = false
|
26
|
+
end
|
27
|
+
|
28
|
+
def infer(typer)
|
29
|
+
@self_type ||= typer.self_type
|
30
|
+
|
31
|
+
unless @inferred_type
|
32
|
+
receiver_type = @self_type
|
33
|
+
should_defer = false
|
34
|
+
|
35
|
+
parameter_types = parameters.map do |param|
|
36
|
+
typer.infer(param) || should_defer = true
|
37
|
+
end
|
38
|
+
|
39
|
+
parameter_types << Duby::AST.block_type if @block
|
40
|
+
|
41
|
+
unless should_defer
|
42
|
+
if parameters.size == 1 && typer.known_types[name]
|
43
|
+
# cast operation
|
44
|
+
resolved!
|
45
|
+
self.cast = true
|
46
|
+
@inferred_type = typer.known_types[name]
|
47
|
+
else
|
48
|
+
@inferred_type = typer.method_type(receiver_type, name,
|
49
|
+
parameter_types)
|
50
|
+
if @inferred_type.kind_of? InlineCode
|
51
|
+
@inlined = @inferred_type.inline(typer.transformer, self)
|
52
|
+
proxy.__inline__(@inlined)
|
53
|
+
return proxy.infer(typer)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
@inferred_type ? resolved! : typer.defer(proxy)
|
59
|
+
end
|
60
|
+
|
61
|
+
@inferred_type
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class Call < Node
|
66
|
+
include Named
|
67
|
+
attr_accessor :target, :parameters, :block, :inlined, :proxy
|
68
|
+
|
69
|
+
def self.new(*args, &block)
|
70
|
+
real_node = super
|
71
|
+
real_node.proxy = NodeProxy.new(real_node)
|
72
|
+
end
|
73
|
+
|
74
|
+
def initialize(parent, line_number, name, &kids)
|
75
|
+
super(parent, line_number, children, &kids)
|
76
|
+
@target, @parameters, @block = children
|
77
|
+
@name = name
|
78
|
+
end
|
79
|
+
|
80
|
+
def infer(typer)
|
81
|
+
unless @inferred_type
|
82
|
+
receiver_type = typer.infer(target)
|
83
|
+
should_defer = receiver_type.nil?
|
84
|
+
parameter_types = parameters.map do |param|
|
85
|
+
typer.infer(param) || should_defer = true
|
86
|
+
end
|
87
|
+
|
88
|
+
parameter_types << Duby::AST.block_type if @block
|
89
|
+
|
90
|
+
unless should_defer
|
91
|
+
@inferred_type = typer.method_type(receiver_type, name,
|
92
|
+
parameter_types)
|
93
|
+
if @inferred_type.kind_of? InlineCode
|
94
|
+
@inlined = @inferred_type.inline(typer.transformer, self)
|
95
|
+
proxy.__inline__(@inlined)
|
96
|
+
return proxy.infer(typer)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
@inferred_type ? resolved! : typer.defer(proxy)
|
101
|
+
end
|
102
|
+
|
103
|
+
@inferred_type
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
class Super < Node
|
108
|
+
include Named
|
109
|
+
attr_accessor :parameters, :method, :cast
|
110
|
+
alias :cast? :cast
|
111
|
+
|
112
|
+
def initialize(parent, line_number)
|
113
|
+
super(parent, line_number)
|
114
|
+
@parameters = children[0]
|
115
|
+
@call_parent = parent
|
116
|
+
@call_parent = (@call_parent = @call_parent.parent) until MethodDefinition === @call_parent
|
117
|
+
@cast = false
|
118
|
+
end
|
119
|
+
|
120
|
+
def name
|
121
|
+
@call_parent.name
|
122
|
+
end
|
123
|
+
|
124
|
+
def infer(typer)
|
125
|
+
@self_type ||= typer.self_type.superclass
|
126
|
+
|
127
|
+
unless @inferred_type
|
128
|
+
receiver_type = @call_parent.defining_class
|
129
|
+
should_defer = receiver_type.nil?
|
130
|
+
parameter_types = parameters.map do |param|
|
131
|
+
typer.infer(param) || should_defer = true
|
132
|
+
end
|
133
|
+
|
134
|
+
unless should_defer
|
135
|
+
@inferred_type = typer.method_type(receiver_type, name,
|
136
|
+
parameter_types)
|
137
|
+
end
|
138
|
+
|
139
|
+
@inferred_type ? resolved! : typer.defer(self)
|
140
|
+
end
|
141
|
+
|
142
|
+
@inferred_type
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
module Duby::AST
|
2
|
+
class ClassDefinition < Node
|
3
|
+
include Annotated
|
4
|
+
include Named
|
5
|
+
include Scope
|
6
|
+
attr_accessor :superclass, :body, :interfaces
|
7
|
+
|
8
|
+
def initialize(parent, line_number, name, annotations=[], &block)
|
9
|
+
@annotations = annotations
|
10
|
+
@interfaces = []
|
11
|
+
@name = name
|
12
|
+
if Duby::AST.type_factory.respond_to? :declare_type
|
13
|
+
Duby::AST.type_factory.declare_type(self)
|
14
|
+
end
|
15
|
+
super(parent, line_number, &block)
|
16
|
+
@superclass, @body = children
|
17
|
+
end
|
18
|
+
|
19
|
+
def infer(typer)
|
20
|
+
unless resolved?
|
21
|
+
@inferred_type ||= typer.define_type(name, superclass, @interfaces) do
|
22
|
+
if body
|
23
|
+
typer.infer(body)
|
24
|
+
else
|
25
|
+
typer.no_type
|
26
|
+
end
|
27
|
+
end
|
28
|
+
@inferred_type ? resolved! : typer.defer(self)
|
29
|
+
end
|
30
|
+
|
31
|
+
@inferred_type
|
32
|
+
end
|
33
|
+
|
34
|
+
def implements(*types)
|
35
|
+
raise ArgumentError if types.any? {|x| x.nil?}
|
36
|
+
@interfaces.concat types
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
defmacro('implements') do |transformer, fcall, parent|
|
41
|
+
interfaces = fcall.args_node.child_nodes.map do |interface|
|
42
|
+
interface.type_reference(parent)
|
43
|
+
end
|
44
|
+
parent.parent.implements(*interfaces)
|
45
|
+
Noop.new(parent, fcall.position)
|
46
|
+
end
|
47
|
+
|
48
|
+
class InterfaceDeclaration < ClassDefinition
|
49
|
+
attr_accessor :superclass, :body, :interfaces
|
50
|
+
|
51
|
+
def initialize(parent, line_number, name, annotations)
|
52
|
+
super(parent, line_number, name, annotations) {|p| }
|
53
|
+
@interfaces = []
|
54
|
+
@name = name
|
55
|
+
@children = yield(self)
|
56
|
+
@interfaces, @body = children
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
defmacro('interface') do |transformer, fcall, parent|
|
61
|
+
raise "Interface name required" unless fcall.args_node
|
62
|
+
interfaces = fcall.args_node.child_nodes.to_a
|
63
|
+
interface_name = interfaces.shift
|
64
|
+
if (JRubyAst::CallNode === interface_name &&
|
65
|
+
interface_name.args_node.size == 1)
|
66
|
+
interfaces.unshift(interface_name.args_node.get(0))
|
67
|
+
interface_name = interface_name.receiver_node
|
68
|
+
end
|
69
|
+
raise 'Interface body required' unless fcall.iter_node
|
70
|
+
InterfaceDeclaration.new(parent, fcall.position,
|
71
|
+
interface_name.name,
|
72
|
+
transformer.annotations) do |interface|
|
73
|
+
[interfaces.map {|p| p.type_reference(interface)},
|
74
|
+
if fcall.iter_node.body_node
|
75
|
+
transformer.transform(fcall.iter_node.body_node, interface)
|
76
|
+
end
|
77
|
+
]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
class FieldDeclaration < Node
|
82
|
+
include Annotated
|
83
|
+
include Named
|
84
|
+
include ClassScoped
|
85
|
+
include Typed
|
86
|
+
|
87
|
+
def initialize(parent, line_number, name, annotations=[], &block)
|
88
|
+
@annotations = annotations
|
89
|
+
super(parent, line_number, &block)
|
90
|
+
@name = name
|
91
|
+
@type = children[0]
|
92
|
+
end
|
93
|
+
|
94
|
+
def infer(typer)
|
95
|
+
unless resolved?
|
96
|
+
resolved!
|
97
|
+
@inferred_type = typer.known_types[type]
|
98
|
+
if @inferred_type
|
99
|
+
resolved!
|
100
|
+
typer.learn_field_type(scope, name, @inferred_type)
|
101
|
+
else
|
102
|
+
typer.defer(self)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
@inferred_type
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
class FieldAssignment < Node
|
110
|
+
include Annotated
|
111
|
+
include Named
|
112
|
+
include Valued
|
113
|
+
include ClassScoped
|
114
|
+
|
115
|
+
def initialize(parent, line_number, name, annotations=[], &block)
|
116
|
+
@annotations = annotations
|
117
|
+
super(parent, line_number, &block)
|
118
|
+
@value = children[0]
|
119
|
+
@name = name
|
120
|
+
end
|
121
|
+
|
122
|
+
def infer(typer)
|
123
|
+
unless resolved?
|
124
|
+
@inferred_type = typer.learn_field_type(scope, name, typer.infer(value))
|
125
|
+
|
126
|
+
@inferred_type ? resolved! : typer.defer(self)
|
127
|
+
end
|
128
|
+
|
129
|
+
@inferred_type
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
class Field < Node
|
134
|
+
include Annotated
|
135
|
+
include Named
|
136
|
+
include ClassScoped
|
137
|
+
|
138
|
+
def initialize(parent, line_number, name, annotations=[], &block)
|
139
|
+
@annotations = annotations
|
140
|
+
super(parent, line_number, &block)
|
141
|
+
@name = name
|
142
|
+
end
|
143
|
+
|
144
|
+
def infer(typer)
|
145
|
+
unless resolved?
|
146
|
+
@inferred_type = typer.field_type(scope, name)
|
147
|
+
|
148
|
+
@inferred_type ? resolved! : typer.defer(self)
|
149
|
+
end
|
150
|
+
|
151
|
+
@inferred_type
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
@@ -0,0 +1,332 @@
|
|
1
|
+
module Duby
|
2
|
+
module AST
|
3
|
+
class Condition < Node
|
4
|
+
attr_accessor :predicate
|
5
|
+
|
6
|
+
def initialize(parent, line_number, &block)
|
7
|
+
super(parent, line_number, &block)
|
8
|
+
@predicate = children[0]
|
9
|
+
end
|
10
|
+
|
11
|
+
def infer(typer)
|
12
|
+
unless resolved?
|
13
|
+
@inferred_type = typer.infer(predicate)
|
14
|
+
if @inferred_type && !@inferred_type.primitive?
|
15
|
+
call = Call.new(parent, position, '!=') do |call|
|
16
|
+
@predicate.parent = call
|
17
|
+
[@predicate, [Null.new(call, position)]]
|
18
|
+
end
|
19
|
+
@predicate = children[0] = call
|
20
|
+
@inferred_type = typer.infer(predicate)
|
21
|
+
end
|
22
|
+
|
23
|
+
@inferred_type ? resolved! : typer.defer(self)
|
24
|
+
end
|
25
|
+
|
26
|
+
@inferred_type
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class If < Node
|
31
|
+
attr_accessor :condition, :body, :else
|
32
|
+
|
33
|
+
def initialize(parent, line_number, &block)
|
34
|
+
super(parent, line_number, &block)
|
35
|
+
@condition, @body, @else = children
|
36
|
+
end
|
37
|
+
|
38
|
+
def infer(typer)
|
39
|
+
unless resolved?
|
40
|
+
condition_type = typer.infer(condition)
|
41
|
+
unless condition_type
|
42
|
+
typer.defer(condition)
|
43
|
+
end
|
44
|
+
|
45
|
+
# condition type is unrelated to body types, so we proceed with bodies
|
46
|
+
then_type = typer.infer(body) if body
|
47
|
+
|
48
|
+
if !then_type
|
49
|
+
# attempt to determine else branch
|
50
|
+
if self.else
|
51
|
+
else_type = typer.infer(self.else)
|
52
|
+
|
53
|
+
if !else_type
|
54
|
+
# we have neither type, defer until later
|
55
|
+
typer.defer(self)
|
56
|
+
else
|
57
|
+
# we have else but not then, defer only then and use else type for now
|
58
|
+
@inferred_type = else_type
|
59
|
+
typer.defer(self)
|
60
|
+
end
|
61
|
+
else
|
62
|
+
# no then type could be inferred and no else body, defer for now
|
63
|
+
typer.defer(self)
|
64
|
+
end
|
65
|
+
else
|
66
|
+
if self.else
|
67
|
+
else_type = typer.infer(self.else)
|
68
|
+
|
69
|
+
if !else_type
|
70
|
+
# we determined a then type, so we use that and defer the else body
|
71
|
+
@inferred_type = then_type
|
72
|
+
typer.defer(self)
|
73
|
+
else
|
74
|
+
# both then and else inferred, ensure they're compatible
|
75
|
+
if then_type.compatible?(else_type)
|
76
|
+
# types are compatible...if condition is resolved, we're done
|
77
|
+
@inferred_type = then_type.narrow(else_type)
|
78
|
+
resolved! if condition_type
|
79
|
+
else
|
80
|
+
raise Typer::InferenceError.new("if statement with incompatible result types")
|
81
|
+
end
|
82
|
+
end
|
83
|
+
else
|
84
|
+
# only then and type inferred, we're 100% resolved
|
85
|
+
@inferred_type = then_type
|
86
|
+
resolved! if condition_type
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
@inferred_type
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
class Loop < Node
|
96
|
+
attr_accessor :init, :condition, :pre, :post, :body
|
97
|
+
attr_accessor :check_first, :negative, :redo
|
98
|
+
|
99
|
+
def initialize(parent, position, check_first, negative, &block)
|
100
|
+
@check_first = check_first
|
101
|
+
@negative = negative
|
102
|
+
@init = Body.new(self, position)
|
103
|
+
@pre = Body.new(self, position)
|
104
|
+
@post = Body.new(self, position)
|
105
|
+
super(parent, position, &block)
|
106
|
+
@condition, @body = @children
|
107
|
+
end
|
108
|
+
|
109
|
+
def infer(typer)
|
110
|
+
unless resolved?
|
111
|
+
child_types = children.map do |c|
|
112
|
+
if c.nil? || (Body === c && c.empty?)
|
113
|
+
typer.no_type
|
114
|
+
else
|
115
|
+
typer.infer(c)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
if child_types.any? {|t| t.nil?}
|
119
|
+
typer.defer(self)
|
120
|
+
else
|
121
|
+
resolved!
|
122
|
+
@inferred_type = typer.null_type
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
@inferred_type
|
127
|
+
end
|
128
|
+
|
129
|
+
def children
|
130
|
+
[init, condition, pre, post, body]
|
131
|
+
end
|
132
|
+
|
133
|
+
def check_first?; @check_first; end
|
134
|
+
def negative?; @negative; end
|
135
|
+
|
136
|
+
def redo?
|
137
|
+
if @redo.nil?
|
138
|
+
nodes = @children.dup
|
139
|
+
until nodes.empty?
|
140
|
+
node = nodes.shift
|
141
|
+
while node.respond_to?(:inlined) && node.inlined
|
142
|
+
node = node.inlined
|
143
|
+
end
|
144
|
+
next if node.nil? || Loop === node
|
145
|
+
if Redo === node
|
146
|
+
return @redo = true
|
147
|
+
end
|
148
|
+
nodes.insert(-1, *node.children.flatten)
|
149
|
+
end
|
150
|
+
return @redo = false
|
151
|
+
else
|
152
|
+
@redo
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def init?
|
157
|
+
@init && !(@init.kind_of?(Body) && @init.empty?)
|
158
|
+
end
|
159
|
+
|
160
|
+
def pre?
|
161
|
+
@pre && !(@pre.kind_of?(Body) && @pre.empty?)
|
162
|
+
end
|
163
|
+
|
164
|
+
def post?
|
165
|
+
@post && !(@post.kind_of?(Body) && @post.empty?)
|
166
|
+
end
|
167
|
+
|
168
|
+
def to_s
|
169
|
+
"Loop(check_first = #{check_first?}, negative = #{negative?})"
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
class Not < Node
|
174
|
+
def initialize(parent, line_number, &block)
|
175
|
+
super(parent, line_number, &block)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
class Return < Node
|
180
|
+
include Valued
|
181
|
+
|
182
|
+
def initialize(parent, line_number, &block)
|
183
|
+
super(parent, line_number, &block)
|
184
|
+
@value = children[0]
|
185
|
+
end
|
186
|
+
|
187
|
+
def infer(typer)
|
188
|
+
unless resolved?
|
189
|
+
@inferred_type = typer.infer(value)
|
190
|
+
|
191
|
+
(@inferred_type && value.resolved?) ? resolved! : typer.defer(self)
|
192
|
+
end
|
193
|
+
|
194
|
+
@inferred_type
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
class Break < Node;
|
199
|
+
def infer(typer)
|
200
|
+
unless resolved?
|
201
|
+
resolved!
|
202
|
+
@inferred_type = typer.null_type
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
class Next < Break; end
|
208
|
+
|
209
|
+
class Redo < Break; end
|
210
|
+
|
211
|
+
class Raise < Node
|
212
|
+
include Valued
|
213
|
+
|
214
|
+
def initialize(parent, line_number, &block)
|
215
|
+
super(parent, line_number, &block)
|
216
|
+
end
|
217
|
+
|
218
|
+
def infer(typer)
|
219
|
+
unless resolved?
|
220
|
+
@inferred_type = AST.unreachable_type
|
221
|
+
throwable = AST.type('java.lang.Throwable')
|
222
|
+
if children.size == 1
|
223
|
+
arg_type = typer.infer(children[0])
|
224
|
+
unless arg_type
|
225
|
+
typer.defer(self)
|
226
|
+
return
|
227
|
+
end
|
228
|
+
if throwable.assignable_from?(arg_type) && !arg_type.meta?
|
229
|
+
@exception = children[0]
|
230
|
+
resolved!
|
231
|
+
return @inferred_type
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
arg_types = children.map {|c| typer.infer(c)}
|
236
|
+
if arg_types.any? {|c| c.nil?}
|
237
|
+
typer.defer(self)
|
238
|
+
else
|
239
|
+
if arg_types[0] && throwable.assignable_from?(arg_types[0])
|
240
|
+
klass = children.shift
|
241
|
+
else
|
242
|
+
klass = Constant.new(self, position, 'RuntimeException')
|
243
|
+
end
|
244
|
+
@exception = Call.new(self, position, 'new') do
|
245
|
+
[klass, children, nil]
|
246
|
+
end
|
247
|
+
resolved!
|
248
|
+
@children = [@exception]
|
249
|
+
typer.infer(@exception)
|
250
|
+
end
|
251
|
+
end
|
252
|
+
@inferred_type
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
defmacro('raise') do |transformer, fcall, parent|
|
257
|
+
Raise.new(parent, fcall.position) do |raise_node|
|
258
|
+
if fcall.args_node
|
259
|
+
fcall.args_node.child_nodes.map do |arg|
|
260
|
+
transformer.transform(arg, raise_node)
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
class RescueClause < Node
|
267
|
+
include Scoped
|
268
|
+
attr_accessor :types, :body, :name, :type
|
269
|
+
|
270
|
+
def initialize(parent, position, &block)
|
271
|
+
super(parent, position, &block)
|
272
|
+
@types, @body = children
|
273
|
+
end
|
274
|
+
|
275
|
+
def infer(typer)
|
276
|
+
unless resolved?
|
277
|
+
if name
|
278
|
+
orig_type = typer.local_type(scope, name)
|
279
|
+
# TODO find the common parent Throwable
|
280
|
+
@type = types.size == 1 ? types[0] : AST.type('java.lang.Throwable')
|
281
|
+
typer.learn_local_type(scope, name, @type)
|
282
|
+
end
|
283
|
+
@inferred_type = typer.infer(body)
|
284
|
+
|
285
|
+
(@inferred_type && body.resolved?) ? resolved! : typer.defer(self)
|
286
|
+
typer.local_type_hash(scope)[name] = orig_type if name
|
287
|
+
end
|
288
|
+
|
289
|
+
@inferred_type
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
class Rescue < Node
|
294
|
+
attr_accessor :body, :clauses
|
295
|
+
def initialize(parent, position, &block)
|
296
|
+
super(parent, position, &block)
|
297
|
+
@body, @clauses = children
|
298
|
+
end
|
299
|
+
|
300
|
+
def infer(typer)
|
301
|
+
unless resolved?
|
302
|
+
types = [typer.infer(body)] + clauses.map {|c| typer.infer(c)}
|
303
|
+
if types.any? {|t| t.nil?}
|
304
|
+
typer.defer(self)
|
305
|
+
else
|
306
|
+
# TODO check types for compatibility (maybe only if an expression)
|
307
|
+
resolved!
|
308
|
+
@inferred_type = types[0]
|
309
|
+
end
|
310
|
+
end
|
311
|
+
@inferred_type
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
class Ensure < Node
|
316
|
+
attr_reader :body, :clause
|
317
|
+
attr_accessor :state # Used by the some compilers.
|
318
|
+
|
319
|
+
def initialize(parent, position, &block)
|
320
|
+
super(parent, position, &block)
|
321
|
+
@body, @clause = children
|
322
|
+
end
|
323
|
+
|
324
|
+
def infer(typer)
|
325
|
+
resolve_if(typer) do
|
326
|
+
typer.infer(clause)
|
327
|
+
typer.infer(body)
|
328
|
+
end
|
329
|
+
end
|
330
|
+
end
|
331
|
+
end
|
332
|
+
end
|