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()
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)
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
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
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