Class: Duby::JVM::Types::Type

Inherits:
AST::TypeReference show all
Includes:
MethodLookup
Defined in:
lib/duby/jvm/types.rb,
lib/duby/jvm/source_generator/builder.rb,
lib/duby/jvm/types/intrinsics.rb,
lib/duby/jvm/types/methods.rb

Constant Summary

Constants included from MethodLookup

MethodLookup::BOOLEAN, MethodLookup::BYTE, MethodLookup::CHAR, MethodLookup::DOUBLE, MethodLookup::FLOAT, MethodLookup::INT, MethodLookup::LONG, MethodLookup::PrimitiveConversions, MethodLookup::SHORT

Constants inherited from AST::TypeReference

AST::TypeReference::ErrorType, AST::TypeReference::NoType, AST::TypeReference::NullType, AST::TypeReference::UnreachableType

Instance Attribute Summary

Attributes inherited from AST::TypeReference

#array

Attributes included from AST::Named

#name

Attributes inherited from AST::Node

#children, #inferred_type, #newline, #parent, #position

Instance Method Summary collapse

Methods included from MethodLookup

#each_is_exact, #each_is_exact_or_subtype_or_convertible, #find_jls, #find_method, #is_more_specific?, #log, #phase1, #phase2, #phase3, #primitive_convertible?

Methods inherited from AST::TypeReference

#==, #eql?, #error?, #hash, #narrow, #to_s, #unreachable?

Methods included from AST::Named

#to_s

Methods inherited from AST::Node

#[], #each, #expr?, #line_number, #log, #precompile, #resolve_if, #resolved!, #resolved?, #simple_name, #temp, #to_s

Constructor Details

#initialize(java_type) ⇒ Type

Returns a new instance of Type.

Raises:

  • (ArgumentError)


17
18
19
20
21
22
23
24
25
26
# File 'lib/duby/jvm/types.rb', line 17

def initialize(java_type)
  orig_type = java_type
  if !(java_type.kind_of?(Java::JavaClass) ||
       java_type.class_builder?)
    java_type = java_type.java_class
  end
  super(java_type.name, false, false)
  raise ArgumentError, "Bad type #{orig_type}" if name =~ /Java::/
  @type = java_type
end

Instance Method Details

#add_intrinsicsObject



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/duby/jvm/types/intrinsics.rb', line 61

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|
    # Should this call Object.equals for consistency with Ruby?
    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|
    # Should this call Object.equals for consistency with Ruby?
    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_method(name, args, method_or_type = nil, &block) ⇒ Object



43
44
45
46
47
48
49
# File 'lib/duby/jvm/types/intrinsics.rb', line 43

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



134
135
136
137
138
139
140
# File 'lib/duby/jvm/types.rb', line 134

def aload(builder)
  if primitive?
    builder.send "#{name[0,1]}aload"
  else
    builder.aaload
  end
end

#array?Boolean

Returns:



40
41
42
# File 'lib/duby/jvm/types.rb', line 40

def array?
  false
end

#array_typeObject



94
95
96
# File 'lib/duby/jvm/types.rb', line 94

def array_type
  @array_type ||= ArrayType.new(self)
end

#assignable_from?(other) ⇒ Boolean

Returns:



60
61
62
63
64
65
66
67
68
69
70
# File 'lib/duby/jvm/types.rb', line 60

def assignable_from?(other)
  return true if !primitive? && other == Null
  return true if other == self
  return true if other.error? || other.unreachable?
  begin
    jvm_type.assignable_from?(other.jvm_type)
  rescue
    assignable_from?(other.superclass) ||
        other.interfaces.any? {|i| assignable_from?(i)}
  end
end

#astore(builder) ⇒ Object



126
127
128
129
130
131
132
# File 'lib/duby/jvm/types.rb', line 126

def astore(builder)
  if primitive?
    builder.send "#{name[0,1]}astore"
  else
    builder.aastore
  end
end

#basic_typeObject



90
91
92
# File 'lib/duby/jvm/types.rb', line 90

def basic_type
  self
end

#compatible?(other) ⇒ Boolean

Returns:



56
57
58
# File 'lib/duby/jvm/types.rb', line 56

def compatible?(other)
  assignable_from?(other)
end

#component_typeObject



78
79
80
# File 'lib/duby/jvm/types.rb', line 78

def component_type
  AST.type('java.lang.Object') if iterable?
end

#constructor(*types) ⇒ Object

Raises:

  • (NameError)


235
236
237
238
239
240
# File 'lib/duby/jvm/types/methods.rb', line 235

def constructor(*types)
  types = types.map {|type| type.jvm_type}
  constructor = (jvm_type.constructor(*types) rescue nil)
  return JavaConstructor.new(constructor) if constructor
  raise NameError, "No constructor #{name}(#{types.join ', '})"
end

#declared_class_methodsObject



265
266
267
268
269
270
# File 'lib/duby/jvm/types/methods.rb', line 265

def declared_class_methods
  methods = jvm_type.declared_class_methods.map do |method|
    JavaStaticMethod.new(method)
  end
  methods.concat(meta.declared_intrinsics)
end

#declared_instance_methodsObject



254
255
256
257
258
259
260
261
262
263
# File 'lib/duby/jvm/types/methods.rb', line 254

def declared_instance_methods
  if jvm_type && !array?
    methods = jvm_type.declared_instance_methods.map do |method|
      JavaMethod.new(method)
    end
  else
    methods = []
  end
  methods.concat((meta? ? unmeta : self).declared_intrinsics)
end

#declared_intrinsicsObject



51
52
53
54
55
56
57
58
59
# File 'lib/duby/jvm/types/intrinsics.rb', line 51

def declared_intrinsics
  methods = []
  intrinsics.each do |name, group|
    group.each do |args, method|
      methods << method
    end
  end
  methods
end

#get_method(name, args) ⇒ Object



222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/duby/jvm/types/methods.rb', line 222

def get_method(name, args)
  method = find_method(self, name, args, meta?)
  unless method
    # Allow constant narrowing for assignment methods
    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



31
32
33
# File 'lib/duby/jvm/types/intrinsics.rb', line 31

def init_value(builder)
  builder.aconst_null
end

#inspect(indent = 0) ⇒ Object



107
108
109
# File 'lib/duby/jvm/types.rb', line 107

def inspect(indent=0)
  "#{' ' * indent}#<#{self.class.name} #{name}>"
end

#interface?Boolean

Returns:



48
49
50
# File 'lib/duby/jvm/types.rb', line 48

def interface?
  @type.interface?
end

#interfacesObject



120
121
122
123
124
# File 'lib/duby/jvm/types.rb', line 120

def interfaces
  @interfaces ||= jvm_type.interfaces.map do |interface|
    AST.type(interface)
  end
end

#intrinsicsObject



35
36
37
38
39
40
41
# File 'lib/duby/jvm/types/intrinsics.rb', line 35

def intrinsics
  @intrinsics ||= begin
    @intrinsics = Hash.new {|h, k| h[k] = {}}
    add_intrinsics
    @intrinsics
  end
end

#is_parent(other) ⇒ Object



52
53
54
# File 'lib/duby/jvm/types.rb', line 52

def is_parent(other)
  assignable_from?(other)
end

#iterable?Boolean

Returns:



72
73
74
75
76
# File 'lib/duby/jvm/types.rb', line 72

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

Raises:

  • (NameError)


242
243
244
245
246
247
248
249
250
251
252
# File 'lib/duby/jvm/types/methods.rb', line 242

def java_method(name, *types)
  intrinsic = intrinsics[name][types]
  return intrinsic if intrinsic
  types = types.map {|type| type.jvm_type}
  method = (jvm_type.java_method(name, *types) rescue nil)
  if method && method.static? == meta?
    return JavaStaticMethod.new(method) if method.static?
    return JavaMethod.new(method)
  end
  raise NameError, "No method #{self.name}.#{name}(#{types.join ', '})"
end

#jvm_typeObject



28
29
30
# File 'lib/duby/jvm/types.rb', line 28

def jvm_type
  @type
end

#load(builder, index) ⇒ Object



19
20
21
# File 'lib/duby/jvm/types/intrinsics.rb', line 19

def load(builder, index)
  builder.send "#{prefix}load", index
end

#metaObject



82
83
84
# File 'lib/duby/jvm/types.rb', line 82

def meta
  @meta ||= MetaType.new(self)
end

#meta?Boolean

Returns:



36
37
38
# File 'lib/duby/jvm/types.rb', line 36

def meta?
  false
end

#newarray(method) ⇒ Object



111
112
113
# File 'lib/duby/jvm/types.rb', line 111

def newarray(method)
  method.anewarray(self)
end

#prefixObject



98
99
100
# File 'lib/duby/jvm/types.rb', line 98

def prefix
  'a'
end

#primitive?Boolean

Returns:



44
45
46
# File 'lib/duby/jvm/types.rb', line 44

def primitive?
  false
end

#return(builder) ⇒ Object



27
28
29
# File 'lib/duby/jvm/types/intrinsics.rb', line 27

def return(builder)
  builder.send "#{prefix}return"
end

#store(builder, index) ⇒ Object



23
24
25
# File 'lib/duby/jvm/types/intrinsics.rb', line 23

def store(builder, index)
  builder.send "#{prefix}store", index
end

#superclassObject



115
116
117
118
# File 'lib/duby/jvm/types.rb', line 115

def superclass
  raise "Incomplete type #{self}" unless jvm_type
  AST.type(jvm_type.superclass) if jvm_type.superclass
end

#to_sourceObject



5
6
7
# File 'lib/duby/jvm/source_generator/builder.rb', line 5

def to_source
  "#{name}#{'[]' if array?}"
end

#unmetaObject



86
87
88
# File 'lib/duby/jvm/types.rb', line 86

def unmeta
  self
end

#void?Boolean

Returns:



32
33
34
# File 'lib/duby/jvm/types.rb', line 32

def void?
  false
end

#wide?Boolean

is this a 64 bit type?

Returns:



103
104
105
# File 'lib/duby/jvm/types.rb', line 103

def wide?
  false
end