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
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
module Mirah
|
|
2
|
+
module JVM
|
|
3
|
+
module Types
|
|
4
|
+
class ArrayType < Type
|
|
5
|
+
attr_reader :component_type
|
|
6
|
+
|
|
7
|
+
def initialize(component_type)
|
|
8
|
+
@component_type = component_type
|
|
9
|
+
if @component_type.jvm_type
|
|
10
|
+
#@type = java.lang.reflect.Array.newInstance(@component_type.jvm_type, 0).class
|
|
11
|
+
else
|
|
12
|
+
# FIXME: THIS IS WRONG, but I don't know how to fix it
|
|
13
|
+
#@type = @component_type
|
|
14
|
+
end
|
|
15
|
+
@name = component_type.name
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def array?
|
|
19
|
+
true
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def iterable?
|
|
23
|
+
true
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def inner_class?
|
|
27
|
+
basic_type.inner_class?
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def basic_type
|
|
31
|
+
component_type.basic_type
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def superclass
|
|
35
|
+
if component_type.primitive?
|
|
36
|
+
Object
|
|
37
|
+
elsif component_type.array?
|
|
38
|
+
# fix covariance here for arrays of arrays
|
|
39
|
+
# see #55
|
|
40
|
+
Object
|
|
41
|
+
else
|
|
42
|
+
if component_type == Object
|
|
43
|
+
Object
|
|
44
|
+
else
|
|
45
|
+
component_type.superclass.array_type
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def interfaces
|
|
51
|
+
[]
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def meta
|
|
55
|
+
@meta ||= ArrayMetaType.new(self)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
class ArrayMetaType < MetaType; end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
module Mirah
|
|
2
|
+
module JVM
|
|
3
|
+
module Types
|
|
4
|
+
class DynamicType < Type
|
|
5
|
+
ObjectType = Type.new(BiteScript::ASM::ClassMirror.for_name('java.lang.Object'))
|
|
6
|
+
|
|
7
|
+
def initialize
|
|
8
|
+
# For naming, bytecode purposes, we are an Object
|
|
9
|
+
@name = "java.lang.Object"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def basic_type
|
|
13
|
+
self
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def is_parent(other)
|
|
17
|
+
ObjectType.assignable_from?(other)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def assignable_from?(other)
|
|
21
|
+
ObjectType.assignable_from?(other)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def jvm_type
|
|
25
|
+
java.lang.Object
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def full_name
|
|
29
|
+
"dynamic"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def dynamic?
|
|
33
|
+
true
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def superclass
|
|
37
|
+
ObjectType.superclass
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def interfaces
|
|
41
|
+
ObjectType.interfaces
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
# limitations under the License.
|
|
15
15
|
|
|
16
16
|
require 'jruby'
|
|
17
|
+
require 'mirah/jvm/types/source_mirror'
|
|
17
18
|
module Mirah::JVM::Types
|
|
18
19
|
class TypeFactory
|
|
19
20
|
BASIC_TYPES = {
|
|
@@ -136,7 +137,7 @@ module Mirah::JVM::Types
|
|
|
136
137
|
packages.each do |package|
|
|
137
138
|
begin
|
|
138
139
|
return get_type("#{package}.#{name}")
|
|
139
|
-
rescue
|
|
140
|
+
rescue NameError
|
|
140
141
|
end
|
|
141
142
|
end
|
|
142
143
|
raise NameError, "Cannot find class #{name}"
|
|
@@ -213,12 +214,29 @@ module Mirah::JVM::Types
|
|
|
213
214
|
Void
|
|
214
215
|
end
|
|
215
216
|
|
|
217
|
+
def unreachable_type
|
|
218
|
+
Unreachable
|
|
219
|
+
end
|
|
220
|
+
|
|
216
221
|
def get_mirror(name)
|
|
217
222
|
@mirrors[name] ||= begin
|
|
218
|
-
classname = name.tr('.', '/')
|
|
219
|
-
stream = JRuby.runtime.jruby_class_loader.getResourceAsStream(classname)
|
|
220
|
-
|
|
221
|
-
|
|
223
|
+
classname = name.tr('.', '/')
|
|
224
|
+
stream = JRuby.runtime.jruby_class_loader.getResourceAsStream(classname + ".class")
|
|
225
|
+
if stream
|
|
226
|
+
BiteScript::ASM::ClassMirror.load(stream) if stream
|
|
227
|
+
else
|
|
228
|
+
url = JRuby.runtime.jruby_class_loader.getResource(classname + ".java")
|
|
229
|
+
if url
|
|
230
|
+
file = java.io.File.new(url.toURI)
|
|
231
|
+
mirrors = JavaSourceMirror.load(file, self)
|
|
232
|
+
mirrors.each do |mirror|
|
|
233
|
+
@mirrors[mirror.type.class_name] = mirror
|
|
234
|
+
end if mirrors
|
|
235
|
+
@mirrors[name]
|
|
236
|
+
else
|
|
237
|
+
raise NameError, "Class '#{name}' not found."
|
|
238
|
+
end
|
|
239
|
+
end
|
|
222
240
|
end
|
|
223
241
|
end
|
|
224
242
|
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module Mirah
|
|
2
|
+
module JVM
|
|
3
|
+
module Types
|
|
4
|
+
class InterfaceDefinition < TypeDefinition
|
|
5
|
+
def initialize(name, node)
|
|
6
|
+
super(name, node)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def define(builder)
|
|
10
|
+
class_name = @name.tr('.', '/')
|
|
11
|
+
@type ||= builder.public_interface(class_name, *interfaces)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def interface?
|
|
15
|
+
true
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -78,11 +78,15 @@ module Mirah::JVM::Types
|
|
|
78
78
|
# However the only way to do that is to wrap them in a ScopedBody.
|
|
79
79
|
# It'd be better if we didn't have to expose this wrapper node to
|
|
80
80
|
# the user code.
|
|
81
|
+
#
|
|
82
|
+
if call.block && call.name != 'quote'
|
|
83
|
+
call.block.body = wrap_with_scoped_body call, call.block.body
|
|
84
|
+
end
|
|
85
|
+
|
|
81
86
|
call.parameters = call.parameters.map do |arg|
|
|
82
|
-
|
|
83
|
-
wrapper.static_scope = call.scope.static_scope
|
|
84
|
-
wrapper << arg
|
|
87
|
+
wrap_with_scoped_body call, arg
|
|
85
88
|
end
|
|
89
|
+
|
|
86
90
|
expander = klass.constructors[0].newInstance(duby, call)
|
|
87
91
|
ast = expander.expand
|
|
88
92
|
if ast
|
|
@@ -98,6 +102,12 @@ module Mirah::JVM::Types
|
|
|
98
102
|
end
|
|
99
103
|
end
|
|
100
104
|
end
|
|
105
|
+
|
|
106
|
+
def wrap_with_scoped_body call, node
|
|
107
|
+
wrapper = Mirah::AST::ScopedBody.new(call.parent, call.position)
|
|
108
|
+
wrapper.static_scope = call.scope.static_scope
|
|
109
|
+
wrapper << node
|
|
110
|
+
end
|
|
101
111
|
|
|
102
112
|
def declared_intrinsics(name=nil)
|
|
103
113
|
methods = []
|
|
@@ -377,6 +387,8 @@ module Mirah::JVM::Types
|
|
|
377
387
|
if var
|
|
378
388
|
forloop.pre << transformer.eval(
|
|
379
389
|
"#{var.name} = #{it}.next", '', forloop, it)
|
|
390
|
+
else
|
|
391
|
+
forloop.pre << transformer.eval("#{it}.next", '', forloop, it)
|
|
380
392
|
end
|
|
381
393
|
call.block.body.parent = forloop if call.block.body
|
|
382
394
|
[
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
module Mirah
|
|
2
|
+
module JVM
|
|
3
|
+
module Types
|
|
4
|
+
class MetaType < Type
|
|
5
|
+
attr_reader :unmeta
|
|
6
|
+
|
|
7
|
+
def initialize(unmeta)
|
|
8
|
+
@name = unmeta.name
|
|
9
|
+
@unmeta = unmeta
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def basic_type
|
|
13
|
+
@unmeta.basic_type
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def meta?
|
|
17
|
+
true
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def meta
|
|
21
|
+
self
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def superclass
|
|
25
|
+
@unmeta.superclass.meta if @unmeta.superclass
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def interfaces
|
|
29
|
+
[]
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def jvm_type
|
|
33
|
+
unmeta.jvm_type
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def inner_class?
|
|
37
|
+
basic_type.inner_class?
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
class TypeDefMeta < MetaType
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -280,16 +280,21 @@ module Mirah::JVM::Types
|
|
|
280
280
|
ast.parameters.each do |param|
|
|
281
281
|
param.compile(compiler, true)
|
|
282
282
|
end
|
|
283
|
+
handle = compiler.method.mh_invokestatic(
|
|
284
|
+
org.dynalang.dynalink.DefaultBootstrapper,
|
|
285
|
+
"bootstrap",
|
|
286
|
+
java.lang.invoke.CallSite,
|
|
287
|
+
java.lang.invoke.MethodHandles::Lookup,
|
|
288
|
+
java.lang.String,
|
|
289
|
+
java.lang.invoke.MethodType)
|
|
283
290
|
compiler.method.invokedynamic(
|
|
284
|
-
target,
|
|
285
291
|
"dyn:callPropWithThis:#{name}",
|
|
286
|
-
[return_type, target, *@types]
|
|
292
|
+
[return_type, target, *@types],
|
|
293
|
+
handle)
|
|
287
294
|
|
|
288
295
|
unless expression
|
|
289
296
|
return_type.pop(compiler.method)
|
|
290
297
|
end
|
|
291
|
-
|
|
292
|
-
compiler.bootstrap_dynamic
|
|
293
298
|
end
|
|
294
299
|
end
|
|
295
300
|
|
|
@@ -568,7 +573,9 @@ module Mirah::JVM::Types
|
|
|
568
573
|
member = MirahMember.new(self, name, arguments, type, false, exceptions)
|
|
569
574
|
if name == 'initialize'
|
|
570
575
|
if @default_constructor_added
|
|
571
|
-
|
|
576
|
+
if arguments.empty?
|
|
577
|
+
@default_constructor_added = false
|
|
578
|
+
else
|
|
572
579
|
raise "Can't add constructor #{member} after using the default."
|
|
573
580
|
end
|
|
574
581
|
else
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module Mirah
|
|
2
|
+
module JVM
|
|
3
|
+
module Types
|
|
4
|
+
class NullType < Type
|
|
5
|
+
def initialize
|
|
6
|
+
super(BiteScript::ASM::ClassMirror.load('java.lang.Object'))
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def to_s
|
|
10
|
+
"Type(null)"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def null?
|
|
14
|
+
true
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def compatible?(other)
|
|
18
|
+
!other.primitive?
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def assignable_from?(other)
|
|
22
|
+
!other.primitive?
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module Mirah
|
|
2
|
+
module JVM
|
|
3
|
+
module Types
|
|
4
|
+
class PrimitiveType < Type
|
|
5
|
+
def initialize(type, wrapper)
|
|
6
|
+
@wrapper = wrapper
|
|
7
|
+
super(type)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def primitive?
|
|
11
|
+
true
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def primitive_type
|
|
15
|
+
@wrapper::TYPE
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def newarray(method)
|
|
19
|
+
method.send "new#{name}array"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def interfaces
|
|
23
|
+
[]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def convertible_to?(type)
|
|
27
|
+
return true if type == self
|
|
28
|
+
widening_conversions = WIDENING_CONVERSIONS[self]
|
|
29
|
+
widening_conversions && widening_conversions.include?(type)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def superclass
|
|
33
|
+
nil
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,266 @@
|
|
|
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 'jruby'
|
|
17
|
+
require 'set'
|
|
18
|
+
require 'bitescript'
|
|
19
|
+
module Mirah::JVM::Types
|
|
20
|
+
class JavaSourceMirror
|
|
21
|
+
begin
|
|
22
|
+
java_import 'javax.tools.ToolProvider'
|
|
23
|
+
java_import 'java.util.Arrays'
|
|
24
|
+
java_import 'javax.tools.SimpleJavaFileObject'
|
|
25
|
+
java_import 'javax.tools.JavaFileObject'
|
|
26
|
+
java_import 'java.net.URI'
|
|
27
|
+
java_import 'javax.lang.model.element.Element'
|
|
28
|
+
java_import 'javax.lang.model.type.TypeKind'
|
|
29
|
+
java_import 'javax.lang.model.type.TypeMirror'
|
|
30
|
+
java_import 'com.sun.tools.javac.model.JavacElements'
|
|
31
|
+
java_import 'javax.lang.model.util.ElementScanner6'
|
|
32
|
+
java_import 'javax.lang.model.element.AnnotationValueVisitor'
|
|
33
|
+
rescue
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
if defined?(JavacElements)
|
|
37
|
+
class FakeJavaFile < SimpleJavaFileObject
|
|
38
|
+
def initialize(package, name, kind='class')
|
|
39
|
+
package ||= ''
|
|
40
|
+
super(URI.create(FakeJavaFile.build_uri(package, name)), JavaFileObject::Kind::SOURCE)
|
|
41
|
+
@code = ''
|
|
42
|
+
if package != ""
|
|
43
|
+
@code << "package #{package};\n"
|
|
44
|
+
end
|
|
45
|
+
@code << "@org.mirah.infer.FakeClass\n"
|
|
46
|
+
@code << "public #{kind} #{name} { }"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def self.build_uri(package, name)
|
|
50
|
+
name = name.tr('.', '$')
|
|
51
|
+
package = package.tr('.', '/')
|
|
52
|
+
package << '/' unless "" == package
|
|
53
|
+
"string:///#{package}#{name}#{JavaFileObject::Kind::SOURCE.extension}"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def getCharContent(ignoreEncodingErrors)
|
|
57
|
+
java.lang.String.new(@code)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
class JavaSourceParser < ElementScanner6
|
|
62
|
+
include AnnotationValueVisitor
|
|
63
|
+
|
|
64
|
+
# TODO support generics
|
|
65
|
+
def initialize(file, type_factory)
|
|
66
|
+
super()
|
|
67
|
+
@file = file
|
|
68
|
+
@type_factory = type_factory
|
|
69
|
+
@mirrors = []
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def parse
|
|
73
|
+
tools = ToolProvider.system_java_compiler
|
|
74
|
+
units = [get_java_file(tools)] + get_fake_files
|
|
75
|
+
@javac = tools.get_task(nil, nil, nil, classpath, nil, units)
|
|
76
|
+
@element_utils = JavacElements.instance(@javac.context)
|
|
77
|
+
elements = @javac.enter
|
|
78
|
+
elements.each {|elem| scan(elem)}
|
|
79
|
+
@mirrors
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def classpath
|
|
83
|
+
[
|
|
84
|
+
'-classpath',
|
|
85
|
+
$CLASSPATH.to_a.join(java.io.File.pathSeparator)
|
|
86
|
+
]
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def get_java_file(tools)
|
|
90
|
+
fm = tools.get_standard_file_manager(nil, nil, nil)
|
|
91
|
+
fm.get_java_file_objects(@file).to_a[0]
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def get_fake_files
|
|
95
|
+
mirah_typedefs = Set.new(@type_factory.known_types.values.reject {|t| !t.kind_of?(TypeDefinition)})
|
|
96
|
+
files = [FakeJavaFile.new('org.mirah.infer', 'FakeClass', '@interface')]
|
|
97
|
+
mirah_typedefs.each do |typedef|
|
|
98
|
+
typedef.name =~ /^(?:(.+)\.)?([^.]+)$/
|
|
99
|
+
package, name = $1, $2
|
|
100
|
+
kind = if typedef.interface?
|
|
101
|
+
'interface'
|
|
102
|
+
else
|
|
103
|
+
'class'
|
|
104
|
+
end
|
|
105
|
+
files << FakeJavaFile.new(package, name, kind)
|
|
106
|
+
end
|
|
107
|
+
files
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def visitType(elem, arg)
|
|
111
|
+
return anno_visitType(elem, arg) if elem.kind_of?(TypeMirror)
|
|
112
|
+
if elem.annotation_mirrors.any? {|a| a.toString == '@org.mirah.infer.FakeClass'}
|
|
113
|
+
return
|
|
114
|
+
end
|
|
115
|
+
superclass = internal_type_name(elem.superclass) || 'java/lang/Object'
|
|
116
|
+
interfaces = elem.interfaces.map {|i| internal_type_name(i)}
|
|
117
|
+
flags = flags_from_modifiers(elem)
|
|
118
|
+
builder = BiteScript::ASM::ClassMirror::Builder.new
|
|
119
|
+
builder.visit(0, flags, internal_name(elem), nil, superclass, interfaces)
|
|
120
|
+
with(builder) do
|
|
121
|
+
elem.annotation_mirrors.each {|anno| visitAnnotation(anno)}
|
|
122
|
+
super(elem, arg)
|
|
123
|
+
end
|
|
124
|
+
@mirrors << builder.mirror
|
|
125
|
+
builder.mirror
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def visitVariable(field, arg)
|
|
129
|
+
flags = flags_from_modifiers(field)
|
|
130
|
+
type = type_desc(field.as_type)
|
|
131
|
+
fbuilder = @current.visitField(
|
|
132
|
+
flags, field.simple_name, type, nil, field.constant_value)
|
|
133
|
+
with fbuilder do
|
|
134
|
+
field.annotation_mirrors.each {|anno| visitAnnotation(anno)}
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def visitExecutable(method, arg)
|
|
139
|
+
# TODO varags
|
|
140
|
+
flags = flags_from_modifiers(method)
|
|
141
|
+
exceptions = method.thrown_types.map {|t| internal_type_name(t)}
|
|
142
|
+
desc = type_desc(method.as_type)
|
|
143
|
+
mbuilder = @current.visitMethod(flags, method.simple_name, desc, nil, exceptions)
|
|
144
|
+
with mbuilder do
|
|
145
|
+
method.annotation_mirrors.each {|anno| visitAnnotation(anno)}
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def visitAnnotation(elem, arg=nil)
|
|
150
|
+
desc = type_desc(elem.annotation_type)
|
|
151
|
+
if arg.nil?
|
|
152
|
+
anno = @current.visitAnnotation(desc, 0)
|
|
153
|
+
else
|
|
154
|
+
builder, name = arg
|
|
155
|
+
anno = builder.visitAnnotation(name, desc)
|
|
156
|
+
end
|
|
157
|
+
elem.element_values.each do |method, value|
|
|
158
|
+
name = method.simple_name
|
|
159
|
+
visit(value, [anno, name])
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# AnnotationValueVisitor
|
|
164
|
+
def visitArray(values, arg)
|
|
165
|
+
anno, name = arg
|
|
166
|
+
array = anno.visitArray(name)
|
|
167
|
+
values.each do |value|
|
|
168
|
+
visit(value, [array, name])
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def visitBoolean(val, arg)
|
|
173
|
+
anno, name = arg
|
|
174
|
+
anno.visit(name, val)
|
|
175
|
+
end
|
|
176
|
+
alias visitByte visitBoolean
|
|
177
|
+
alias visitChar visitBoolean
|
|
178
|
+
alias visitDouble visitBoolean
|
|
179
|
+
alias visitFloat visitBoolean
|
|
180
|
+
alias visitInt visitBoolean
|
|
181
|
+
alias visitLong visitBoolean
|
|
182
|
+
alias visitShort visitBoolean
|
|
183
|
+
alias visitString visitBoolean
|
|
184
|
+
alias visitUnknown visitBoolean
|
|
185
|
+
|
|
186
|
+
def visitEnumConstant(c, arg)
|
|
187
|
+
anno, name = arg
|
|
188
|
+
anno.visitEnum(name, type_desc(c.as_type), c.simple_name)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def anno_visitType(t, arg)
|
|
192
|
+
anno, name = arg
|
|
193
|
+
anno.visit(name, BiteScript::ASM::Type.getType(type_desc(t)))
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def with(elem)
|
|
197
|
+
saved, @current = @current, elem
|
|
198
|
+
begin
|
|
199
|
+
yield
|
|
200
|
+
ensure
|
|
201
|
+
@current = saved
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def flags_from_modifiers(elem)
|
|
206
|
+
flags = 0
|
|
207
|
+
elem.modifiers.each do |modifier|
|
|
208
|
+
flags |= BiteScript::ASM::Opcodes.const_get("ACC_#{modifier.name}")
|
|
209
|
+
end
|
|
210
|
+
flags
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def internal_name(element)
|
|
214
|
+
@element_utils.get_binary_name(element).to_s.tr('.', '/')
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def internal_type_name(type)
|
|
218
|
+
return nil if type.kind == TypeKind::NONE
|
|
219
|
+
return @element_utils.get_binary_name(type.as_element).to_s.tr('.', '/')
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def type_desc(type)
|
|
223
|
+
case type.kind.name
|
|
224
|
+
when 'ARRAY'
|
|
225
|
+
"[#{type_desc(type.component_type)}"
|
|
226
|
+
when 'BOOLEAN'
|
|
227
|
+
'Z'
|
|
228
|
+
when 'BYTE'
|
|
229
|
+
'B'
|
|
230
|
+
when 'CHAR'
|
|
231
|
+
'C'
|
|
232
|
+
when 'DECLARED'
|
|
233
|
+
name = internal_type_name(type)
|
|
234
|
+
"L#{name};"
|
|
235
|
+
when 'DOUBLE'
|
|
236
|
+
'D'
|
|
237
|
+
when 'FLOAT'
|
|
238
|
+
'F'
|
|
239
|
+
when 'INT'
|
|
240
|
+
'I'
|
|
241
|
+
when 'LONG'
|
|
242
|
+
'J'
|
|
243
|
+
when 'SHORT'
|
|
244
|
+
'S'
|
|
245
|
+
when 'VOID'
|
|
246
|
+
'V'
|
|
247
|
+
when 'EXECUTABLE'
|
|
248
|
+
desc = '('
|
|
249
|
+
type.parameter_types.each do |param|
|
|
250
|
+
desc << type_desc(param)
|
|
251
|
+
end
|
|
252
|
+
desc << ')'
|
|
253
|
+
desc << type_desc(type.return_type)
|
|
254
|
+
else
|
|
255
|
+
raise ArgumentError, "Unsupported type #{type.kind.name}"
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def self.load(file, factory)
|
|
262
|
+
parser = JavaSourceParser.new(file, factory)
|
|
263
|
+
parser.parse
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
end
|