Class: Mirah::JVM::Typer

Inherits:
Typer::Simple show all
Includes:
Types
Defined in:
lib/mirah/jvm/typer.rb

Constant Summary

Constants included from Types

Mirah::JVM::Types::Boolean, Mirah::JVM::Types::Byte, Mirah::JVM::Types::Char, Mirah::JVM::Types::ClassType, Mirah::JVM::Types::Double, Mirah::JVM::Types::Float, Mirah::JVM::Types::Int, Mirah::JVM::Types::Iterable, Mirah::JVM::Types::Long, Mirah::JVM::Types::Null, Mirah::JVM::Types::Object, Mirah::JVM::Types::Short, Mirah::JVM::Types::String, Mirah::JVM::Types::TYPE_ORDERING, Mirah::JVM::Types::Unreachable, Mirah::JVM::Types::Void, Mirah::JVM::Types::WIDENING_CONVERSIONS

Constants included from Mirah

TransformError, VERSION

Instance Attribute Summary collapse

Attributes inherited from Typer::Simple

#errors, #known_types, #last_chance

Instance Method Summary collapse

Methods inherited from Typer::Simple

#boolean_type, #cycle, #cycling=, #cycling?, #default_type, #defer, #deferred_nodes, #define_type, #error, #field_type, #field_type_hash, #field_types, #get_method_type_hash, #infer, #learn_field_type, #learn_local_type, #learn_static_field_type, #local_type, #local_type_hash, #local_types, #method_type, #method_types, #plugins, #resolve, #self_type, #static_field_type, #static_field_type_hash, #static_field_types, #string_type

Methods inherited from Typer::Base

#log, #to_s

Methods included from Mirah

compile, compiler_options, compiler_options=, dest_path, dest_path=, dest_paths, dest_to_source_path, find_dest, find_source, parse, plugins, print_error, reset, run, source_path, source_path=, source_paths, typer_plugins

Constructor Details

#initialize(transformer) ⇒ Typer

Returns a new instance of Typer.



27
28
29
30
31
32
33
34
35
36
# File 'lib/mirah/jvm/typer.rb', line 27

def initialize(transformer)
  @factory = AST.type_factory
  @transformer = transformer
  unless @factory.kind_of? TypeFactory
    raise "TypeFactory not installed"
  end
  @known_types = @factory.known_types
  @known_types['dynamic'] = DynamicType.new
  @errors = []
end

Instance Attribute Details

#transformerObject (readonly)

Returns the value of attribute transformer.



25
26
27
# File 'lib/mirah/jvm/typer.rb', line 25

def transformer
  @transformer
end

Instance Method Details

#array_typeObject



76
77
78
79
# File 'lib/mirah/jvm/typer.rb', line 76

def array_type
  # TODO: allow other types for pre-1.2 profiles
  type_reference(nil, "java.util.List")
end

#fixnum_type(value) ⇒ Object



94
95
96
# File 'lib/mirah/jvm/typer.rb', line 94

def fixnum_type(value)
  FixnumLiteral.new(value)
end

#float_type(value) ⇒ Object



98
99
100
# File 'lib/mirah/jvm/typer.rb', line 98

def float_type(value)
  FloatLiteral.new(value)
end

#hash_typeObject



81
82
83
84
# File 'lib/mirah/jvm/typer.rb', line 81

def hash_type
  # TODO: allow other types for pre-1.2 profiles
  type_reference(nil, "java.util.Map")
end

#infer_signature(method_def) ⇒ Object



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/mirah/jvm/typer.rb', line 112

def infer_signature(method_def)
  signature = method_def.signature
  sig_args = signature.dup
  return_type = sig_args.delete(:return)
  exceptions = sig_args.delete(:throws)
  args = method_def.arguments.args || []
  static = method_def.kind_of? Mirah::AST::StaticMethodDefinition
  if sig_args.size != args.size
    # If the superclass declares one method with the same name and
    # same number of arguments, assume we're overriding it.
    found = nil
    ambiguous = false
    classes = [self_type.superclass] + self_type.interfaces
    while classes.size > 0
      cls = classes.pop
      if static
        methods = cls.declared_class_methods
      else
        methods = cls.declared_instance_methods
      end
      methods.each do |method|
        if method.name == method_def.name &&
           method.argument_types.size == args.size
          if found && found.argument_types != method.argument_types
            ambiguous = true
          else
            found ||= method
          end
        end
      end
      classes << cls.superclass if cls.superclass
    end
    if found && !ambiguous
      signature[:return] = found.return_type
      signature[:throws] = found.exceptions
      args.zip(found.argument_types) do |arg, type|
        signature[arg.name.intern] = type
      end
    end
  elsif signature[:return].nil? && !static
    arg_types = args.map do |arg|
      signature[arg.name.intern]
    end
    method = self_type.find_method(
        self_type, method_def.name, arg_types, false)
    interfaces = self_type.interfaces.dup
    until method || interfaces.empty?
      interface = interfaces.pop
      method = interface.find_method(
          interface, method_def.name, arg_types, false)
    end
    if method
      signature[:return] = method.return_type
      signature[:throws] = method.exceptions
    end
  end
end

#known_type(scope, name) ⇒ Object



90
91
92
# File 'lib/mirah/jvm/typer.rb', line 90

def known_type(scope, name)
  @factory.known_type(scope, name)
end

#learn_method_type(target_type, name, parameter_types, type, exceptions) ⇒ Object



102
103
104
105
106
107
108
109
110
# File 'lib/mirah/jvm/typer.rb', line 102

def learn_method_type(target_type, name, parameter_types, type, exceptions)
  static = target_type.meta?
  if static
    target_type.unmeta.declare_static_method(name, parameter_types, type, exceptions)
  else
    target_type.declare_method(name, parameter_types, type, exceptions)
  end
  super
end

#nameObject



53
54
55
# File 'lib/mirah/jvm/typer.rb', line 53

def name
  "JVM"
end

#no_typeObject



72
73
74
# File 'lib/mirah/jvm/typer.rb', line 72

def no_type
  Void
end

#null_typeObject



68
69
70
# File 'lib/mirah/jvm/typer.rb', line 68

def null_type
  Null
end

#regexp_typeObject



86
87
88
# File 'lib/mirah/jvm/typer.rb', line 86

def regexp_type
  type_reference(nil, "java.util.regex.Pattern")
end

#set_filename(scope, filename) ⇒ Object



38
39
40
41
42
# File 'lib/mirah/jvm/typer.rb', line 38

def set_filename(scope, filename)
  classname = Mirah::JVM::Compiler::JVMBytecode.classname_from_filename(filename)
  main_class = @factory.declare_type(scope, classname)
  @known_types['self'] = main_class.meta
end

#type_definition(scope, name, superclass, interfaces) ⇒ Object



57
58
59
60
61
62
63
64
65
66
# File 'lib/mirah/jvm/typer.rb', line 57

def type_definition(scope, name, superclass, interfaces)
  imports = scope.static_scope.imports
  name = imports[name] while imports.include?(name)
  package = scope.static_scope.package
  unless name =~ /\./ || package.empty?
    name = "#{package}.#{name}"
  end

  @known_types[name]
end

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



44
45
46
47
48
49
50
51
# File 'lib/mirah/jvm/typer.rb', line 44

def type_reference(scope, name, array=false, meta=false)
  begin
    @factory.type(scope, name, array, meta)
  rescue NameError => ex
    known_types[name] = Mirah::AST.error_type
    raise Mirah::InferenceError.wrap(ex, nil)
  end
end