Class: Duby::JVM::Types::Type
- Inherits:
-
AST::TypeReference
show all
- Includes:
- MethodLookup
- Defined in:
- lib/duby/jvm/types.rb,
lib/duby/jvm/types/enumerable.rb,
lib/duby/jvm/source_generator/builder.rb,
lib/duby/jvm/types/intrinsics.rb,
lib/duby/jvm/types/methods.rb
Constant Summary
AST::TypeReference::BlockType, AST::TypeReference::ErrorType, AST::TypeReference::NoType, AST::TypeReference::NullType, AST::TypeReference::UnreachableType
Instance Attribute Summary collapse
#array
Attributes included from AST::Named
#name
Attributes inherited from AST::Node
#children, #inferred_type, #newline, #parent, #position
Instance Method Summary
collapse
-
#add_enumerable_macros ⇒ Object
-
#add_intrinsics ⇒ Object
-
#add_macro(name, *args, &block) ⇒ Object
-
#add_method(name, args, method_or_type = nil, &block) ⇒ Object
-
#aload(builder) ⇒ Object
-
#array? ⇒ Boolean
-
#array_type ⇒ Object
-
#assignable_from?(other) ⇒ Boolean
-
#astore(builder) ⇒ Object
-
#basic_type ⇒ Object
-
#compatible?(other) ⇒ Boolean
-
#component_type ⇒ Object
-
#constructor(*types) ⇒ Object
-
#declared_class_methods(name = nil) ⇒ Object
-
#declared_constructors ⇒ Object
-
#declared_instance_methods(name = nil) ⇒ Object
-
#declared_intrinsics(name = nil) ⇒ Object
-
#dynamic? ⇒ Boolean
-
#expand_each(transformer, call) ⇒ Object
-
#field_getter(name) ⇒ Object
-
#field_setter(name) ⇒ Object
-
#get_method(name, args) ⇒ Object
-
#init_value(builder) ⇒ Object
-
#initialize(mirror_or_name) ⇒ Type
constructor
-
#inner_class? ⇒ Boolean
-
#inner_class_getter(name) ⇒ Object
-
#inspect(indent = 0) ⇒ Object
-
#interface? ⇒ Boolean
-
#interfaces ⇒ Object
-
#intrinsics ⇒ Object
-
#is_parent(other) ⇒ Object
-
#iterable? ⇒ Boolean
-
#java_method(name, *types) ⇒ Object
-
#jvm_type ⇒ Object
-
#load(builder, index) ⇒ Object
-
#log(message) ⇒ Object
-
#meta ⇒ Object
-
#meta? ⇒ Boolean
-
#newarray(method) ⇒ Object
-
#prefix ⇒ Object
-
#primitive? ⇒ Boolean
-
#return(builder) ⇒ Object
-
#store(builder, index) ⇒ Object
-
#superclass ⇒ Object
-
#to_source ⇒ Object
-
#unmeta ⇒ Object
-
#void? ⇒ Boolean
-
#wide? ⇒ Boolean
#each_is_exact, #each_is_exact_or_subtype_or_convertible, #field_lookup, #find_jls, #find_method, #inner_class, #is_more_specific?, #phase1, #phase2, #phase3, #primitive_convertible?
#==, #block?, #eql?, #error?, #hash, #narrow, #null?, #to_s, #unreachable?
Methods included from AST::Named
#to_s
Methods inherited from AST::Node
#<<, ===, #[], #_set_parent, child, child_name, #each, #empty?, #expr?, #initialize_copy, #insert, #line_number, #precompile, #resolve_if, #resolved!, #resolved?, #simple_name, #temp, #to_s
Constructor Details
#initialize(mirror_or_name) ⇒ Type
Returns a new instance of Type.
18
19
20
21
22
23
24
25
26
27
|
# File 'lib/duby/jvm/types.rb', line 18
def initialize(mirror_or_name)
if mirror_or_name.kind_of?(BiteScript::ASM::ClassMirror)
@type = mirror_or_name
name = mirror_or_name.type.class_name
else
name = mirror_or_name.to_s
end
super(name, false, false)
raise ArgumentError, "Bad type #{mirror_or_name}" if name =~ /Java::/
end
|
Instance Attribute Details
#inner_class=(value) ⇒ Object
Sets the attribute inner_class
12
13
14
|
# File 'lib/duby/jvm/types.rb', line 12
def inner_class=(value)
@inner_class = value
end
|
Instance Method Details
#add_enumerable_macros ⇒ Object
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
# File 'lib/duby/jvm/types/enumerable.rb', line 9
def add_enumerable_macros
all_proc = proc do |transformer, call|
if !call.block
var = transformer.tmp
call.block = transformer.eval("foo {|#{var}| #{var}}").block
end
forloop = expand_each(transformer, call)
all = transformer.tmp
forloop.init << transformer.eval("#{all} = true")
body = transformer.eval(
"unless foo;#{all} = false;break;end", '', forloop)
body.condition.predicate = call.block.body
forloop.body = call.block.body.parent = body
result = Duby::AST::Body.new(call.parent, call.position)
result << forloop << transformer.eval("#{all}", '', nil, all)
end
add_macro('all?', &all_proc)
add_macro('all?', Duby::AST.block_type, &all_proc)
any_proc = proc do |transformer, call|
if !call.block
var = transformer.tmp
call.block = transformer.eval("foo {|#{var}| #{var}}").block
end
forloop = expand_each(transformer, call)
any = transformer.tmp
forloop.init << transformer.eval("#{any} = false")
body = transformer.eval(
"if foo;#{any} = true;break;end", '', forloop)
body.condition.predicate = call.block.body
forloop.body = call.block.body.parent = body
result = Duby::AST::Body.new(call.parent, call.position)
result << forloop << transformer.eval("#{any}", '', nil, any)
end
add_macro('any?', &any_proc)
add_macro('any?', Duby::AST.block_type, &any_proc)
end
|
#add_intrinsics ⇒ Object
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
# File 'lib/duby/jvm/types/intrinsics.rb', line 77
def add_intrinsics
add_method('nil?', [], Boolean) do |compiler, call, expression|
if expression
call.target.compile(compiler, true)
compiler.method.op_to_bool do |target|
compiler.method.ifnull(target)
end
end
end
add_method('==', [Object], Boolean) do |compiler, call, expression|
if expression
call.target.compile(compiler, true)
call.parameters[0].compile(compiler, true)
compiler.method.op_to_bool do |target|
compiler.method.if_acmpeq(target)
end
end
end
add_method('!=', [Object], Boolean) do |compiler, call, expression|
if expression
call.target.compile(compiler, true)
call.parameters[0].compile(compiler, true)
compiler.method.op_to_bool do |target|
compiler.method.if_acmpne(target)
end
end
end
end
|
#add_macro(name, *args, &block) ⇒ Object
52
53
54
55
56
57
|
# File 'lib/duby/jvm/types/intrinsics.rb', line 52
def add_macro(name, *args, &block)
type = Duby::AST::InlineCode.new(&block)
intrinsics[name][args] = Intrinsic.new(self, name, args, type) do
raise "Macro should be expanded, no called!"
end
end
|
#add_method(name, args, method_or_type = nil, &block) ⇒ Object
44
45
46
47
48
49
50
|
# File 'lib/duby/jvm/types/intrinsics.rb', line 44
def add_method(name, args, method_or_type=nil, &block)
if block_given?
method_or_type = Intrinsic.new(self, name, args,
method_or_type, &block)
end
intrinsics[name][args] = method_or_type
end
|
#aload(builder) ⇒ Object
147
148
149
150
151
152
153
|
# File 'lib/duby/jvm/types.rb', line 147
def aload(builder)
if primitive?
builder.send "#{name[0,1]}aload"
else
builder.aaload
end
end
|
41
42
43
|
# File 'lib/duby/jvm/types.rb', line 41
def array?
false
end
|
#array_type ⇒ Object
106
107
108
|
# File 'lib/duby/jvm/types.rb', line 106
def array_type
@array_type ||= Duby::JVM::Types::ArrayType.new(self)
end
|
#assignable_from?(other) ⇒ Boolean
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
# File 'lib/duby/jvm/types.rb', line 69
def assignable_from?(other)
return false if other.nil?
return true if !primitive? && other == Null
return true if other == self
return true if other.error? || other.unreachable?
return interface? if other.block?
return true if jvm_type && (jvm_type == other.jvm_type)
assignable_from?(other.superclass) ||
other.interfaces.any? {|i| assignable_from?(i)}
end
|
#astore(builder) ⇒ Object
139
140
141
142
143
144
145
|
# File 'lib/duby/jvm/types.rb', line 139
def astore(builder)
if primitive?
builder.send "#{name[0,1]}astore"
else
builder.aastore
end
end
|
#basic_type ⇒ Object
102
103
104
|
# File 'lib/duby/jvm/types.rb', line 102
def basic_type
self
end
|
#compatible?(other) ⇒ Boolean
65
66
67
|
# File 'lib/duby/jvm/types.rb', line 65
def compatible?(other)
assignable_from?(other)
end
|
#component_type ⇒ Object
90
91
92
|
# File 'lib/duby/jvm/types.rb', line 90
def component_type
AST.type('java.lang.Object') if iterable?
end
|
#constructor(*types) ⇒ Object
400
401
402
403
404
405
406
407
408
409
|
# File 'lib/duby/jvm/types/methods.rb', line 400
def constructor(*types)
begin
descriptors = types.map {|type| BiteScript::Signature.class_id(type)}
constructor = jvm_type.getConstructor(*descriptors)
return JavaConstructor.new(constructor) if constructor
rescue => ex
log(ex.message)
end
raise NameError, "No constructor #{name}(#{types.join ', '})"
end
|
#declared_class_methods(name = nil) ⇒ Object
453
454
455
456
457
458
459
|
# File 'lib/duby/jvm/types/methods.rb', line 453
def declared_class_methods(name=nil)
methods = []
jvm_type.getDeclaredMethods(name).each do |method|
methods << JavaStaticMethod.new(method) if method.static?
end
methods.concat(meta.declared_intrinsics(name))
end
|
#declared_constructors ⇒ Object
461
462
463
464
465
|
# File 'lib/duby/jvm/types/methods.rb', line 461
def declared_constructors
jvm_type.getConstructors.map do |method|
JavaConstructor.new(method)
end
end
|
#declared_instance_methods(name = nil) ⇒ Object
443
444
445
446
447
448
449
450
451
|
# File 'lib/duby/jvm/types/methods.rb', line 443
def declared_instance_methods(name=nil)
methods = []
if jvm_type && !array?
jvm_type.getDeclaredMethods(name).each do |method|
methods << JavaMethod.new(method) unless method.static?
end
end
methods.concat((meta? ? unmeta : self).declared_intrinsics(name))
end
|
#declared_intrinsics(name = nil) ⇒ Object
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
# File 'lib/duby/jvm/types/intrinsics.rb', line 59
def declared_intrinsics(name=nil)
methods = []
all_intrinsics = if name.nil?
intrinsics
else
[[name, intrinsics[name]]]
end
all_intrinsics.each do |name, group|
group.each do |args, method|
methods << method
end
end
interfaces.each do |interface|
methods.concat(interface.declared_intrinsics(name))
end
methods
end
|
53
54
55
|
# File 'lib/duby/jvm/types.rb', line 53
def dynamic?
false
end
|
#expand_each(transformer, call) ⇒ Object
3
4
5
6
7
|
# File 'lib/duby/jvm/types/enumerable.rb', line 3
def expand_each(transformer, call)
arg_types = [Duby::AST.block_type]
code = intrinsics['each'][arg_types].return_type
code.inline(transformer, call)
end
|
#field_getter(name) ⇒ Object
467
468
469
470
471
472
473
474
|
# File 'lib/duby/jvm/types/methods.rb', line 467
def field_getter(name)
if jvm_type
field = jvm_type.getField(name)
JavaFieldGetter.new(field) if field
else
nil
end
end
|
#field_setter(name) ⇒ Object
476
477
478
479
480
481
482
483
|
# File 'lib/duby/jvm/types/methods.rb', line 476
def field_setter(name)
if jvm_type
field = jvm_type.getField(name)
JavaFieldSetter.new(field) if field
else
nil
end
end
|
#get_method(name, args) ⇒ Object
387
388
389
390
391
392
393
394
395
396
397
398
|
# File 'lib/duby/jvm/types/methods.rb', line 387
def get_method(name, args)
method = find_method(self, name, args, meta?)
unless method
if name =~ /=$/ && args[-1].respond_to?(:narrow!)
if args[-1].narrow!
method = find_method(self, name, args, meta?)
end
end
end
method
end
|
#init_value(builder) ⇒ Object
32
33
34
|
# File 'lib/duby/jvm/types/intrinsics.rb', line 32
def init_value(builder)
builder.aconst_null
end
|
#inner_class? ⇒ Boolean
57
58
59
|
# File 'lib/duby/jvm/types.rb', line 57
def inner_class?
@inner_class
end
|
#inner_class_getter(name) ⇒ Object
485
486
487
488
489
490
491
492
493
494
|
# File 'lib/duby/jvm/types/methods.rb', line 485
def inner_class_getter(name)
full_name = "#{self.name}$#{name}"
inner_class = Duby::AST.type(full_name) rescue nil
return unless inner_class
inner_class.inner_class = true
add_macro(name) do |transformer, call|
Duby::AST::Constant.new(call.parent, call.position, full_name)
end
intrinsics[name][[]]
end
|
#inspect(indent = 0) ⇒ Object
119
120
121
|
# File 'lib/duby/jvm/types.rb', line 119
def inspect(indent=0)
"#{' ' * indent}#<#{self.class.name} #{name}>"
end
|
49
50
51
|
# File 'lib/duby/jvm/types.rb', line 49
def interface?
@type.interface?
end
|
#interfaces ⇒ Object
132
133
134
135
136
137
|
# File 'lib/duby/jvm/types.rb', line 132
def interfaces
raise "Incomplete type #{self} (#{self.class})" unless jvm_type
@interfaces ||= jvm_type.interfaces.map do |interface|
AST.type(interface)
end
end
|
#intrinsics ⇒ Object
36
37
38
39
40
41
42
|
# File 'lib/duby/jvm/types/intrinsics.rb', line 36
def intrinsics
@intrinsics ||= begin
@intrinsics = Hash.new {|h, k| h[k] = {}}
add_intrinsics
@intrinsics
end
end
|
#is_parent(other) ⇒ Object
61
62
63
|
# File 'lib/duby/jvm/types.rb', line 61
def is_parent(other)
assignable_from?(other)
end
|
84
85
86
87
88
|
# File 'lib/duby/jvm/types.rb', line 84
def iterable?
['java.lang.Iterable',
'java.util.Iterator',
'java.util.Enumeration'].any? {|n| AST.type(n).assignable_from(self)}
end
|
#java_method(name, *types) ⇒ Object
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
|
# File 'lib/duby/jvm/types/methods.rb', line 411
def java_method(name, *types)
intrinsic = intrinsics[name][types]
return intrinsic if intrinsic
jvm_types = types.map {|type| type.jvm_type}
return JavaDynamicMethod.new(name, *jvm_types) if dynamic?
begin
descriptors = types.map {|type| BiteScript::Signature.class_id(type)}
method = jvm_type.getDeclaredMethod(name, *descriptors)
if method.nil? && superclass
method = superclass.java_method(name, *types) rescue nil
end
if method.nil? && jvm_type.abstract?
interfaces.each do |interface|
method = interface.java_method(name, *types) rescue nil
break if method
end
end
if method && method.static? == meta?
return JavaStaticMethod.new(method) if method.static?
return JavaMethod.new(method)
end
rescue => ex
log(ex.message)
end
raise NameError, "No method #{self.name}.#{name}(#{types.join ', '})"
end
|
29
30
31
|
# File 'lib/duby/jvm/types.rb', line 29
def jvm_type
@type
end
|
#load(builder, index) ⇒ Object
20
21
22
|
# File 'lib/duby/jvm/types/intrinsics.rb', line 20
def load(builder, index)
builder.send "#{prefix}load", index
end
|
#log(message) ⇒ Object
14
15
16
|
# File 'lib/duby/jvm/types.rb', line 14
def log(message)
puts "* [JVM::Types] #{message}" if Duby::Compiler::JVM.verbose
end
|
94
95
96
|
# File 'lib/duby/jvm/types.rb', line 94
def meta
@meta ||= MetaType.new(self)
end
|
37
38
39
|
# File 'lib/duby/jvm/types.rb', line 37
def meta?
false
end
|
#newarray(method) ⇒ Object
123
124
125
|
# File 'lib/duby/jvm/types.rb', line 123
def newarray(method)
method.anewarray(self)
end
|
110
111
112
|
# File 'lib/duby/jvm/types.rb', line 110
def prefix
'a'
end
|
45
46
47
|
# File 'lib/duby/jvm/types.rb', line 45
def primitive?
false
end
|
#return(builder) ⇒ Object
28
29
30
|
# File 'lib/duby/jvm/types/intrinsics.rb', line 28
def return(builder)
builder.send "#{prefix}return"
end
|
#store(builder, index) ⇒ Object
24
25
26
|
# File 'lib/duby/jvm/types/intrinsics.rb', line 24
def store(builder, index)
builder.send "#{prefix}store", index
end
|
#superclass ⇒ Object
127
128
129
130
|
# File 'lib/duby/jvm/types.rb', line 127
def superclass
raise "Incomplete type #{self}" unless jvm_type
AST.type(jvm_type.superclass) if jvm_type.superclass
end
|
#to_source ⇒ Object
5
6
7
8
9
|
# File 'lib/duby/jvm/source_generator/builder.rb', line 5
def to_source
java_name = name
java_name = java_name.tr '$', '.' if inner_class?
"#{java_name}#{'[]' if array?}"
end
|
98
99
100
|
# File 'lib/duby/jvm/types.rb', line 98
def unmeta
self
end
|
33
34
35
|
# File 'lib/duby/jvm/types.rb', line 33
def void?
false
end
|
115
116
117
|
# File 'lib/duby/jvm/types.rb', line 115
def wide?
false
end
|