Пример #1
0
 def to_cpp(self):
     """Generate the C++ code for wrapping."""
     instantiated_names = [
         inst.qualified_name() for inst in self.instantiations
     ]
     name = "{}<{}>".format(self.original.name,
                            ",".join(instantiated_names))
     namespaces_name = self.namespaces()
     namespaces_name.append(name)
     # Leverage Typename to generate the fully qualified C++ name
     return parser.Typename(namespaces_name).to_cpp()
Пример #2
0
 def cpp_typename(self):
     """
     Return a parser.Typename including namespaces and cpp name of this
     class.
     """
     if self.original.template:
         name = "{}<{}>".format(
             self.original.name,
             ", ".join([inst.to_cpp() for inst in self.instantiations]))
     else:
         name = self.original.name
     namespaces_name = self.namespaces()
     namespaces_name.append(name)
     return parser.Typename(namespaces_name)
Пример #3
0
def instantiate_type(ctype, template_typenames, instantiations, cpp_typename, instantiated_class=None):
    """
    Instantiate template typename for @p ctype.
    @return If ctype's name is in the @p template_typenames, return the
        corresponding type to replace in @p instantiations.
        If ctype name is `This`, return the new typename @p `cpp_typename`.
        Otherwise, return the original ctype.
    """
    str_arg_typename = str(ctype.typename)
    if str_arg_typename in template_typenames:
        idx = template_typenames.index(str_arg_typename)
        return parser.Type(
            typename=instantiations[idx],
            is_const=ctype.is_const,
            is_ptr=ctype.is_ptr,
            is_ref=ctype.is_ref,
            is_basis=ctype.is_basis,
        )
    elif str_arg_typename == 'This':
        # import sys
        if instantiated_class:
            name = instantiated_class.original.name
            namespaces_name = instantiated_class.namespaces()
            namespaces_name.append(name)
            # print("INST: {}, {}, CPP: {}, CLS: {}".format(
            #     ctype, instantiations, cpp_typename, instantiated_class.instantiations
            # ), file=sys.stderr)
            cpp_typename = parser.Typename(
                namespaces_name, instantiations=[inst for inst in instantiated_class.instantiations]
            )
        return parser.Type(
            typename=cpp_typename,
            is_const=ctype.is_const,
            is_ptr=ctype.is_ptr,
            is_ref=ctype.is_ref,
            is_basis=ctype.is_basis,
        )
    else:
        return ctype
Пример #4
0
def instantiate_type(ctype: parser.Type,
                     template_typenames: List[str],
                     instantiations: List[parser.Typename],
                     cpp_typename: parser.Typename,
                     instantiated_class=None):
    """
    Instantiate template typename for @p ctype.

    Args:
        instiated_class (InstantiatedClass):

    @return If ctype's name is in the @p template_typenames, return the
        corresponding type to replace in @p instantiations.
        If ctype name is `This`, return the new typename @p `cpp_typename`.
        Otherwise, return the original ctype.
    """
    # make a deep copy so that there is no overwriting of original template params
    ctype = deepcopy(ctype)

    # Check if the return type has template parameters
    if ctype.typename.instantiations:
        for idx, instantiation in enumerate(ctype.typename.instantiations):
            if instantiation.name in template_typenames:
                template_idx = template_typenames.index(instantiation.name)
                ctype.typename.instantiations[
                    idx] = instantiations[  # type: ignore
                        template_idx]

        return ctype

    str_arg_typename = str(ctype.typename)

    if str_arg_typename in template_typenames:
        idx = template_typenames.index(str_arg_typename)
        return parser.Type(
            typename=instantiations[idx],
            is_const=ctype.is_const,
            is_shared_ptr=ctype.is_shared_ptr,
            is_ptr=ctype.is_ptr,
            is_ref=ctype.is_ref,
            is_basic=ctype.is_basic,
        )
    elif str_arg_typename == 'This':
        if instantiated_class:
            name = instantiated_class.original.name
            namespaces_name = instantiated_class.namespaces()
            namespaces_name.append(name)
            # print("INST: {}, {}, CPP: {}, CLS: {}".format(
            #     ctype, instantiations, cpp_typename, instantiated_class.instantiations
            # ), file=sys.stderr)
            cpp_typename = parser.Typename(
                namespaces_name,
                instantiations=instantiated_class.instantiations)

        return parser.Type(
            typename=cpp_typename,
            is_const=ctype.is_const,
            is_shared_ptr=ctype.is_shared_ptr,
            is_ptr=ctype.is_ptr,
            is_ref=ctype.is_ref,
            is_basic=ctype.is_basic,
        )
    else:
        return ctype
Пример #5
0
def instantiate_type(
        ctype: parser.Type,
        template_typenames: Sequence[str],
        instantiations: Sequence[parser.Typename],
        cpp_typename: parser.Typename,
        instantiated_class: 'InstantiatedClass' = None) -> parser.Type:
    """
    Instantiate template typename for `ctype`.

    Args:
        ctype: The original argument type.
        template_typenames: List of strings representing the templates.
        instantiations: List of the instantiations of the templates in `template_typenames`.
        cpp_typename: Full-namespace cpp class name of this instantiation
            to replace for arguments of type named `This`.
        instiated_class: The instantiated class which, if provided,
            will be used for instantiating `This`.

    Returns:
        If `ctype`'s name is in the `template_typenames`, return the
        corresponding type to replace in `instantiations`.
        If ctype name is `This`, return the new typename `cpp_typename`.
        Otherwise, return the original ctype.
    """
    # make a deep copy so that there is no overwriting of original template params
    ctype = deepcopy(ctype)

    # Check if the return type has template parameters as the typename's name
    if ctype.typename.instantiations:
        for idx, instantiation in enumerate(ctype.typename.instantiations):
            if instantiation.name in template_typenames:
                template_idx = template_typenames.index(instantiation.name)
                ctype.typename.instantiations[idx].name =\
                    instantiations[template_idx]


    str_arg_typename = str(ctype.typename)

    # Check if template is a scoped template e.g. T::Value where T is the template
    scoped_template, scoped_idx = is_scoped_template(template_typenames,
                                                     str_arg_typename)

    # Instantiate templates which have enumerated instantiations in the template.
    # E.g. `template<T={double}>`.

    # Instantiate scoped templates, e.g. T::Value.
    if scoped_template:
        # Create a copy of the instantiation so we can modify it.
        instantiation = deepcopy(instantiations[scoped_idx])
        # Replace the part of the template with the instantiation
        instantiation.name = str_arg_typename.replace(scoped_template,
                                                      instantiation.name)
        return parser.Type(
            typename=instantiation,
            is_const=ctype.is_const,
            is_shared_ptr=ctype.is_shared_ptr,
            is_ptr=ctype.is_ptr,
            is_ref=ctype.is_ref,
            is_basic=ctype.is_basic,
        )
    # Check for exact template match.
    elif str_arg_typename in template_typenames:
        idx = template_typenames.index(str_arg_typename)
        return parser.Type(
            typename=instantiations[idx],
            is_const=ctype.is_const,
            is_shared_ptr=ctype.is_shared_ptr,
            is_ptr=ctype.is_ptr,
            is_ref=ctype.is_ref,
            is_basic=ctype.is_basic,
        )

    # If a method has the keyword `This`, we replace it with the (instantiated) class.
    elif str_arg_typename == 'This':
        # Check if the class is template instantiated
        # so we can replace it with the instantiated version.
        if instantiated_class:
            name = instantiated_class.original.name
            namespaces_name = instantiated_class.namespaces()
            namespaces_name.append(name)
            cpp_typename = parser.Typename(
                namespaces_name,
                instantiations=instantiated_class.instantiations)

        return parser.Type(
            typename=cpp_typename,
            is_const=ctype.is_const,
            is_shared_ptr=ctype.is_shared_ptr,
            is_ptr=ctype.is_ptr,
            is_ref=ctype.is_ref,
            is_basic=ctype.is_basic,
        )

    # Case when 'This' is present in the type namespace, e.g `This::Subclass`.
    elif 'This' in str_arg_typename:
        # Check if `This` is in the namespaces
        if 'This' in ctype.typename.namespaces:
            # Simply get the index of `This` in the namespace and
            # replace it with the instantiated name.
            namespace_idx = ctype.typename.namespaces.index('This')
            ctype.typename.namespaces[namespace_idx] = cpp_typename.name
        # Else check if it is in the template namespace, e.g vector<This::Value>
        else:
            for idx, instantiation in enumerate(ctype.typename.instantiations):
                if 'This' in instantiation.namespaces:
                    ctype.typename.instantiations[idx].namespaces = \
                        cpp_typename.namespaces + [cpp_typename.name]
        return ctype

    else:
        return ctype