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,74 @@
|
|
|
1
|
+
require 'delegate'
|
|
2
|
+
|
|
3
|
+
module Duby::JVM::Types
|
|
4
|
+
|
|
5
|
+
# Represents a literal number that can be represented
|
|
6
|
+
# in multiple types
|
|
7
|
+
class NarrowingType < DelegateClass(PrimitiveType)
|
|
8
|
+
def initialize(default_type, narrowed_type)
|
|
9
|
+
super(default_type)
|
|
10
|
+
@narrowed = default_type != narrowed_type && narrowed_type
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def hash
|
|
14
|
+
__getobj__.hash
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Changes this type to the smallest type that will hold
|
|
18
|
+
# its literal value.
|
|
19
|
+
def narrow!
|
|
20
|
+
if @narrowed
|
|
21
|
+
__setobj__(@narrowed)
|
|
22
|
+
true
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
class FixnumLiteral < NarrowingType
|
|
28
|
+
def self.range(type)
|
|
29
|
+
type::MIN_VALUE .. type::MAX_VALUE
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
BYTE_RANGE = range(java.lang.Byte)
|
|
33
|
+
SHORT_RANGE = range(java.lang.Short)
|
|
34
|
+
INT_RANGE = range(java.lang.Integer)
|
|
35
|
+
LONG_RANGE = range(java.lang.Long)
|
|
36
|
+
|
|
37
|
+
def initialize(literal)
|
|
38
|
+
default_type = case literal
|
|
39
|
+
when INT_RANGE
|
|
40
|
+
Int
|
|
41
|
+
else
|
|
42
|
+
Long
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# TODO chars?
|
|
46
|
+
# There's not really any way to tell if we should narrow to a char
|
|
47
|
+
# or a byte/short. I suppose we could try both, but that seems ugly.
|
|
48
|
+
# Maybe it's the right thing to do though?
|
|
49
|
+
narrowed_type = case literal
|
|
50
|
+
when BYTE_RANGE
|
|
51
|
+
Byte
|
|
52
|
+
when SHORT_RANGE
|
|
53
|
+
Short
|
|
54
|
+
when INT_RANGE
|
|
55
|
+
Int
|
|
56
|
+
else
|
|
57
|
+
Long
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
super(default_type, narrowed_type)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
class FloatLiteral < NarrowingType
|
|
65
|
+
FLOAT_RANGE = java.lang.Float::MIN_VALUE .. java.lang.Float::MAX_VALUE
|
|
66
|
+
NaN = java.lang.Float::NaN
|
|
67
|
+
POSITIVE_INFINITY = java.lang.Float::POSITIVE_INFINITY
|
|
68
|
+
NEGATIVE_INFINITY = java.lang.Float::NEGATIVE_INFINITY
|
|
69
|
+
|
|
70
|
+
def initialize(literal)
|
|
71
|
+
super(Double, Double)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,614 @@
|
|
|
1
|
+
require 'mirah/jvm/types'
|
|
2
|
+
|
|
3
|
+
class Java::JavaMethod
|
|
4
|
+
def static?
|
|
5
|
+
java.lang.reflect.Modifier.static?(modifiers)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def abstract?
|
|
9
|
+
java.lang.reflect.Modifier.abstract?(modifiers)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
module Duby::JVM::Types
|
|
14
|
+
AST ||= Duby::AST
|
|
15
|
+
|
|
16
|
+
module ArgumentConversion
|
|
17
|
+
def convert_args(compiler, values, types=nil)
|
|
18
|
+
# TODO boxing/unboxing
|
|
19
|
+
# TODO varargs
|
|
20
|
+
types ||= argument_types
|
|
21
|
+
values.zip(types).each do |value, type|
|
|
22
|
+
compiler.compile(value, true)
|
|
23
|
+
if type.primitive? && type != value.inferred_type
|
|
24
|
+
value.inferred_type.widen(compiler.method, type)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
Type.send :include, ArgumentConversion
|
|
31
|
+
|
|
32
|
+
class Intrinsic
|
|
33
|
+
include ArgumentConversion
|
|
34
|
+
attr_reader :name, :argument_types, :return_type
|
|
35
|
+
|
|
36
|
+
def initialize(klass, name, args, type, &block)
|
|
37
|
+
raise ArgumentError, "Block required" unless block_given?
|
|
38
|
+
@class = klass
|
|
39
|
+
@name = name
|
|
40
|
+
@argument_types = args
|
|
41
|
+
@return_type = type
|
|
42
|
+
@block = block
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def call(builder, ast, expression)
|
|
46
|
+
@block.call(builder, ast, expression)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def declaring_class
|
|
50
|
+
@class
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def constructor?
|
|
54
|
+
false
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def field?
|
|
58
|
+
false
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def abstract?
|
|
62
|
+
false
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def exceptions
|
|
66
|
+
[]
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
class JavaCallable
|
|
71
|
+
include ArgumentConversion
|
|
72
|
+
|
|
73
|
+
attr_accessor :member
|
|
74
|
+
|
|
75
|
+
def initialize(member)
|
|
76
|
+
@member = member
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def name
|
|
80
|
+
@name ||= @member.name
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def field?
|
|
84
|
+
false
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def parameter_types
|
|
88
|
+
@member.parameter_types
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
class JavaConstructor < JavaCallable
|
|
93
|
+
def argument_types
|
|
94
|
+
@argument_types ||= @member.argument_types.map do |arg|
|
|
95
|
+
if arg.kind_of?(AST::TypeReference) || arg.nil?
|
|
96
|
+
arg
|
|
97
|
+
else
|
|
98
|
+
AST.type(nil, arg)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def return_type
|
|
104
|
+
declaring_class
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def exceptions
|
|
108
|
+
@member.exception_types.map do |exception|
|
|
109
|
+
if exception.kind_of?(Duby::JVM::Types::Type)
|
|
110
|
+
exception
|
|
111
|
+
else
|
|
112
|
+
Duby::AST.type(nil, exception.class_name)
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def declaring_class
|
|
118
|
+
AST.type(nil, @member.declaring_class)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def call(compiler, ast, expression)
|
|
122
|
+
target = ast.target.inferred_type
|
|
123
|
+
compiler.method.new target
|
|
124
|
+
compiler.method.dup if expression
|
|
125
|
+
convert_args(compiler, ast.parameters)
|
|
126
|
+
compiler.method.invokespecial(
|
|
127
|
+
target,
|
|
128
|
+
"<init>",
|
|
129
|
+
[nil, *@member.argument_types])
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def constructor?
|
|
133
|
+
true
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
class JavaMethod < JavaConstructor
|
|
138
|
+
def return_type
|
|
139
|
+
@return_type ||= begin
|
|
140
|
+
if void?
|
|
141
|
+
Void
|
|
142
|
+
else
|
|
143
|
+
AST.type(nil, @member.return_type)
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def static?
|
|
149
|
+
@member.static?
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def abstract?
|
|
153
|
+
@member.abstract?
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def void?
|
|
157
|
+
return_type = @member.return_type
|
|
158
|
+
return true if return_type.nil?
|
|
159
|
+
if return_type.respond_to?(:descriptor) && return_type.descriptor == 'V'
|
|
160
|
+
return true
|
|
161
|
+
end
|
|
162
|
+
false
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def constructor?
|
|
166
|
+
false
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def call(compiler, ast, expression)
|
|
170
|
+
target = ast.target.inferred_type
|
|
171
|
+
ast.target.compile(compiler, true)
|
|
172
|
+
|
|
173
|
+
# if expression, void methods return the called object,
|
|
174
|
+
# for consistency and chaining
|
|
175
|
+
# TODO: inference phase needs to track that signature is
|
|
176
|
+
# void but actual type is callee
|
|
177
|
+
if expression && void?
|
|
178
|
+
compiler.method.dup
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
convert_args(compiler, ast.parameters)
|
|
182
|
+
if target.interface?
|
|
183
|
+
compiler.method.invokeinterface(
|
|
184
|
+
target,
|
|
185
|
+
name,
|
|
186
|
+
[@member.return_type, *@member.argument_types])
|
|
187
|
+
else
|
|
188
|
+
compiler.method.invokevirtual(
|
|
189
|
+
target,
|
|
190
|
+
name,
|
|
191
|
+
[@member.return_type, *@member.argument_types])
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
unless expression || void?
|
|
195
|
+
if return_type.wide?
|
|
196
|
+
compiler.method.pop2
|
|
197
|
+
else
|
|
198
|
+
compiler.method.pop
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def call_special(compiler, ast, expression)
|
|
204
|
+
target = ast.target.inferred_type
|
|
205
|
+
ast.target.compile(compiler, true)
|
|
206
|
+
|
|
207
|
+
# if expression, void methods return the called object,
|
|
208
|
+
# for consistency and chaining
|
|
209
|
+
# TODO: inference phase needs to track that signature is
|
|
210
|
+
# void but actual type is callee
|
|
211
|
+
if expression && void?
|
|
212
|
+
compiler.method.dup
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
convert_args(compiler, ast.parameters)
|
|
216
|
+
if target.interface?
|
|
217
|
+
raise "interfaces should not receive call_special"
|
|
218
|
+
else
|
|
219
|
+
compiler.method.invokespecial(
|
|
220
|
+
target,
|
|
221
|
+
name,
|
|
222
|
+
[@member.return_type, *@member.argument_types])
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
unless expression || void?
|
|
226
|
+
compiler.method.pop
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
class JavaStaticMethod < JavaMethod
|
|
232
|
+
def call(compiler, ast, expression)
|
|
233
|
+
target = declaring_class
|
|
234
|
+
convert_args(compiler, ast.parameters)
|
|
235
|
+
compiler.method.invokestatic(
|
|
236
|
+
target,
|
|
237
|
+
name,
|
|
238
|
+
[@member.return_type, *@member.argument_types])
|
|
239
|
+
# if expression, void static methods return null, for consistency
|
|
240
|
+
# TODO: inference phase needs to track that signature is void
|
|
241
|
+
# but actual type is null object
|
|
242
|
+
compiler.method.aconst_null if expression && void?
|
|
243
|
+
compiler.method.pop unless expression || void?
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
class JavaDynamicMethod < JavaMethod
|
|
248
|
+
def initialize(name, *types)
|
|
249
|
+
@name = name
|
|
250
|
+
@types = types
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
def return_type
|
|
254
|
+
AST.type(nil, 'dynamic')
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def declaring_class
|
|
258
|
+
java.lang.Object
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def argument_types
|
|
262
|
+
@types
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
def call(compiler, ast, expression)
|
|
266
|
+
target = ast.target.inferred_type
|
|
267
|
+
ast.target.compile(compiler, true)
|
|
268
|
+
|
|
269
|
+
ast.parameters.each do |param|
|
|
270
|
+
param.compile(compiler, true)
|
|
271
|
+
end
|
|
272
|
+
compiler.method.invokedynamic(
|
|
273
|
+
target,
|
|
274
|
+
"dyn:callPropWithThis:#{name}",
|
|
275
|
+
[return_type, target, *@types])
|
|
276
|
+
|
|
277
|
+
unless expression
|
|
278
|
+
compiler.method.pop
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
compiler.bootstrap_dynamic
|
|
282
|
+
end
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
class JavaFieldAccessor < JavaMethod
|
|
286
|
+
def field?
|
|
287
|
+
true
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
def return_type
|
|
291
|
+
AST.type(nil, @member.type)
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
def public?
|
|
295
|
+
@member.public?
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
def final?
|
|
299
|
+
@member.final?
|
|
300
|
+
end
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
class JavaFieldGetter < JavaFieldAccessor
|
|
304
|
+
def argument_types
|
|
305
|
+
[]
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
def call(compiler, ast, expression)
|
|
309
|
+
target = ast.target.inferred_type
|
|
310
|
+
|
|
311
|
+
# TODO: assert that no args are being passed, though that should have failed lookup
|
|
312
|
+
|
|
313
|
+
if expression
|
|
314
|
+
if @member.static?
|
|
315
|
+
compiler.method.getstatic(target, name, @member.type)
|
|
316
|
+
else
|
|
317
|
+
ast.target.compile(compiler, true)
|
|
318
|
+
compiler.method.getfield(target, name, @member.type)
|
|
319
|
+
end
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
class JavaFieldSetter < JavaFieldAccessor
|
|
325
|
+
def return_type
|
|
326
|
+
AST.type(nil, @member.type)
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
def argument_types
|
|
330
|
+
[AST.type(nil, @member.type)]
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
def call(compiler, ast, expression)
|
|
334
|
+
target = ast.target.inferred_type
|
|
335
|
+
|
|
336
|
+
# TODO: assert that no args are being passed, though that should have failed lookup
|
|
337
|
+
|
|
338
|
+
if @member.static?
|
|
339
|
+
convert_args(compiler, ast.parameters)
|
|
340
|
+
compiler.method.dup if expression
|
|
341
|
+
compiler.method.putstatic(target, name, @member.type)
|
|
342
|
+
else
|
|
343
|
+
ast.target.compile(compiler, true)
|
|
344
|
+
convert_args(compiler, ast.parameters)
|
|
345
|
+
compiler.method.dup_x2 if expression
|
|
346
|
+
compiler.method.putfield(target, name, @member.type)
|
|
347
|
+
end
|
|
348
|
+
end
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
class DubyMember
|
|
352
|
+
attr_reader :name, :argument_types, :declaring_class, :return_type
|
|
353
|
+
attr_reader :exception_types
|
|
354
|
+
|
|
355
|
+
def initialize(klass, name, args, return_type, static, exceptions)
|
|
356
|
+
if return_type == Void
|
|
357
|
+
return_type = nil
|
|
358
|
+
end
|
|
359
|
+
@declaring_class = klass
|
|
360
|
+
@name = name
|
|
361
|
+
@argument_types = args
|
|
362
|
+
@return_type = return_type
|
|
363
|
+
@static = static
|
|
364
|
+
@exception_types = exceptions || []
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
def static?
|
|
368
|
+
@static
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
def abstract?
|
|
372
|
+
@declaring_class.interface?
|
|
373
|
+
end
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
class Type
|
|
377
|
+
def get_method(name, args)
|
|
378
|
+
method = find_method(self, name, args, meta?)
|
|
379
|
+
unless method
|
|
380
|
+
# Allow constant narrowing for assignment methods
|
|
381
|
+
if name =~ /=$/ && args[-1].respond_to?(:narrow!)
|
|
382
|
+
if args[-1].narrow!
|
|
383
|
+
method = find_method(self, name, args, meta?)
|
|
384
|
+
end
|
|
385
|
+
end
|
|
386
|
+
end
|
|
387
|
+
method
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
def constructor(*types)
|
|
391
|
+
begin
|
|
392
|
+
descriptors = types.map {|type| BiteScript::Signature.class_id(type)}
|
|
393
|
+
constructor = jvm_type.getConstructor(*descriptors)
|
|
394
|
+
return JavaConstructor.new(constructor) if constructor
|
|
395
|
+
rescue => ex
|
|
396
|
+
log(ex.message)
|
|
397
|
+
end
|
|
398
|
+
raise NameError, "No constructor #{name}(#{types.join ', '})"
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
def java_method(name, *types)
|
|
402
|
+
intrinsic = intrinsics[name][types]
|
|
403
|
+
return intrinsic if intrinsic
|
|
404
|
+
jvm_types = types.map {|type| type.jvm_type}
|
|
405
|
+
|
|
406
|
+
return JavaDynamicMethod.new(name, *jvm_types) if dynamic?
|
|
407
|
+
|
|
408
|
+
begin
|
|
409
|
+
descriptors = types.map {|type| BiteScript::Signature.class_id(type)}
|
|
410
|
+
method = jvm_type.getDeclaredMethod(name, *descriptors)
|
|
411
|
+
|
|
412
|
+
if method.nil? && superclass
|
|
413
|
+
method = superclass.java_method(name, *types) rescue nil
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
if method.nil? && jvm_type.abstract?
|
|
417
|
+
interfaces.each do |interface|
|
|
418
|
+
method = interface.java_method(name, *types) rescue nil
|
|
419
|
+
break if method
|
|
420
|
+
end
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
return method if method.kind_of?(JavaCallable)
|
|
424
|
+
if method && method.static? == meta?
|
|
425
|
+
return JavaStaticMethod.new(method) if method.static?
|
|
426
|
+
return JavaMethod.new(method)
|
|
427
|
+
end
|
|
428
|
+
rescue => ex
|
|
429
|
+
log(ex.message)
|
|
430
|
+
end
|
|
431
|
+
raise NameError, "No method #{self.name}.#{name}(#{types.join ', '})"
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
def declared_instance_methods(name=nil)
|
|
435
|
+
methods = []
|
|
436
|
+
if jvm_type && !array?
|
|
437
|
+
jvm_type.getDeclaredMethods(name).each do |method|
|
|
438
|
+
methods << JavaMethod.new(method) unless method.static?
|
|
439
|
+
end
|
|
440
|
+
end
|
|
441
|
+
methods.concat((meta? ? unmeta : self).declared_intrinsics(name))
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
def declared_class_methods(name=nil)
|
|
445
|
+
methods = []
|
|
446
|
+
if jvm_type && !unmeta.array?
|
|
447
|
+
jvm_type.getDeclaredMethods(name).each do |method|
|
|
448
|
+
methods << JavaStaticMethod.new(method) if method.static?
|
|
449
|
+
end
|
|
450
|
+
end
|
|
451
|
+
methods.concat(meta.declared_intrinsics(name))
|
|
452
|
+
end
|
|
453
|
+
|
|
454
|
+
def declared_constructors
|
|
455
|
+
jvm_type.getConstructors.map do |method|
|
|
456
|
+
JavaConstructor.new(method)
|
|
457
|
+
end
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
def field_getter(name)
|
|
461
|
+
if jvm_type
|
|
462
|
+
field = jvm_type.getField(name)
|
|
463
|
+
JavaFieldGetter.new(field) if field
|
|
464
|
+
else
|
|
465
|
+
nil
|
|
466
|
+
end
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
def field_setter(name)
|
|
470
|
+
if jvm_type
|
|
471
|
+
field = jvm_type.getField(name)
|
|
472
|
+
JavaFieldSetter.new(field) if field
|
|
473
|
+
else
|
|
474
|
+
nil
|
|
475
|
+
end
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
def inner_class_getter(name)
|
|
479
|
+
full_name = "#{self.name}$#{name}"
|
|
480
|
+
inner_class = Duby::AST.type(nil, full_name) rescue nil
|
|
481
|
+
return unless inner_class
|
|
482
|
+
inner_class.inner_class = true
|
|
483
|
+
add_macro(name) do |transformer, call|
|
|
484
|
+
Duby::AST::Constant.new(call.parent, call.position, full_name)
|
|
485
|
+
end
|
|
486
|
+
intrinsics[name][[]]
|
|
487
|
+
end
|
|
488
|
+
end
|
|
489
|
+
|
|
490
|
+
class TypeDefinition
|
|
491
|
+
def java_method(name, *types)
|
|
492
|
+
method = instance_methods[name].find {|m| m.argument_types == types}
|
|
493
|
+
return method if method
|
|
494
|
+
intrinsic = intrinsics[name][types]
|
|
495
|
+
return intrinsic if intrinsic
|
|
496
|
+
raise NameError, "No method #{self.name}.#{name}(#{types.join ', '})"
|
|
497
|
+
end
|
|
498
|
+
|
|
499
|
+
def java_static_method(name, *types)
|
|
500
|
+
method = static_methods[name].find {|m| m.argument_types == types}
|
|
501
|
+
return method if method
|
|
502
|
+
intrinsic = meta.intrinsics[name][types]
|
|
503
|
+
return intrinsic if intrinsic
|
|
504
|
+
raise NameError, "No method #{self.name}.#{name}(#{types.join ', '})"
|
|
505
|
+
end
|
|
506
|
+
|
|
507
|
+
def constructor(*types)
|
|
508
|
+
constructor = constructors.find {|c| c.argument_types == types}
|
|
509
|
+
return constructor if constructor
|
|
510
|
+
raise NameError, "No constructor #{name}(#{types.join ', '})"
|
|
511
|
+
end
|
|
512
|
+
|
|
513
|
+
def declared_instance_methods(name=nil)
|
|
514
|
+
declared_intrinsics(name) + if name.nil?
|
|
515
|
+
instance_methods.values.flatten
|
|
516
|
+
else
|
|
517
|
+
instance_methods[name]
|
|
518
|
+
end
|
|
519
|
+
end
|
|
520
|
+
|
|
521
|
+
def declared_class_methods(name=nil)
|
|
522
|
+
meta.declared_intrinsics(name) + if name.nil?
|
|
523
|
+
static_methods.values.flatten
|
|
524
|
+
else
|
|
525
|
+
static_methods[name]
|
|
526
|
+
end
|
|
527
|
+
end
|
|
528
|
+
|
|
529
|
+
def declared_constructors
|
|
530
|
+
constructors
|
|
531
|
+
end
|
|
532
|
+
|
|
533
|
+
def constructors
|
|
534
|
+
@constructors ||= []
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
def default_constructor
|
|
538
|
+
if constructors.empty?
|
|
539
|
+
declare_method('initialize', [], self, [])
|
|
540
|
+
@default_constructor_added = true
|
|
541
|
+
constructors[0]
|
|
542
|
+
else
|
|
543
|
+
constructor
|
|
544
|
+
end
|
|
545
|
+
end
|
|
546
|
+
|
|
547
|
+
def instance_methods
|
|
548
|
+
@instance_methods ||= Hash.new {|h, k| h[k] = []}
|
|
549
|
+
end
|
|
550
|
+
|
|
551
|
+
def static_methods
|
|
552
|
+
@static_methods ||= Hash.new {|h, k| h[k] = []}
|
|
553
|
+
end
|
|
554
|
+
|
|
555
|
+
def declare_method(name, arguments, type, exceptions)
|
|
556
|
+
raise "Bad args" unless arguments.all?
|
|
557
|
+
member = DubyMember.new(self, name, arguments, type, false, exceptions)
|
|
558
|
+
if name == 'initialize'
|
|
559
|
+
if @default_constructor_added
|
|
560
|
+
unless arguments.empty?
|
|
561
|
+
raise "Can't add constructor #{member} after using the default."
|
|
562
|
+
end
|
|
563
|
+
else
|
|
564
|
+
constructors << JavaConstructor.new(member)
|
|
565
|
+
end
|
|
566
|
+
else
|
|
567
|
+
instance_methods[name] << JavaMethod.new(member)
|
|
568
|
+
end
|
|
569
|
+
end
|
|
570
|
+
|
|
571
|
+
def declare_static_method(name, arguments, type, exceptions)
|
|
572
|
+
member = DubyMember.new(self, name, arguments, type, true, exceptions)
|
|
573
|
+
static_methods[name] << JavaStaticMethod.new(member)
|
|
574
|
+
end
|
|
575
|
+
|
|
576
|
+
def interface?
|
|
577
|
+
false
|
|
578
|
+
end
|
|
579
|
+
|
|
580
|
+
def field_getter(name)
|
|
581
|
+
nil
|
|
582
|
+
end
|
|
583
|
+
|
|
584
|
+
def field_setter(name)
|
|
585
|
+
nil
|
|
586
|
+
end
|
|
587
|
+
end
|
|
588
|
+
|
|
589
|
+
class TypeDefMeta
|
|
590
|
+
def constructor(*args)
|
|
591
|
+
unmeta.constructor(*args)
|
|
592
|
+
end
|
|
593
|
+
|
|
594
|
+
def java_method(*args)
|
|
595
|
+
unmeta.java_static_method(*args)
|
|
596
|
+
end
|
|
597
|
+
|
|
598
|
+
def declared_class_methods(name=nil)
|
|
599
|
+
unmeta.declared_class_methods(name)
|
|
600
|
+
end
|
|
601
|
+
|
|
602
|
+
def declared_instance_methods(name=nil)
|
|
603
|
+
unmeta.declared_instance_methods(name)
|
|
604
|
+
end
|
|
605
|
+
|
|
606
|
+
def field_getter(name)
|
|
607
|
+
nil
|
|
608
|
+
end
|
|
609
|
+
|
|
610
|
+
def field_setter(name)
|
|
611
|
+
nil
|
|
612
|
+
end
|
|
613
|
+
end
|
|
614
|
+
end
|