module RubyBreaker::TypeComparer

This module compares two RubyBreaker-defined types for the syntactic equivalence.

Public Class Methods

compare(lhs,rhs) click to toggle source

This equal method determines whether two types are syntactically equivalent. Note that this is NOT a type equivalent check.

# File lib/rubybreaker/type/type_comparer.rb, line 95
def self.compare(lhs,rhs)
  if lhs == rhs
    is_equal = true
  elsif lhs.class != rhs.class 
    is_equal = false
  elsif lhs.instance_of?(NominalType)
    is_equal = (lhs.mod == rhs.mod)
  elsif lhs.instance_of?(SelfType)
    is_equal = rhs.instance_of?(SelfType)
  elsif lhs.instance_of?(DuckType)
    is_equal = duck_compare(lhs,rhs)
  elsif lhs.instance_of?(FusionType)
    is_equal = self.compare(lhs.nom_type, rhs.nom_type)        
    if is_equal # do more testing
      is_equal = duck_compare(lhs,rhs)
    end
  elsif lhs.instance_of?(MethodType)
    is_equal = lhs.meth_name == rhs.meth_name
    if is_equal # then do more testing
      is_equal = self.proc_compare(lhs,rhs)
    end
  elsif lhs.instance_of?(BlockType)
    is_equal = self.proc_compare(lhs,rhs)
  elsif lhs.instance_of?(MethodListType)
    is_equal = self.meth_list_compare(lhs,rhs)
  elsif lhs.instance_of?(OrType)
    is_equal = self.or_compare(lhs,rhs)
  elsif lhs.instance_of?(VarLengthType)
    is_equal = rhs.instance_of?(VarLengthType) && 
               self.compare(lhs.type, rhs.type)
  elsif lhs.instance_of?(OptionalType)
    is_equal = rhs.instance_of?(OptionalType) &&
               self.compare(lhs.type, rhs.type)
  else
    is_equal = lhs.class == rhs.class
  end
  return is_equal
end

Private Class Methods

duck_compare(lhs,rhs) click to toggle source

This method checks if two types are syntactically equivalent. The order of method names do not matter.

# File lib/rubybreaker/type/type_comparer.rb, line 18
def self.duck_compare(lhs,rhs)
  is_equal = false
  if lhs.kind_of?(DuckType) && rhs.kind_of?(DuckType) &&
     lhs.meth_names.size == rhs.meth_names.size
    is_equal = true
    lhs.meth_names.each {|mname| 
      if !rhs.meth_names.include?(mname)
        is_equal = false
        break
      end
    }
  end 
  return is_equal
end
meth_list_compare(lhs, rhs) click to toggle source

This method compares a method list to another method list.

# File lib/rubybreaker/type/type_comparer.rb, line 87
def self.meth_list_compare(lhs, rhs)
  return self.or_compare(lhs, rhs)
end
or_compare(lhs,rhs) click to toggle source

This method compares two OR or MethodListType. The order of inner types do not matter.

XXX: Should the order not matter really?

# File lib/rubybreaker/type/type_comparer.rb, line 72
def self.or_compare(lhs,rhs)
  is_equal = false
  if lhs.class == rhs.class && lhs.types.size == rhs.types.size
    is_equal = true
    lhs.types.each { |t|
      if !self.type_in_types?(t, rhs.types)
        is_equal = false
        break
      end
    }
  end
  return is_equal
end
proc_compare(lhs, rhs) click to toggle source

This method compares two proc types.

# File lib/rubybreaker/type/type_comparer.rb, line 34
def self.proc_compare(lhs, rhs)
  is_equal = false
  if lhs.arg_types.size == rhs.arg_types.size
    is_equal = true
    # check arguments first
    lhs.arg_types.each_with_index do |atype,i|
      if !self.compare(atype,rhs.arg_types[i])
        is_equal = false
        break
      end
    end
    # check block types
    if lhs.blk_type && rhs.blk_type
      is_equal = is_equal && self.proc_compare(lhs.blk_type, rhs.blk_type)
    elsif lhs.blk_type || rhs.blk_type
      is_equal = false
    end
    is_equal = is_equal && self.compare(lhs.ret_type, rhs.ret_type)
  end 
  return is_equal
end
type_in_types?(t, types) click to toggle source

This method determines if the type exists in the given type list.

# File lib/rubybreaker/type/type_comparer.rb, line 57
def self.type_in_types?(t, types)
  exist = false
  types.each do |t2|
    if self.compare(t, t2)
      exist = true
      break
    end
  end
  return exist
end