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.
- data/History.txt +15 -0
- data/README.txt +51 -0
- data/Rakefile +86 -0
- data/bin/duby +10 -0
- data/bin/dubyc +10 -0
- data/bin/dubyp +10 -0
- data/bin/jrubyp +36 -0
- data/bin/mirah +9 -0
- data/bin/mirah.cmd +1 -0
- data/bin/mirahc +9 -0
- data/bin/mirahc.cmd +1 -0
- data/bin/mirahp +9 -0
- data/bin/mirahp.cmd +1 -0
- data/examples/ant/example-build.xml +7 -0
- data/examples/appengine/Rakefile +19 -0
- data/examples/appengine/Readme +29 -0
- data/examples/appengine/src/org/mirah/MirahApp.mirah +57 -0
- data/examples/appengine/src/org/mirah/list.dhtml +15 -0
- data/examples/appengine/war/WEB-INF/lib/dubydatastore.jar +0 -0
- data/examples/bintrees.mirah +66 -0
- data/examples/construction.mirah +8 -0
- data/examples/dynamic.mirah +17 -0
- data/examples/edb.mirah +3 -0
- data/examples/fib.mirah +16 -0
- data/examples/fields.mirah +22 -0
- data/examples/fractal.mirah +55 -0
- data/examples/java_thing.mirah +13 -0
- data/examples/plugins/appengine/Rakefile +55 -0
- data/examples/plugins/appengine/lib/com/google/appengine/ext/duby/db/datastore.rb +375 -0
- data/examples/plugins/appengine/src/com/google/appengine/ext/duby/db/Model.duby +336 -0
- data/examples/plugins/appengine/test/com/google/appengine/ext/duby/db/ModelTest.duby +113 -0
- data/examples/simple_class.mirah +12 -0
- data/examples/sort_closure.mirah +7 -0
- data/examples/swing.mirah +20 -0
- data/examples/tak.mirah +15 -0
- data/examples/test.edb +9 -0
- data/examples/wiki/Rakefile +18 -0
- data/examples/wiki/src/org/mirah/wiki/MirahWiki.duby +324 -0
- data/examples/wiki/src/org/mirah/wiki/edit.eduby.html +42 -0
- data/examples/wiki/src/org/mirah/wiki/error.eduby.html +2 -0
- data/examples/wiki/src/org/mirah/wiki/layout.eduby.html +69 -0
- data/examples/wiki/src/org/mirah/wiki/parser.eduby.html +7 -0
- data/examples/wiki/src/org/mirah/wiki/view.eduby.html +15 -0
- data/examples/wiki/war/WEB-INF/classes/test/HeredocContext.class +0 -0
- data/examples/wiki/war/WEB-INF/classes/test/MirahParser.class +0 -0
- data/examples/wiki/war/WEB-INF/lib/appengine-api.jar +0 -0
- data/examples/wiki/war/WEB-INF/lib/dubydatastore.jar +0 -0
- data/examples/wiki/war/WEB-INF/lib/jmeta-runtime.jar +0 -0
- data/examples/wiki/war/WEB-INF/lib/pegdown-stubs.jar +0 -0
- data/examples/wiki/war/WEB-INF/pegdown.jar +0 -0
- data/examples/wiki/war/app.yaml +21 -0
- data/examples/wiki/war/public/favicon.ico +0 -0
- data/examples/wiki/war/public/images/appengine_duby.png +0 -0
- data/examples/wiki/war/public/images/back.gif +0 -0
- data/examples/wiki/war/public/images/dir.gif +0 -0
- data/examples/wiki/war/public/images/file.gif +0 -0
- data/examples/wiki/war/public/javascripts/prettify.js +61 -0
- data/examples/wiki/war/public/robots.txt +0 -0
- data/examples/wiki/war/public/stylesheets/main.css +156 -0
- data/examples/wiki/war/public/stylesheets/prettify.css +1 -0
- data/examples/wiki/war/public/stylesheets/sh_style.css +66 -0
- data/examples/wiki/war/public/stylesheets/source.css +21 -0
- data/examples/wiki/war/public/wmd/images/bg-fill.png +0 -0
- data/examples/wiki/war/public/wmd/images/bg.png +0 -0
- data/examples/wiki/war/public/wmd/images/blockquote.png +0 -0
- data/examples/wiki/war/public/wmd/images/bold.png +0 -0
- data/examples/wiki/war/public/wmd/images/code.png +0 -0
- data/examples/wiki/war/public/wmd/images/h1.png +0 -0
- data/examples/wiki/war/public/wmd/images/hr.png +0 -0
- data/examples/wiki/war/public/wmd/images/img.png +0 -0
- data/examples/wiki/war/public/wmd/images/italic.png +0 -0
- data/examples/wiki/war/public/wmd/images/link.png +0 -0
- data/examples/wiki/war/public/wmd/images/ol.png +0 -0
- data/examples/wiki/war/public/wmd/images/redo.png +0 -0
- data/examples/wiki/war/public/wmd/images/separator.png +0 -0
- data/examples/wiki/war/public/wmd/images/ul.png +0 -0
- data/examples/wiki/war/public/wmd/images/undo.png +0 -0
- data/examples/wiki/war/public/wmd/images/wmd-on.png +0 -0
- data/examples/wiki/war/public/wmd/images/wmd.png +0 -0
- data/examples/wiki/war/public/wmd/showdown.js +421 -0
- data/examples/wiki/war/public/wmd/wmd-base.js +1799 -0
- data/examples/wiki/war/public/wmd/wmd-plus.js +311 -0
- data/examples/wiki/war/public/wmd/wmd.js +73 -0
- data/javalib/JRubyParser.jar +0 -0
- data/javalib/dynalang-invoke-0.1.jar +0 -0
- data/javalib/mirah-bootstrap.jar +0 -0
- data/javalib/mirah-parser.jar +0 -0
- data/lib/duby.rb +2 -0
- data/lib/mirah.rb +338 -0
- data/lib/mirah/appengine_tasks.rb +146 -0
- data/lib/mirah/ast.rb +615 -0
- data/lib/mirah/ast/call.rb +307 -0
- data/lib/mirah/ast/class.rb +311 -0
- data/lib/mirah/ast/flow.rb +364 -0
- data/lib/mirah/ast/intrinsics.rb +470 -0
- data/lib/mirah/ast/literal.rb +154 -0
- data/lib/mirah/ast/local.rb +89 -0
- data/lib/mirah/ast/method.rb +360 -0
- data/lib/mirah/ast/scope.rb +208 -0
- data/lib/mirah/ast/structure.rb +226 -0
- data/lib/mirah/ast/type.rb +130 -0
- data/lib/mirah/compiler.rb +341 -0
- data/lib/mirah/env.rb +33 -0
- data/lib/mirah/jvm/base.rb +258 -0
- data/lib/mirah/jvm/compiler.rb +885 -0
- data/lib/mirah/jvm/method_lookup.rb +203 -0
- data/lib/mirah/jvm/source_compiler.rb +737 -0
- data/lib/mirah/jvm/source_generator/builder.rb +444 -0
- data/lib/mirah/jvm/source_generator/loops.rb +110 -0
- data/lib/mirah/jvm/source_generator/precompile.rb +188 -0
- data/lib/mirah/jvm/source_generator/typer.rb +11 -0
- data/lib/mirah/jvm/typer.rb +151 -0
- data/lib/mirah/jvm/types.rb +416 -0
- data/lib/mirah/jvm/types/basic_types.rb +33 -0
- data/lib/mirah/jvm/types/boolean.rb +17 -0
- data/lib/mirah/jvm/types/enumerable.rb +65 -0
- data/lib/mirah/jvm/types/extensions.rb +86 -0
- data/lib/mirah/jvm/types/factory.rb +186 -0
- data/lib/mirah/jvm/types/floats.rb +86 -0
- data/lib/mirah/jvm/types/integers.rb +171 -0
- data/lib/mirah/jvm/types/intrinsics.rb +376 -0
- data/lib/mirah/jvm/types/literals.rb +74 -0
- data/lib/mirah/jvm/types/methods.rb +614 -0
- data/lib/mirah/jvm/types/number.rb +143 -0
- data/lib/mirah/nbcompiler.rb +29 -0
- data/lib/mirah/plugin/edb.rb +29 -0
- data/lib/mirah/plugin/gwt.rb +173 -0
- data/lib/mirah/plugin/java.rb +55 -0
- data/lib/mirah/transform.rb +266 -0
- data/lib/mirah/transform2.rb +728 -0
- data/lib/mirah/typer.rb +407 -0
- data/lib/mirah_task.rb +107 -0
- data/test/test_ast.rb +359 -0
- data/test/test_compilation.rb +112 -0
- data/test/test_env.rb +42 -0
- data/test/test_gwt.rb +58 -0
- data/test/test_java_typer.rb +183 -0
- data/test/test_javac_compiler.rb +63 -0
- data/test/test_jvm_compiler.rb +2607 -0
- data/test/test_typer.rb +221 -0
- 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
|