class IDL::AST::Union

def default_label

def default_label
  swtype = @switchtype.resolved_type
  return nil if IDL::Type::WChar === swtype # No default label detection for wchar
  lbls = members.collect { |m| m.labels.include?(:default) ? [] : m.labels.collect { |l| l.value } }.flatten
  lbls = lbls.sort unless IDL::Type::Boolean === swtype ## work around bug in Ruby 1.9.2
  def_lbl = swtype.min
  while swtype.in_range?(def_lbl)
    return IDL::Expression::Value.new(@switchtype, def_lbl) unless lbls.include?(def_lbl)
    return nil if def_lbl == swtype.max
    def_lbl = swtype.next(def_lbl)
  end
  nil
end

def defined=(f)

def defined=(f)
  @defined = f
end

def has_default?

def has_default?
  members.any? { |m| m.labels.include?(:default) }
end

def initialize(_name, _enclosure, params)

def initialize(_name, _enclosure, params)
  @defined = false
  @recursive = false
  @forward = params[:forward] ? true : false
  @switchtype = nil
  super(_name, _enclosure)
  @idltype = IDL::Type::Union.new(self)
end

def instantiate(instantiation_context, _enclosure)

def instantiate(instantiation_context, _enclosure)
  _params = {
    forward: @forward
  }
  _u = super(instantiation_context, _enclosure, _params)
  _u.set_switchtype(@switchtype.instantiate(instantiation_context))
  _u.validate_labels
  _u.defined = self.is_defined?
  _u
end

def is_defined?

def is_defined?
  @defined
end

def is_forward?

def is_forward?
  @forward
end

def is_local?(recurstk = [])

def is_local?(recurstk = [])
  # not local if forward decl or recursion detected
  return false if is_forward? || recurstk.include?(self)
  recurstk.push self # track root node to detect recursion
  ret = members.any? { |m| m.is_local?(recurstk) }
  recurstk.pop
  ret
end

def is_recursive?

def is_recursive?
  @recursive
end

def marshal_dump

def marshal_dump
  super() << @defined << @recursive << @forward << @idltype << @switchtype
end

def marshal_load(vars)

def marshal_load(vars)
  @switchtype = vars.pop
  @idltype = vars.pop
  @forward = vars.pop
  @recursive = vars.pop
  @defined = vars.pop
  super(vars)
end

def members

def members
  @children.find_all { |c| c.is_a? IDL::AST::UnionMember }
end

def recursive=(f)

def recursive=(f)
  @recursive = f
end

def set_switchtype(_switchtype)

def set_switchtype(_switchtype)
  @switchtype = _switchtype
end

def types

def types
  @children.reject { |c| c.is_a? IDL::AST::UnionMember }
end

def validate_labels

def validate_labels
  return if self.is_template?
  labelvals = []
  default_ = false
  members.each { |m|
    ## check union case labels for validity
    m.labels.each { |lbl|
      if lbl == :default
        raise "duplicate case label 'default' for #{typename} #{lm_name}" if default_
        default_ = true
      else
        # correct type
        lv = @switchtype.resolved_type.narrow(lbl.value)
        # doubles
        if labelvals.include? lv
          raise "duplicate case label #{lv} for #{typename} #{lm_name}"
        end
        labelvals << lv
      end
    }
  }
  ## check if default allowed if defined
  if default_
    if @switchtype.resolved_type.range_length == labelvals.size
      raise "'default' case label superfluous for #{typename} #{lm_name}"
    end
  end
end

def walk_members

def walk_members
  @children.each { |m| yield(m) unless m.is_a? IDL::AST::UnionMember }
end

def walk_members_for_copy

def walk_members_for_copy
  @children.each { |c| yield(c) }
end