class IDL::AST::ComponentBase

def add_interfaces(intfs)

def add_interfaces(intfs)
  intfs.each do |tc|
    unless tc.is_a?(IDL::Type::ScopedName) && tc.is_node?(IDL::AST::TemplateParam)
      unless (tc.is_a?(IDL::Type::ScopedName) && tc.is_node?(IDL::AST::Interface))
        raise "invalid inheritance identifier for #{typename} #{scoped_lm_name}: #{tc.typename}"
      end
      rtc = tc.resolved_type
      if not rtc.node.is_defined?
        raise "#{typename} #{scoped_lm_name} cannot support forward declared #{tc.node.typename} #{tc.node.scoped_lm_name}"
      end
      ## TODO : is this legal?
      if rtc.node.is_local?
        raise "#{typename} #{scoped_lm_name} cannot support 'local' #{tc.node.typename} #{tc.node.scoped_lm_name}"
      end
      if rtc.node.is_pseudo?
        raise "#{typename} #{scoped_lm_name} cannot support 'pseudo' #{tc.node.typename} #{tc.node.scoped_lm_name}"
      end
      ## TODO : is this legal?
      #if tc.node.is_abstract?
      #  raise RuntimeError,
      #        "'abstract' #{typename} #{scoped_lm_name} cannot support 'abstract' #{tc.node.typename} #{tc.node.scoped_lm_name}"
      #end
      if self.has_support?(rtc.node)
        raise "#{typename} #{scoped_lm_name} cannot support #{tc.node.typename} #{tc.node.scoped_lm_name} multiple times"
      end
      # check if we indirectly support this base multiple times (which is ok; no further need to check)
      unless @resolved_interfaces.any? { |b| b.has_ancestor?(rtc.node) }
        # this is a new support interface so we need to check for member redefinition/ambiguity
        new_op_att_ = []
        rtc.node.walk_members do |m|
          new_op_att_ << m if m.is_a?(IDL::AST::Operation) || m.is_a?(IDL::AST::Attribute)
        end
        if new_op_att_.any? {|n| n_ = self.search_self(n.name); n_.is_a?(IDL::AST::Operation) || n_.is_a?(IDL::AST::Attribute) }
          raise "#{typename} #{scoped_lm_name} cannot support #{tc.node.typename} #{tc.node.scoped_lm_name} because of duplicated operations/attributes"
        end
        # no need to check for duplicate member names; this support is ok
      end
      @resolved_interfaces << rtc.node
    end
    @interfaces << tc.node
  end
end

def ancestors

def ancestors
  resolved_bases
end

def concrete_interfaces(instantiation_context)

def concrete_interfaces(instantiation_context)
  # collect all bases and resolve any template param types
  @interfaces.collect do |_intf|
    IDL::AST::TemplateParam.concrete_param(instantiation_context, _intf)
  end
end

def has_base?(n)

def has_base?(n)
  @resolved_base && (@resolved_base == n.idltype.resolved_type.node) # || @resolved_base.has_base?(n))
end

def has_support?(intf)

def has_support?(intf)
  @resolved_interfaces.any? { |b| b == intf.idltype.resolved_type.node }
end

def initialize(_name, _enclosure, params)

def initialize(_name, _enclosure, params)
  super(_name, _enclosure)
  @base = nil
  @resolved_base = nil
  @interfaces = []
  @resolved_interfaces = []
  set_base(params[:base]) if params[:base]
  add_interfaces(params[:supports] || [])
end

def instantiate(instantiation_context, _enclosure, _params = {})

def instantiate(instantiation_context, _enclosure, _params = {})
  _params.merge!({
    :base => @base ? IDL::AST::TemplateParam.concrete_param(instantiation_context, @base) : @base,
    :supports => self.concrete_interfaces(instantiation_context)
  })
  # instantiate concrete def and validate
  super(instantiation_context, _enclosure, _params)
end

def marshal_dump

def marshal_dump
  super() << @base << @resolved_base << @interfaces << @resolved_interfaces << @idltype
end

def marshal_load(vars)

def marshal_load(vars)
  @idltype = vars.pop
  @resolved_interfaces = vars.pop
  @interfaces = vars.pop
  @resolved_base = vars.pop
  @base = vars.pop
  super(vars)
end

def redefine(node, params)

def redefine(node, params)
  if node.enclosure == self
    case node
    when IDL::AST::Struct, IDL::AST::Union
      if node.is_defined?
        raise "#{node.typename} \"#{node.name}\" is already defined."
      end
      node.annotations.concat(params[:annotations])
      _new_node = node.class.new(node.name, self, params)
      _new_node.annotations.concat(node.annotations)
      _new_node.prefix = node.prefix
      _new_node.instance_variable_set(:@repo_ver, node.instance_variable_get(:@repo_ver))
      _new_node.instance_variable_set(:@repo_id, node.instance_variable_get(:@repo_id))
      node.switchtype = params[:switchtype] if node.is_a?(IDL::AST::Union)
      @children << _new_node
      # replace forward node registration
      node.enclosure.undo_introduction(node)
      introduce(_new_node)
      return _new_node
    else
      raise "#{node.typename} \"#{node.name}\" is already defined."
    end
  end
  case node
  when IDL::AST::Operation, IDL::AST::Attribute
    raise "#{node.typename} '#{node.scoped_lm_name}' cannot be overridden."
  else
    newnode = node.class.new(node.name, self, params)
    newnode.annotations.concat(params[:annotations])
    introduce(newnode)
    @children << newnode  # add overriding child
    return newnode
  end
end

def resolved_bases

def resolved_bases
  (@resolved_base ? [@resolved_base] : []).concat(@resolved_interfaces)
end

def set_base(parent)

def set_base(parent)
  unless parent.is_a?(IDL::Type::ScopedName) && parent.is_node?(IDL::AST::TemplateParam)
    unless (parent.is_a?(IDL::Type::NodeType) && parent.is_node?(self.class))
      raise "invalid inheritance identifier for #{typename} #{scoped_lm_name}: #{parent.typename}"
    end
    if parent.resolved_type.node.has_base?(self)
      raise "circular inheritance detected for #{typename} #{scoped_lm_name}: #{parent.node.scoped_lm_name} is descendant"
    end
    @resolved_base = parent.resolved_type.node
  end
  @base = parent.node
end

def supports?(intf)

def supports?(intf)
  self.has_support?(intf) || (@resolved_base && @resolved_base.supports?(intf)) || @resolved_interfaces.any? { |base_i| i.has_ancestor?(intf) }
end