Class: Mirah::JVM::Types::TypeFactory

Inherits:
Object
  • Object
show all
Defined in:
lib/mirah/jvm/types/factory.rb

Defined Under Namespace

Classes: ParanoidHash

Constant Summary collapse

BASIC_TYPES =
{
  "boolean" => Boolean,
  "byte" => Byte,
  "char" => Char,
  "short" => Short,
  "int" => Int,
  "long" => Long,
  "float" => Float,
  "double" => Double,
  "fixnum" => Int,
  "string" => String,
  "java.lang.String" => String,
  "String" => String,
  "java.lang.Object" => Object,
  "Object" => Object,
  "java.lang.Class" => ClassType,
  "java.lang.Iterable" => Iterable,
  "Iterable" => Iterable,
  "void" => Void,
  "notype" => Void,
  "null" => Null,
  "dynamic" => DynamicType.new
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeTypeFactory

Returns a new instance of TypeFactory.



54
55
56
57
58
59
# File 'lib/mirah/jvm/types/factory.rb', line 54

def initialize
  @known_types = ParanoidHash.new
  @known_types.update(BASIC_TYPES)
  @declarations = []
  @mirrors = {}
end

Instance Attribute Details

#known_typesObject (readonly)

Returns the value of attribute known_types.



45
46
47
# File 'lib/mirah/jvm/types/factory.rb', line 45

def known_types
  @known_types
end

#packageObject

Returns the value of attribute package.



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

def package
  @package
end

Instance Method Details

#basic_type(scope, name) ⇒ Object

Raises:

  • (ArgumentError)


89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/mirah/jvm/types/factory.rb', line 89

def basic_type(scope, name)
  if name.kind_of?(Type) || name.kind_of?(NarrowingType)
    return name.basic_type
  end
  orig = name
  if name.kind_of? Java::JavaClass
    if name.array?
      return type(name.component_type, true)
    else
      name = name.name
    end
  elsif name.respond_to? :java_class
    name = name.java_class.name
  end
  name = name.to_s unless name.kind_of?(::String)
  raise ArgumentError, "Bad Type #{orig}" if name =~ /Java::/
  raise ArgumentError, "Bad Type #{orig.inspect}" if name == '' || name.nil?
  find_type(scope, name)
end

#declare_type(scope, name) ⇒ Object



177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/mirah/jvm/types/factory.rb', line 177

def declare_type(scope, name)
  full_name = name
  package = scope.static_scope.package
  if !name.include?('.') && !package.empty?
    full_name = "#{package}.#{name}"
  end
  if @known_types.include? full_name
    @known_types[full_name]
  else
    scope.static_scope.import(full_name, name)
    @known_types[full_name] = TypeDefinition.new(full_name, nil)
  end
end

#define_type(node) ⇒ Object



191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'lib/mirah/jvm/types/factory.rb', line 191

def define_type(node)
  name = node.name
  full_name = name
  package = node.static_scope.package
  if !name.include?('.') && !package.empty?
    full_name = "#{package}.#{name}"
  end
  if @known_types.include? full_name
    existing = @known_types[full_name]
    existing.node ||= node
    existing
  else
    if Mirah::AST::InterfaceDeclaration === node
      klass = InterfaceDefinition
    else
      klass = TypeDefinition
    end
    node.scope.static_scope.import(full_name, name)
    @known_types[full_name] = klass.new(full_name, node)
  end
end

#define_types(builder) ⇒ Object



69
70
71
72
73
# File 'lib/mirah/jvm/types/factory.rb', line 69

def define_types(builder)
  @declarations.each do |declaration|
    declaration.define(builder)
  end
end

#find_type(scope, name) ⇒ Object



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/mirah/jvm/types/factory.rb', line 109

def find_type(scope, name)
  saved_ex = nil
  begin
    return get_type(name)
  rescue NameError => ex
    saved_ex = ex
  end

  if scope
    imports = scope.static_scope.imports
    if imports.include?(name)
      name = imports[name] while imports.include?(name)
      return get_type(name)
    end

    # TODO support inner class names
    if name !~ /\./
      return package_search(name, scope)
    end
  end
  raise saved_ex
end

#get_mirror(name) ⇒ Object



221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/mirah/jvm/types/factory.rb', line 221

def get_mirror(name)
  @mirrors[name] ||= begin
    classname = name.tr('.', '/')
    stream = JRuby.runtime.jruby_class_loader.getResourceAsStream(classname + ".class")
    if stream
      BiteScript::ASM::ClassMirror.load(stream) if stream
    else
      url = JRuby.runtime.jruby_class_loader.getResource(classname + ".java")
      if url
        file = java.io.File.new(url.toURI)
        mirrors = JavaSourceMirror.load(file, self)
        mirrors.each do |mirror|
          @mirrors[mirror.type.class_name] = mirror
        end if mirrors
        @mirrors[name]
      else
        raise NameError, "Class '#{name}' not found."
      end
    end
  end
end

#get_type(full_name) ⇒ Object



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/mirah/jvm/types/factory.rb', line 146

def get_type(full_name)
  type = @known_types[full_name]
  return type.basic_type if type
  begin
    mirror = get_mirror(full_name)
  rescue NameError => ex
    if full_name =~ /^(.+)\.([^.]+)/
      outer_name = $1
      inner_name = $2
      begin
        outer_type = get_type(outer_name)
        full_name = "#{outer_type.name}$#{inner_name}"
      rescue NameError
        raise ex
      end
      mirror = get_mirror(full_name)
    else
      raise ex
    end
  end
  type = Type.new(mirror).load_extensions
  if full_name.include? '$'
    @known_types[full_name.gsub('$', '.')] = type
  end
  @known_types[full_name] = type
end

#initialize_copy(other) ⇒ Object



61
62
63
64
65
66
67
# File 'lib/mirah/jvm/types/factory.rb', line 61

def initialize_copy(other)
  @known_types = other.known_types.dup
  @known_types.delete_if do |key, value|
    value.basic_type.kind_of?(Mirah::JVM::Types::TypeDefinition)
  end
  @declarations = []
end

#known_type(scope, name) ⇒ Object



173
174
175
# File 'lib/mirah/jvm/types/factory.rb', line 173

def known_type(scope, name)
  basic_type(scope, name) rescue nil
end

#no_typeObject



213
214
215
# File 'lib/mirah/jvm/types/factory.rb', line 213

def no_type
  Void
end

#package_search(name, scope) ⇒ Object

Raises:

  • (NameError)


132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/mirah/jvm/types/factory.rb', line 132

def package_search(name, scope)
  packages = []
  packages << scope.static_scope.package unless scope.static_scope.package.empty?
  packages.concat(scope.static_scope.search_packages)
  packages << 'java.lang'
  packages.each do |package|
    begin
      return get_type("#{package}.#{name}")
    rescue NameError
    end
  end
  raise NameError, "Cannot find class #{name}"
end

#type(scope, name, array = false, meta = false) ⇒ Object



75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/mirah/jvm/types/factory.rb', line 75

def type(scope, name, array=false, meta=false)
  if name.kind_of?(BiteScript::ASM::Type)
    if name.getDescriptor[0] == ?[
      return type(scope, name.getElementType, true, meta)
    else
      name = name.getClassName
    end
  end
  type = basic_type(scope, name)
  type = type.array_type if array
  type = type.meta if meta
  return type
end

#unreachable_typeObject



217
218
219
# File 'lib/mirah/jvm/types/factory.rb', line 217

def unreachable_type
  Unreachable
end