Module: Duby::JVM::MethodLookup
- Included in:
- Compiler::JVM, Types::Type, Typer::JavaTyper
- Defined in:
- lib/duby/jvm/method_lookup.rb
Constant Summary collapse
- BOOLEAN =
Java::boolean.java_class
- BYTE =
Java::byte.java_class
- SHORT =
Java::short.java_class
- CHAR =
Java::char.java_class
- INT =
Java::int.java_class
- LONG =
Java::long.java_class
- FLOAT =
Java::float.java_class
- DOUBLE =
Java::double.java_class
- PrimitiveConversions =
{ BOOLEAN => [BOOLEAN], BYTE => [BYTE, SHORT, CHAR, INT, LONG, FLOAT, DOUBLE], SHORT => [SHORT, INT, LONG, FLOAT, DOUBLE], CHAR => [CHAR, INT, LONG, FLOAT, DOUBLE], INT => [INT, LONG, FLOAT, DOUBLE], LONG => [LONG, DOUBLE], FLOAT => [FLOAT, DOUBLE], DOUBLE => [DOUBLE] }
Instance Method Summary collapse
- #each_is_exact(incoming, target) ⇒ Object
- #each_is_exact_or_subtype_or_convertible(incoming, target) ⇒ Object
- #find_jls(mapped_type, name, mapped_params, meta) ⇒ Object
-
#find_method(mapped_type, name, mapped_params, meta) ⇒ Object
def jvm_type(type) return type if type.kind_of? Java::JavaClass return type.jvm_type end.
- #is_more_specific?(potential, current) ⇒ Boolean
-
#log(msg) ⇒ Object
dummy log; it’s expected the inclusion target will have it.
- #phase1(mapped_params, potentials) ⇒ Object
- #phase2(mapped_params, potentials) ⇒ Object
- #phase3(mapped_params, potentials) ⇒ Object
- #primitive_convertible?(in_type, target_type) ⇒ Boolean
Instance Method Details
#each_is_exact(incoming, target) ⇒ Object
125 126 127 128 129 130 131 132 133 |
# File 'lib/duby/jvm/method_lookup.rb', line 125 def each_is_exact(incoming, target) incoming.each_with_index do |in_type, i| target_type = target[i] # exact match return false unless target_type == in_type end return true end |
#each_is_exact_or_subtype_or_convertible(incoming, target) ⇒ Object
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/duby/jvm/method_lookup.rb', line 135 def each_is_exact_or_subtype_or_convertible(incoming, target) incoming.each_with_index do |in_type, i| target_type = target[i] # exact match next if target_type == in_type # primitive is safely convertible if target_type.primitive? if in_type.primitive? next if primitive_convertible? in_type, target_type end return false end # object type is assignable return false unless target_type.assignable_from? in_type end return true end |
#find_jls(mapped_type, name, mapped_params, meta) ⇒ Object
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/duby/jvm/method_lookup.rb', line 52 def find_jls(mapped_type, name, mapped_params, ) # mapped_type = jvm_type(mapped_type) # mapped_params = convert_params(mapped_params) if all_methods = mapped_type.declared_class_methods else all_methods = [] cls = mapped_type while cls all_methods += cls.declared_instance_methods cls = cls.superclass end end by_name = all_methods.select {|m| m.name == name && mapped_params.size <= m.argument_types.size} by_name_and_arity = by_name.select {|m| m.argument_types.size == mapped_params.size} phase1_methods = phase1(mapped_params, by_name_and_arity) if phase1_methods.size > 1 raise "Ambiguous targets invoking #{mapped_type}.#{name}:\n#{phase1_methods}" end phase1_methods[0] || phase2(mapped_params, by_name) || phase3(mapped_params, by_name) end |
#find_method(mapped_type, name, mapped_params, meta) ⇒ Object
def jvm_type(type)
return type if type.kind_of? Java::JavaClass
return type.jvm_type
end
def convert_params(params)
params.map {|param| jvm_type(param)}
end
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 |
# File 'lib/duby/jvm/method_lookup.rb', line 16 def find_method(mapped_type, name, mapped_params, ) # mapped_type = jvm_type(mapped_type) # mapped_params = convert_params(mapped_params) raise ArgumentError if mapped_params.any? {|p| p.nil?} if name == 'new' if name = "<init>" constructor = true else constructor = false end end begin if constructor method = mapped_type.constructor(*mapped_params) else method = mapped_type.java_method(name, *mapped_params) end rescue NameError unless constructor # exact args failed, do a deeper search log "Failed to locate method #{mapped_type}.#{name}(#{mapped_params})" method = find_jls(mapped_type, name, mapped_params, ) end unless method log "Failed to locate method #{name}(#{mapped_params}) on #{mapped_type}" return nil end end log "Found method #{method.declaring_class}.#{name}(#{method.argument_types}) from #{mapped_type}" return method end |
#is_more_specific?(potential, current) ⇒ Boolean
113 114 115 |
# File 'lib/duby/jvm/method_lookup.rb', line 113 def is_more_specific?(potential, current) each_is_exact_or_subtype_or_convertible(potential, current) end |
#log(msg) ⇒ Object
dummy log; it’s expected the inclusion target will have it
5 |
# File 'lib/duby/jvm/method_lookup.rb', line 5 def log(msg); end |
#phase1(mapped_params, potentials) ⇒ Object
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 109 110 111 |
# File 'lib/duby/jvm/method_lookup.rb', line 79 def phase1(mapped_params, potentials) # cycle through methods looking for more specific matches; gather matches of equal specificity methods = potentials.inject([]) do |currents, potential| method_params = potential.argument_types # exact match always wins; duplicates not possible return [potential] if each_is_exact(mapped_params, method_params) # otherwise, check for potential match and compare to current # TODO: missing ambiguity check; picks last method of equal specificity if each_is_exact_or_subtype_or_convertible(mapped_params, method_params) if currents.size > 0 if is_more_specific?(potential.argument_types, currents[0].argument_types) # potential is better, dump all currents currents = [potential] elsif is_more_specific?(currents[0].argument_types, potential.argument_types) # currents are better, try next potential #next else # equal specificity, append to currents currents << potential end else # no previous matches, use potential currents = [potential] end end currents end methods end |
#phase2(mapped_params, potentials) ⇒ Object
117 118 119 |
# File 'lib/duby/jvm/method_lookup.rb', line 117 def phase2(mapped_params, potentials) nil end |
#phase3(mapped_params, potentials) ⇒ Object
121 122 123 |
# File 'lib/duby/jvm/method_lookup.rb', line 121 def phase3(mapped_params, potentials) nil end |
#primitive_convertible?(in_type, target_type) ⇒ Boolean
176 177 178 179 180 181 182 |
# File 'lib/duby/jvm/method_lookup.rb', line 176 def primitive_convertible?(in_type, target_type) if PrimitiveConversions.include? in_type PrimitiveConversions[in_type].include?(target_type) else in_type.convertible_to?(target_type) end end |