class IDL::AST::TemplateModule

def instantiate(_module_instance, instantiation_context = {})

def instantiate(_module_instance, instantiation_context = {})
  # process concrete parameters
  @template_params.each_with_index do |_tp, _ix|
    raise "missing template parameter for #{typename} #{scoped_lm_name}: #{_tp.name}" unless _ix < _module_instance.template_params.size
    _cp = _module_instance.template_params[_ix]
    if _cp.is_a?(IDL::Type)
      raise "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 "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_matches?(_cp.resolved_type.basetype)
              raise "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 "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 "invalid instantiation parameter for #{typename} #{scoped_lm_name}: #{_cp.class.name}"
    end
    # if we  get here all is well -> store concrete param (either IDL type or expression)
    _tp.set_concrete_param(_cp)
  end
  # instantiate template by copying template module state to module instance
  _module_instance.copy_from(self, instantiation_context)
end