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.
- data/History.txt +181 -0
- data/README.txt +6 -10
- data/Rakefile +86 -9
- data/bin/mirah +2 -0
- data/bin/mirahc +2 -0
- data/bin/mirahp +2 -0
- data/{bin/dubyp → examples/interfaces.mirah} +16 -9
- data/examples/macros/square.mirah +12 -0
- data/examples/macros/square_int.mirah +12 -0
- data/examples/macros/string-each-char.mirah +14 -0
- data/examples/maven/README.txt +2 -0
- data/examples/maven/pom.xml +23 -0
- data/examples/maven/src/main/mirah/hello_mirah.mirah +9 -0
- data/examples/rosettacode/100-doors.mirah +44 -0
- data/examples/rosettacode/99-bottles-of-beer.mirah +13 -0
- data/examples/rosettacode/README.txt +9 -0
- data/examples/rosettacode/boolean-values.mirah +29 -0
- data/examples/rosettacode/comments.mirah +2 -0
- data/examples/rosettacode/copy-a-string.mirah +10 -0
- data/examples/rosettacode/count-occurrences-of-a-substring.mirah +40 -0
- data/examples/rosettacode/create-a-file.mirah +6 -0
- data/examples/rosettacode/empty-string.mirah +9 -0
- data/examples/rosettacode/factorial.mirah +10 -0
- data/examples/rosettacode/fibonacci.mirah +21 -0
- data/examples/rosettacode/file-size.mirah +5 -0
- data/examples/rosettacode/fizz-buzz.mirah +21 -0
- data/examples/rosettacode/flatten-a-list.mirah +24 -0
- data/examples/rosettacode/guess-the-number.mirah +21 -0
- data/examples/rosettacode/is-string-numeric.mirah +127 -0
- data/examples/rosettacode/palindrome.mirah +14 -0
- data/examples/rosettacode/repeat-a-string.mirah +9 -0
- data/examples/rosettacode/reverse-a-string.mirah +6 -0
- data/examples/rosettacode/rot-13.mirah +20 -0
- data/examples/rosettacode/user-input.mirah +4 -0
- data/examples/sort_closure.mirah +1 -1
- data/javalib/dynalink-0.2.jar +0 -0
- data/javalib/mirah-bootstrap.jar +0 -0
- data/lib/mirah.rb +7 -16
- data/lib/mirah/ast.rb +22 -92
- data/lib/mirah/ast/call.rb +41 -9
- data/lib/mirah/ast/class.rb +34 -6
- data/lib/mirah/ast/flow.rb +17 -5
- data/lib/mirah/ast/intrinsics.rb +50 -8
- data/lib/mirah/ast/literal.rb +7 -0
- data/lib/mirah/ast/local.rb +9 -1
- data/lib/mirah/ast/method.rb +21 -8
- data/lib/mirah/ast/scope.rb +1 -1
- data/lib/mirah/ast/structure.rb +81 -15
- data/lib/mirah/ast/type.rb +4 -0
- data/{bin/dubyc → lib/mirah/commands.rb} +4 -11
- data/lib/mirah/commands/base.rb +54 -0
- data/lib/mirah/commands/compile.rb +39 -0
- data/{examples/wiki/Rakefile → lib/mirah/commands/parse.rb} +18 -17
- data/lib/mirah/commands/run.rb +73 -0
- data/lib/mirah/compiler.rb +37 -417
- data/lib/mirah/compiler/call.rb +45 -0
- data/lib/mirah/compiler/class.rb +81 -0
- data/lib/mirah/compiler/flow.rb +109 -0
- data/lib/mirah/compiler/literal.rb +130 -0
- data/lib/mirah/compiler/local.rb +59 -0
- data/lib/mirah/compiler/method.rb +44 -0
- data/lib/mirah/compiler/structure.rb +65 -0
- data/lib/mirah/compiler/type.rb +27 -0
- data/lib/mirah/env.rb +4 -6
- data/lib/mirah/generator.rb +61 -0
- data/lib/mirah/jvm/compiler.rb +8 -867
- data/lib/mirah/jvm/compiler/base.rb +270 -0
- data/lib/mirah/jvm/compiler/java_source.rb +779 -0
- data/lib/mirah/jvm/compiler/jvm_bytecode.rb +851 -0
- data/lib/mirah/jvm/method_lookup.rb +21 -2
- data/lib/mirah/jvm/source_generator/builder.rb +10 -13
- data/lib/mirah/jvm/source_generator/loops.rb +99 -93
- data/lib/mirah/jvm/source_generator/precompile.rb +3 -2
- data/lib/mirah/jvm/typer.rb +3 -3
- data/lib/mirah/jvm/types.rb +10 -426
- data/lib/mirah/jvm/types/array_type.rb +62 -0
- data/lib/mirah/jvm/types/basic_types.rb +1 -0
- data/lib/mirah/jvm/types/dynamic_type.rb +46 -0
- data/lib/mirah/jvm/types/factory.rb +23 -5
- data/lib/mirah/jvm/types/interface_definition.rb +20 -0
- data/lib/mirah/jvm/types/intrinsics.rb +15 -3
- data/lib/mirah/jvm/types/meta_type.rb +45 -0
- data/lib/mirah/jvm/types/methods.rb +12 -5
- data/lib/mirah/jvm/types/null_type.rb +27 -0
- data/lib/mirah/jvm/types/primitive_type.rb +38 -0
- data/lib/mirah/jvm/types/source_mirror.rb +266 -0
- data/lib/mirah/jvm/types/type.rb +173 -0
- data/lib/mirah/jvm/types/type_definition.rb +55 -0
- data/lib/mirah/jvm/types/unreachable_type.rb +27 -0
- data/lib/mirah/jvm/types/void_type.rb +19 -0
- data/lib/mirah/parser.rb +90 -0
- data/lib/mirah/plugin/gwt.rb +5 -5
- data/lib/mirah/plugin/java.rb +1 -1
- data/lib/mirah/transform.rb +4 -321
- data/lib/mirah/transform/ast_ext.rb +63 -0
- data/lib/mirah/transform/error.rb +13 -0
- data/lib/mirah/transform/helper.rb +761 -0
- data/lib/mirah/transform/transformer.rb +255 -0
- data/lib/mirah/typer.rb +2 -383
- data/{bin/duby → lib/mirah/typer/base.rb} +12 -10
- data/lib/mirah/typer/simple.rb +377 -0
- data/lib/mirah/util/argument_processor.rb +114 -0
- data/lib/mirah/util/class_loader.rb +37 -0
- data/lib/mirah/util/compilation_state.rb +51 -0
- data/lib/mirah/util/process_errors.rb +33 -0
- data/lib/mirah/version.rb +1 -1
- data/lib/mirah_task.rb +3 -2
- data/test/{test_ast.rb → core/test_ast.rb} +6 -0
- data/test/{test_compilation.rb → core/test_compilation.rb} +0 -0
- data/test/{test_env.rb → core/test_env.rb} +24 -25
- data/test/{test_macros.rb → core/test_macros.rb} +2 -4
- data/test/{test_typer.rb → core/test_typer.rb} +0 -3
- data/test/jvm/bytecode_test_helper.rb +181 -0
- data/test/{test_javac_compiler.rb → jvm/javac_test_helper.rb} +38 -22
- data/test/jvm/test_enumerable.rb +304 -0
- data/test/{test_java_typer.rb → jvm/test_java_typer.rb} +2 -4
- data/test/{test_jvm_compiler.rb → jvm/test_jvm_compiler.rb} +146 -443
- data/test/jvm/test_macros.rb +147 -0
- data/test/jvm/test_main_method.rb +15 -0
- data/test/{test_gwt.rb → plugins/test_gwt.rb} +0 -2
- metadata +103 -91
- data/bin/jrubyp +0 -52
- data/examples/wiki/src/org/mirah/wiki/MirahWiki.duby +0 -339
- data/examples/wiki/src/org/mirah/wiki/edit.eduby.html +0 -42
- data/examples/wiki/src/org/mirah/wiki/error.eduby.html +0 -2
- data/examples/wiki/src/org/mirah/wiki/layout.eduby.html +0 -69
- data/examples/wiki/src/org/mirah/wiki/parser.eduby.html +0 -7
- data/examples/wiki/src/org/mirah/wiki/view.eduby.html +0 -15
- 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 +0 -21
- 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 +0 -61
- data/examples/wiki/war/public/robots.txt +0 -0
- data/examples/wiki/war/public/stylesheets/main.css +0 -156
- data/examples/wiki/war/public/stylesheets/prettify.css +0 -1
- data/examples/wiki/war/public/stylesheets/sh_style.css +0 -66
- data/examples/wiki/war/public/stylesheets/source.css +0 -21
- 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 +0 -421
- data/examples/wiki/war/public/wmd/wmd-base.js +0 -1799
- data/examples/wiki/war/public/wmd/wmd-plus.js +0 -311
- data/examples/wiki/war/public/wmd/wmd.js +0 -73
- data/examples/wiki/war/src/org/mirah/wiki/MirahWiki.duby +0 -339
- data/examples/wiki/war/src/org/mirah/wiki/edit.eduby.html +0 -42
- data/examples/wiki/war/src/org/mirah/wiki/error.eduby.html +0 -2
- data/examples/wiki/war/src/org/mirah/wiki/layout.eduby.html +0 -69
- data/examples/wiki/war/src/org/mirah/wiki/parser.eduby.html +0 -7
- data/examples/wiki/war/src/org/mirah/wiki/view.eduby.html +0 -15
- data/javalib/dynalink-0.1.jar +0 -0
- data/javalib/jsr292-mock.jar +0 -0
- data/lib/mirah/class_loader.rb +0 -35
- data/lib/mirah/compilation_state.rb +0 -28
- data/lib/mirah/impl.rb +0 -273
- data/lib/mirah/jvm/base.rb +0 -267
- data/lib/mirah/jvm/source_compiler.rb +0 -760
- data/lib/mirah/transform2.rb +0 -752
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
#!/usr/bin/env jruby
|
|
2
|
-
|
|
3
1
|
# Copyright (c) 2010 The Mirah project authors. All Rights Reserved.
|
|
4
2
|
# All contributing project authors may be found in the NOTICE file.
|
|
5
3
|
#
|
|
@@ -15,12 +13,16 @@
|
|
|
15
13
|
# See the License for the specific language governing permissions and
|
|
16
14
|
# limitations under the License.
|
|
17
15
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
end
|
|
16
|
+
module Mirah
|
|
17
|
+
module Typer
|
|
18
|
+
class Base
|
|
19
|
+
include Mirah
|
|
20
|
+
|
|
21
|
+
def log(message); Typer.log(message); end
|
|
24
22
|
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
def to_s
|
|
24
|
+
name
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
# Copyright (c) 2010 The Mirah project authors. All Rights Reserved.
|
|
2
|
+
# All contributing project authors may be found in the NOTICE file.
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
require 'mirah/ast'
|
|
17
|
+
require 'mirah/transform'
|
|
18
|
+
|
|
19
|
+
module Mirah
|
|
20
|
+
module Typer
|
|
21
|
+
class Simple < Base
|
|
22
|
+
attr_accessor :known_types, :errors, :last_chance
|
|
23
|
+
|
|
24
|
+
def initialize(self_type)
|
|
25
|
+
@known_types = {}
|
|
26
|
+
|
|
27
|
+
@known_types["self"] = type_reference(nil, self_type)
|
|
28
|
+
@known_types["fixnum"] = type_reference(nil, "fixnum")
|
|
29
|
+
@known_types["float"] = type_reference(nil, "float")
|
|
30
|
+
@known_types["string"] = type_reference(nil, "string")
|
|
31
|
+
@known_types["boolean"] = type_reference(nil, "boolean")
|
|
32
|
+
@errors = []
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def name
|
|
36
|
+
"Simple"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def set_filename(scope, name); end
|
|
40
|
+
|
|
41
|
+
def self_type
|
|
42
|
+
known_types["self"]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def default_type
|
|
46
|
+
nil
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def fixnum_type(value=0)
|
|
50
|
+
known_types["fixnum"]
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def float_type(value=0)
|
|
54
|
+
known_types["float"]
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def string_type
|
|
58
|
+
known_types["string"]
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def boolean_type
|
|
62
|
+
known_types["boolean"]
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def null_type
|
|
66
|
+
AST::TypeReference::NullType
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def no_type
|
|
70
|
+
AST::TypeReference::NoType
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# to be overridden
|
|
74
|
+
def array_type
|
|
75
|
+
AST::TypeReference::NullType
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# to be overridden
|
|
79
|
+
def hash_type
|
|
80
|
+
AST::TypeReference::NullType
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def known_type(scope, name)
|
|
84
|
+
@known_types[name]
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def define_type(scope, name, superclass, interfaces)
|
|
88
|
+
log "New type defined: '#{name}' < '#{superclass}'"
|
|
89
|
+
result = type_definition(scope, name, superclass, interfaces)
|
|
90
|
+
|
|
91
|
+
# TODO Get rid of known_types["self"]
|
|
92
|
+
old_self, known_types["self"] = known_types["self"], result
|
|
93
|
+
yield
|
|
94
|
+
known_types["self"] = old_self
|
|
95
|
+
|
|
96
|
+
result
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def learn_local_type(scope, name, type)
|
|
100
|
+
return if type.null? && !@last_chance
|
|
101
|
+
type = scope.learn_local_type(name, known_types[type] || type)
|
|
102
|
+
log "Learned local type under #{scope} : #{name} = #{type}" if type
|
|
103
|
+
type
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def local_type(scope, name)
|
|
107
|
+
type = scope.local_type(name)
|
|
108
|
+
log "Retrieved local type in #{scope} : #{name} = #{type}" if type
|
|
109
|
+
type
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def local_types
|
|
113
|
+
@local_types ||= {}
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def local_type_hash(scope)
|
|
117
|
+
local_types[scope] ||= {}
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def field_types
|
|
121
|
+
@field_types ||= {}
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def field_type_hash(cls)
|
|
125
|
+
field_types[cls] ||= {}
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def static_field_types
|
|
129
|
+
@static_field_types ||= {}
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def static_field_type_hash(cls)
|
|
133
|
+
static_field_types[cls] ||= {}
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def infer_signature(method_def)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def learn_field_type(cls, name, type)
|
|
140
|
+
log "Learned field type under #{cls} : #{name} = #{type}" if type
|
|
141
|
+
|
|
142
|
+
# TODO check for compatibility?
|
|
143
|
+
field_type_hash(cls)[name] ||= known_types[type] || type
|
|
144
|
+
|
|
145
|
+
type
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def field_type(cls, name)
|
|
149
|
+
field_type_hash(cls)[name]
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def learn_static_field_type(cls, name, type)
|
|
153
|
+
log "Learned field type under #{cls} : #{name} = #{type}" if type
|
|
154
|
+
|
|
155
|
+
# TODO check for compatibility?
|
|
156
|
+
static_field_type_hash(cls)[name] ||= known_types[type] || type
|
|
157
|
+
|
|
158
|
+
type
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def static_field_type(cls, name)
|
|
162
|
+
static_field_type_hash(cls)[name]
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def learn_method_type(target_type, name, parameter_types, type, exceptions)
|
|
166
|
+
log "Learned method #{name} (#{parameter_types}) on #{target_type} = #{type}" if type
|
|
167
|
+
|
|
168
|
+
get_method_type_hash(target_type, name, parameter_types)[:type] = known_types[type] || type
|
|
169
|
+
|
|
170
|
+
# if it's any args are imported types, also add a mapping for the expanded name
|
|
171
|
+
imported_types = parameter_types.map {|param| known_types[param] || param}
|
|
172
|
+
get_method_type_hash(target_type, name, imported_types)[:type] = type
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def method_type(target_type, name, parameter_types)
|
|
176
|
+
if (target_type && target_type.error?) ||
|
|
177
|
+
parameter_types.any? {|t| t && t.error?}
|
|
178
|
+
return AST.error_type
|
|
179
|
+
end
|
|
180
|
+
constructor = (name == 'new' && target_type && target_type.meta?)
|
|
181
|
+
|
|
182
|
+
if constructor
|
|
183
|
+
# constructor handled different from other methods
|
|
184
|
+
simple_type = get_method_type_hash(target_type.unmeta, 'initialize', parameter_types)[:type]
|
|
185
|
+
else
|
|
186
|
+
simple_type = get_method_type_hash(target_type, name, parameter_types)[:type]
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
if !simple_type
|
|
191
|
+
log "Method type for \"#{name}\" #{parameter_types} on #{target_type} not found."
|
|
192
|
+
|
|
193
|
+
# allow plugins a go if we're in the inference phase
|
|
194
|
+
simple_type = plugins do |plugin|
|
|
195
|
+
plugin.method_type(self, target_type, name, parameter_types)
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
return nil unless simple_type
|
|
200
|
+
|
|
201
|
+
if constructor
|
|
202
|
+
log "Method type for \"#{name}\" #{parameter_types} on #{target_type} = #{target_type}"
|
|
203
|
+
target_type.unmeta
|
|
204
|
+
else
|
|
205
|
+
log "Method type for \"#{name}\" #{parameter_types} on #{target_type} = #{simple_type}"
|
|
206
|
+
simple_type
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def plugins
|
|
211
|
+
if cycling?
|
|
212
|
+
Mirah.typer_plugins.each do |plugin|
|
|
213
|
+
log "Invoking plugin: #{plugin}"
|
|
214
|
+
|
|
215
|
+
result = yield plugin
|
|
216
|
+
return result if result
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
nil
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def cycling?
|
|
224
|
+
@cycling
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def cycling=(c)
|
|
228
|
+
@cycling = c
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def cycle(count)
|
|
232
|
+
@cycling = true
|
|
233
|
+
count.times do |i|
|
|
234
|
+
begin
|
|
235
|
+
log "[Cycle #{i}]: Started... (#{@deferred_nodes.size} nodes to resolve)"
|
|
236
|
+
yield i
|
|
237
|
+
ensure
|
|
238
|
+
log "[Cycle #{i}]: Complete!"
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
ensure
|
|
242
|
+
@cycling = false
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
def method_types
|
|
246
|
+
@method_types ||= {}
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
def get_method_type_hash(target_type, name, parameter_types)
|
|
250
|
+
method_types[target_type] ||= {}
|
|
251
|
+
method_types[target_type][name] ||= {}
|
|
252
|
+
method_types[target_type][name][parameter_types.size] ||= {}
|
|
253
|
+
|
|
254
|
+
current = method_types[target_type][name][parameter_types.size]
|
|
255
|
+
|
|
256
|
+
parameter_types.each {|type| current[type] ||= {}; current = current[type]}
|
|
257
|
+
|
|
258
|
+
current
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def type_reference(scope, name, array=false, meta=false)
|
|
262
|
+
AST::TypeReference.new(name, array, meta)
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
def type_definition(scope, name, superclass, interfaces)
|
|
266
|
+
AST::TypeDefinition.new(name, AST::TypeReference.new(superclass), interfaces)
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
def deferred_nodes
|
|
270
|
+
@deferred_nodes ||= {}
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
def infer(node, expression=true)
|
|
274
|
+
begin
|
|
275
|
+
node.infer(self, expression)
|
|
276
|
+
rescue InferenceError => ex
|
|
277
|
+
ex.node ||= node
|
|
278
|
+
error(node, ex)
|
|
279
|
+
rescue Exception => ex
|
|
280
|
+
raise Mirah::InternalCompilerError.wrap(ex, node)
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
def error(node, error_or_msg=nil, backtrace=nil)
|
|
285
|
+
if error_or_msg.kind_of? InferenceError
|
|
286
|
+
error = error_or_msg
|
|
287
|
+
elsif error_or_msg
|
|
288
|
+
error = InferenceError.new(error_or_msg, node)
|
|
289
|
+
error.set_backtrace(backtrace) if backtrace
|
|
290
|
+
else
|
|
291
|
+
error = InferenceError.new("Unable to infer type.", node)
|
|
292
|
+
end
|
|
293
|
+
@errors << error
|
|
294
|
+
node.resolve_if(self) do
|
|
295
|
+
AST.error_type
|
|
296
|
+
end
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
def defer(node, error_message=nil)
|
|
300
|
+
if @error_next
|
|
301
|
+
log "Marking #{node} as an error"
|
|
302
|
+
@error_next = false
|
|
303
|
+
error(node, error_message)
|
|
304
|
+
else
|
|
305
|
+
raise "Can't defer nil" if node.nil?
|
|
306
|
+
return if deferred_nodes.include? node
|
|
307
|
+
log "Deferring inference for #{node}"
|
|
308
|
+
|
|
309
|
+
deferred_nodes[node] = self_type
|
|
310
|
+
end
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
def resolve(raise = false)
|
|
314
|
+
count = deferred_nodes.size + 1
|
|
315
|
+
|
|
316
|
+
log "Entering type inference cycle"
|
|
317
|
+
|
|
318
|
+
retried = false
|
|
319
|
+
cycle(count) do |i|
|
|
320
|
+
old_deferred = @deferred_nodes
|
|
321
|
+
@deferred_nodes = {}
|
|
322
|
+
old_deferred.each do |node, saved_type|
|
|
323
|
+
known_types["self"] = saved_type
|
|
324
|
+
type = infer(node)
|
|
325
|
+
|
|
326
|
+
log "[Cycle #{i}]: Inferred type for #{node}: #{type || 'FAILED'}"
|
|
327
|
+
|
|
328
|
+
if type == default_type
|
|
329
|
+
@deferred_nodes[node] = saved_type
|
|
330
|
+
end
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
if @deferred_nodes.size == 0
|
|
334
|
+
log "[Cycle #{i}]: Resolved all types, exiting"
|
|
335
|
+
break
|
|
336
|
+
elsif old_deferred == @deferred_nodes
|
|
337
|
+
if @error_next || retried
|
|
338
|
+
log "[Cycle #{i}]: Made no progress, bailing out"
|
|
339
|
+
break
|
|
340
|
+
elsif @last_chance
|
|
341
|
+
# Retry this iteration, and mark the first deferred
|
|
342
|
+
# type as an error.
|
|
343
|
+
retried = true
|
|
344
|
+
@error_next = true
|
|
345
|
+
redo
|
|
346
|
+
else
|
|
347
|
+
# This is a hack for default constructor support. The right fix
|
|
348
|
+
# is probably to check the AST for constructors. Instead we
|
|
349
|
+
# tell the plugins that we're near the end of inference so they
|
|
350
|
+
# can assume no new constructors are being added. You could
|
|
351
|
+
# easily write some circular constructors that would compile
|
|
352
|
+
# with this technique but fail to run.
|
|
353
|
+
@last_chance = true
|
|
354
|
+
redo
|
|
355
|
+
end
|
|
356
|
+
end
|
|
357
|
+
retried = false
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
# done with n sweeps, if any remain mark them as errors
|
|
361
|
+
error_nodes = @errors.map {|e| e.node}
|
|
362
|
+
(deferred_nodes.keys - error_nodes).each do |deferred_node|
|
|
363
|
+
error_nodes << deferred_node
|
|
364
|
+
error(deferred_node)
|
|
365
|
+
end
|
|
366
|
+
if raise && !error_nodes.empty?
|
|
367
|
+
msg = "Could not infer typing for nodes:"
|
|
368
|
+
error_nodes.map do |e|
|
|
369
|
+
msg << "\n "
|
|
370
|
+
msg << "#{e.inspect} at line #{e.line_number} (child of #{e.parent})"
|
|
371
|
+
end
|
|
372
|
+
raise InferenceError.new(msg)
|
|
373
|
+
end
|
|
374
|
+
end
|
|
375
|
+
end
|
|
376
|
+
end
|
|
377
|
+
end
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Copyright (c) 2010 The Mirah project authors. All Rights Reserved.
|
|
2
|
+
# All contributing project authors may be found in the NOTICE file.
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
module Mirah
|
|
17
|
+
module Util
|
|
18
|
+
class ArgumentProcessor
|
|
19
|
+
def initialize(state, args)
|
|
20
|
+
@state = state
|
|
21
|
+
@args = args
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
attr_accessor :state, :args
|
|
25
|
+
|
|
26
|
+
def process
|
|
27
|
+
state.args = args
|
|
28
|
+
while args.length > 0 && args[0] =~ /^-/
|
|
29
|
+
case args[0]
|
|
30
|
+
when '--classpath', '-c'
|
|
31
|
+
args.shift
|
|
32
|
+
Mirah::Env.decode_paths(args.shift, $CLASSPATH)
|
|
33
|
+
when '--cd'
|
|
34
|
+
args.shift
|
|
35
|
+
Dir.chdir(args.shift)
|
|
36
|
+
when '--dest', '-d'
|
|
37
|
+
args.shift
|
|
38
|
+
state.destination = File.join(File.expand_path(args.shift), '')
|
|
39
|
+
when '-e'
|
|
40
|
+
break
|
|
41
|
+
when '--explicit-packages'
|
|
42
|
+
args.shift
|
|
43
|
+
Mirah::AST::Script.explicit_packages = true
|
|
44
|
+
when '--help', '-h'
|
|
45
|
+
print_help
|
|
46
|
+
throw :exit
|
|
47
|
+
when '--java', '-j'
|
|
48
|
+
if state.command == :compile
|
|
49
|
+
require 'mirah/jvm/compiler/java_source'
|
|
50
|
+
state.compiler_class = Mirah::JVM::Compiler::JavaSource
|
|
51
|
+
args.shift
|
|
52
|
+
else
|
|
53
|
+
puts "-j/--java flag only applies to \"compile\" mode."
|
|
54
|
+
print_help
|
|
55
|
+
throw :exit
|
|
56
|
+
end
|
|
57
|
+
when '--jvm'
|
|
58
|
+
args.shift
|
|
59
|
+
state.set_jvm_version(args.shift)
|
|
60
|
+
when '-I'
|
|
61
|
+
args.shift
|
|
62
|
+
$: << args.shift
|
|
63
|
+
when '--plugin', '-p'
|
|
64
|
+
args.shift
|
|
65
|
+
plugin = args.shift
|
|
66
|
+
require "mirah/plugin/#{plugin}"
|
|
67
|
+
when '--verbose', '-V'
|
|
68
|
+
Mirah::Typer.verbose = true
|
|
69
|
+
Mirah::AST.verbose = true
|
|
70
|
+
Mirah::JVM::Compiler::JVMBytecode.verbose = true
|
|
71
|
+
state.verbose = true
|
|
72
|
+
args.shift
|
|
73
|
+
when '--version', '-v'
|
|
74
|
+
args.shift
|
|
75
|
+
print_version
|
|
76
|
+
when '--no-save-extensions'
|
|
77
|
+
args.shift
|
|
78
|
+
state.save_extensions = false
|
|
79
|
+
else
|
|
80
|
+
puts "unrecognized flag: " + args[0]
|
|
81
|
+
print_help
|
|
82
|
+
throw :exit
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
state.destination ||= File.join(File.expand_path('.'), '')
|
|
86
|
+
state.compiler_class ||= Mirah::JVM::Compiler::JVMBytecode
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def print_help
|
|
90
|
+
puts "#{$0} [flags] <files or -e SCRIPT>
|
|
91
|
+
-c, --classpath PATH\tAdd PATH to the Java classpath for compilation
|
|
92
|
+
--cd DIR\t\tSwitch to the specified DIR befor compilation
|
|
93
|
+
-d, --dir DIR\t\tUse DIR as the base dir for compilation, packages
|
|
94
|
+
-e CODE\t\tCompile or run the inline script following -e
|
|
95
|
+
\t\t\t (the class will be named \"DashE\")
|
|
96
|
+
--explicit-packages\tRequire explicit 'package' lines in source
|
|
97
|
+
-h, --help\t\tPrint this help message
|
|
98
|
+
-I DIR\t\tAdd DIR to the Ruby load path before running
|
|
99
|
+
-j, --java\t\tOutput .java source (compile mode [mirahc] only)
|
|
100
|
+
--jvm VERSION\t\tEmit JVM bytecode targeting specified JVM
|
|
101
|
+
\t\t\t version (1.4, 1.5, 1.6, 1.7)
|
|
102
|
+
-p, --plugin PLUGIN\trequire 'mirah/plugin/PLUGIN' before running
|
|
103
|
+
-v, --version\t\tPrint the version of Mirah to the console
|
|
104
|
+
-V, --verbose\t\tVerbose logging"
|
|
105
|
+
state.help_printed = true
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def print_version
|
|
109
|
+
puts "Mirah v#{Mirah::VERSION}"
|
|
110
|
+
state.version_printed = true
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|