class IDL::AST::TemplateModule

def define(*args)

def define(*args)
  child = super(*args)
  @template_params << child if child.is_a?(IDL::AST::TemplateParam)
  child
end

def initialize(_name, _enclosure, _params)

def initialize(_name, _enclosure, _params)
  super(_name, _enclosure, {})
  @idltype = IDL::Type::TemplateModule.new(self)
  @template_params = []
end

def instantiate(_module_instance, _concrete_params, _context = {})

def instantiate(_module_instance, _concrete_params, _context = {})
  # process concrete parameters
  @template_params.each_with_index do |_tp, _ix|
    raise RuntimeError,
          "missing template parameter for #{typename} #{scoped_lm_name}: #{_tp.name}" unless _ix < _concrete_params.size
    _cp = _concrete_params[_ix]
    if _cp.is_a?(IDL::Type)
      raise RuntimeError, "anonymous type definitions are not allowed!" if _cp.is_anonymous?
      # parameter should be a matching IDL::Type
      unless _tp.idltype.is_a?(IDL::Type::Any) || _tp.idltype.class === _cp.resolved_type
        raise RuntimeError, "mismatched instantiation parameter \##{_ix} #{_cp.typename} for #{typename} #{scoped_lm_name}: expected #{_tp.idltype.typename} for #{_tp.name}"
      end
      # verify concrete parameter
      case _tp.idltype
        when IDL::Type::Any # 'typename'
          # no further checks
        when IDL::Type::Interface, # 'interface'
             IDL::Type::Eventtype, # 'eventtype'
             IDL::Type::Valuetype, # 'valuetype'
             IDL::Type::Struct, # 'struct'
             IDL::Type::Union, # 'union'
             IDL::Type::Exception, # 'exception'
             IDL::Type::Enum # 'enum'
           # no further checks
        when IDL::Type::Sequence # 'sequence' or 'sequence<...>'
          _tptype = _tp.idltype
          unless _tptype.basetype.is_a?(IDL::Type::Void)  # 'sequence'
            # check basetype
            unless _tptype.basetype.is_a?(IDL::Type::ScopedName) &&
                   _tptype.basetype.is_node?(IDL::AST::TemplateParam) &&
                   _tptype.basetype.node.concrete &&
                   _tptype.basetype.node.concrete.idltype.resolved_type == _cp.resolved_type.basetype.resolved_type
              raise RuntimeError, "invalid sequence type as instantiation parameter for #{typename} #{scoped_lm_name}: expected #{_tp.idltype.typename} for #{_tp.name}"
            end
          end
      end
    elsif _cp.is_a?(IDL::Expression)
      # template param should be 'const <const_type>'
      unless _tp.idltype.is_a?(IDL::Type::Const)
        raise RuntimeError, "unexpected expression as instantiation parameter for #{typename} #{scoped_lm_name}: expected #{_tp.idltype.typename} for #{_tp.name}"
      end
      # match constant type
      _tp.idltype.narrow(_cp.value)
    else
      raise RuntimeError, "invalid instantiation parameter for #{typename} #{scoped_lm_name}: #{_cp.class.name}"
    end
    # if we  get here all is well -> store concrete param
    _tp.set_concrete_param(_cp.is_a?(IDL::Type::ScopedName) ? _cp.node : _cp)
  end
  # instantiate template by copying template module state to module instance
  _module_instance.copy_from(self, _context)
end

def is_template?

def is_template?
  true
end

def walk_members_for_copy(&block)

def walk_members_for_copy(&block)
  @children.each { |c| yield(c) unless c.is_a?(IDL::AST::TemplateParam) }
end