class Emfrp::Typing::UnionType

Constants

NameCounter

Attributes

name_id[RW]
original_typevar_name[RW]
typeargs[R]
typename[R]
union[RW]

Public Class Methods

from_type(type, tbl={}) click to toggle source
# File lib/emfrp/typing/union_type.rb, line 15
def self.from_type(type, tbl={})
  case type
  when Emfrp::Type
    new(type[:name][:desc], type[:args].map{|a| from_type(a, tbl)})
  when TypeVar
    name = type[:name][:desc]
    if tbl[name]
      tbl[name]
    else
      a = new()
      tbl[name] = a
      a.original_typevar_name = name
      a
    end
  when UnionType
    type
  else
    raise "unexpected type #{type.class} (bug)"
  end
end
new(*args) click to toggle source
# File lib/emfrp/typing/union_type.rb, line 36
def initialize(*args)
  if args.length == 2
    @typename = args[0]
    @typeargs = args[1]
  elsif args.length == 0
    @union = [self]
    @name_id = NameCounter.shift
    @original_name_id = @name_id
  else
    raise "Wrong number of arguments (#{args.length} for 0, 2)"
  end
end

Public Instance Methods

clone_utype(tbl={}) click to toggle source
# File lib/emfrp/typing/union_type.rb, line 114
def clone_utype(tbl={})
  if self.var?
    if tbl[self]
      tbl[self]
    else
      alt = self.class.new
      self.union.each{|t| tbl[t] = alt}
      alt
    end
  else
    self.class.new(self.typename, self.typeargs.map{|t| t.clone_utype(tbl)})
  end
end
collect_union(visited={}) click to toggle source
# File lib/emfrp/typing/union_type.rb, line 93
def collect_union(visited={})
  return [] if visited[self]
  visited[self] = true
  res = @union + @union.map{|t| t.collect_union(visited)}.flatten
  return res.uniq
end
has_var?() click to toggle source
# File lib/emfrp/typing/union_type.rb, line 77
def has_var?
  if self.var?
    true
  else
    self.typeargs.any?{|x| x.has_var?}
  end
end
include?(other) click to toggle source
# File lib/emfrp/typing/union_type.rb, line 67
def include?(other)
  if self.match?(other)
    true
  elsif !self.var?
    self.typeargs.any?{|x| x.include?(other)}
  else
    false
  end
end
inspect() click to toggle source
# File lib/emfrp/typing/union_type.rb, line 186
def inspect
  if self.var?
    #"a#{self.name_id}[#{@original_name_id}]" + (@original_typevar_name ? "(#{@original_typevar_name})" : "")
    "a#{self.name_id}" + (@original_typevar_name ? "(#{@original_typevar_name})" : "")
  else
    args = self.typeargs.size > 0 ? "[#{self.typeargs.map{|t| t.inspect}.join(", ")}]" : ""
    "#{self.typename}#{args}"
  end
end
match?(other) click to toggle source
# File lib/emfrp/typing/union_type.rb, line 53
def match?(other)
  if self.var? && other.var?
    self.name_id == other.name_id
  elsif !self.var? && !other.var?
    if self.typename == other.typename && self.typeargs.size == other.typeargs.size
      self.typeargs.zip(other.typeargs).all?{|a, b| a.match?(b)}
    else
      false
    end
  else
    false
  end
end
occur_check(var) click to toggle source
# File lib/emfrp/typing/union_type.rb, line 152
def occur_check(var)
  if !self.var?
    self.typeargs.each{|t| t.occur_check(var)}
  end
  if self == var
    raise UnifyError.new(nil, nil)
  end
end
to_flatten_uniq_str() click to toggle source
# File lib/emfrp/typing/union_type.rb, line 174
def to_flatten_uniq_str
  if self.var?
    raise "error"
  end
  if self.typeargs.size > 0
    args = self.typeargs.map{|t| t.to_flatten_uniq_str}.join("_")
    "#{self.typename}_#{args}"
  else
    "#{self.typename}"
  end
end
to_uniq_str() click to toggle source
# File lib/emfrp/typing/union_type.rb, line 161
def to_uniq_str
  if self.var?
    raise "error"
  end
  if self.typeargs.size > 0
    args = self.typeargs.map{|t| t.to_uniq_str}.join(", ")
    "#{self.typename}[#{args}]"
  else
    "#{self.typename}"
  end
end
transform(other) click to toggle source
# File lib/emfrp/typing/union_type.rb, line 108
def transform(other)
  @typename = other.typename
  @typeargs = other.typeargs
  @union = nil
end
typevars() click to toggle source
# File lib/emfrp/typing/union_type.rb, line 100
def typevars
  if var?
    [self]
  else
    typeargs.map{|t| t.typevars}.flatten
  end
end
unify(other) click to toggle source
# File lib/emfrp/typing/union_type.rb, line 128
def unify(other)
  if !self.var? && !other.var?
    if self.typename == other.typename && self.typeargs.size == other.typeargs.size
      self.typeargs.zip(other.typeargs).each{|t1, t2| t1.unify(t2)}
    else
      raise UnifyError.new(nil, nil)
    end
  elsif !self.var? && other.var?
    other.collect_union.each do |t|
      self.occur_check(t)
      t.transform(self)
    end
  elsif self.var? && !other.var?
    self.collect_union.each do |t|
      other.occur_check(t)
      t.transform(other)
    end
  else
    self.unite(self, other)
  end
rescue UnifyError => err
  raise UnifyError.new(self, other)
end
unite(a, b) click to toggle source
# File lib/emfrp/typing/union_type.rb, line 85
def unite(a, b)
  new_union = (a.collect_union + b.collect_union).uniq
  substitute_id = new_union.map{|t| t.name_id}.min
  new_union.each{|t| t.name_id = substitute_id}
  a.union = new_union
  b.union = new_union
end
var?() click to toggle source
# File lib/emfrp/typing/union_type.rb, line 49
def var?
  @union
end