1 """Various helpers for instantiation.""" 
    4 from copy 
import deepcopy
 
    5 from typing 
import List, Sequence, Union
 
    9 ClassMembers = Union[parser.Constructor, parser.Method, parser.StaticMethod,
 
   10                      parser.GlobalFunction, parser.Operator, parser.Variable,
 
   12 InstantiatedMembers = Union[
'InstantiatedConstructor', 
'InstantiatedMethod',
 
   13                             'InstantiatedStaticMethod',
 
   14                             'InstantiatedGlobalFunction']
 
   18                        str_arg_typename: str):
 
   20     Check if the template given by `str_arg_typename` is a scoped template e.g. T::Value, 
   21     and if so, return what template from `template_typenames` and 
   22     the corresponding index matches the scoped template correctly. 
   24     for idx, template 
in enumerate(template_typenames):
 
   25         if "::" in str_arg_typename 
and \
 
   26             template 
in str_arg_typename.split(
"::"):
 
   33         template_typenames: Sequence[str],
 
   34         instantiations: Sequence[parser.Typename],
 
   35         cpp_typename: parser.Typename,
 
   36         instantiated_class: 
'InstantiatedClass' = 
None) -> parser.Type:
 
   38     Instantiate template typename for `ctype`. 
   41         ctype: The original argument type. 
   42         template_typenames: List of strings representing the templates. 
   43         instantiations: List of the instantiations of the templates in `template_typenames`. 
   44         cpp_typename: Full-namespace cpp class name of this instantiation 
   45             to replace for arguments of type named `This`. 
   46         instiated_class: The instantiated class which, if provided, 
   47             will be used for instantiating `This`. 
   50         If `ctype`'s name is in the `template_typenames`, return the 
   51         corresponding type to replace in `instantiations`. 
   52         If ctype name is `This`, return the new typename `cpp_typename`. 
   53         Otherwise, return the original ctype. 
   56     ctype = deepcopy(ctype)
 
   59     if ctype.typename.instantiations:
 
   60         for idx, instantiation 
in enumerate(ctype.typename.instantiations):
 
   61             if instantiation.name 
in template_typenames:
 
   62                 template_idx = template_typenames.index(instantiation.name)
 
   63                 ctype.typename.instantiations[idx].name =\
 
   64                     instantiations[template_idx]
 
   67     str_arg_typename = 
str(ctype.typename)
 
   79         instantiation = deepcopy(instantiations[scoped_idx])
 
   81         instantiation.name = str_arg_typename.replace(scoped_template,
 
   84             typename=instantiation,
 
   85             is_const=ctype.is_const,
 
   86             is_shared_ptr=ctype.is_shared_ptr,
 
   89             is_basic=ctype.is_basic,
 
   92     elif str_arg_typename 
in template_typenames:
 
   93         idx = template_typenames.index(str_arg_typename)
 
   95             typename=instantiations[idx],
 
   96             is_const=ctype.is_const,
 
   97             is_shared_ptr=ctype.is_shared_ptr,
 
  100             is_basic=ctype.is_basic,
 
  104     elif str_arg_typename == 
'This':
 
  107         if instantiated_class:
 
  108             name = instantiated_class.original.name
 
  109             namespaces_name = instantiated_class.namespaces()
 
  110             namespaces_name.append(name)
 
  111             cpp_typename = parser.Typename(
 
  113                 instantiations=instantiated_class.instantiations)
 
  116             typename=cpp_typename,
 
  117             is_const=ctype.is_const,
 
  118             is_shared_ptr=ctype.is_shared_ptr,
 
  121             is_basic=ctype.is_basic,
 
  125     elif 'This' in str_arg_typename:
 
  127         if 'This' in ctype.typename.namespaces:
 
  130             namespace_idx = ctype.typename.namespaces.index(
'This')
 
  131             ctype.typename.namespaces[namespace_idx] = cpp_typename.name
 
  134             for idx, instantiation 
in enumerate(ctype.typename.instantiations):
 
  135                 if 'This' in instantiation.namespaces:
 
  136                     ctype.typename.instantiations[idx].namespaces = \
 
  137                         cpp_typename.namespaces + [cpp_typename.name]
 
  145         args_list: Sequence[parser.Argument],
 
  146         template_typenames: Sequence[parser.template.Typename],
 
  147         instantiations: Sequence, cpp_typename: parser.Typename):
 
  149     Instantiate template typenames in an argument list. 
  150     Type with name `This` will be replaced by @p `cpp_typename`. 
  152     @param[in] args_list A list of `parser.Argument` to instantiate. 
  153     @param[in] template_typenames List of template typenames to instantiate, 
  154         e.g. ['T', 'U', 'V']. 
  155     @param[in] instantiations List of specific types to instantiate, each 
  156         associated with each template typename. Each type is a parser.Typename, 
  157         including its name and full namespaces. 
  158     @param[in] cpp_typename Full-namespace cpp class name of this instantiation 
  159         to replace for arguments of type named `This`. 
  160     @return A new list of parser.Argument which types are replaced with their 
  163     instantiated_args = []
 
  164     for arg 
in args_list:
 
  166                                     instantiations, cpp_typename)
 
  167         instantiated_args.append(
 
  168             parser.Argument(name=arg.name, ctype=new_type,
 
  169                             default=arg.default))
 
  170     return instantiated_args
 
  174         return_type: parser.ReturnType,
 
  175         template_typenames: Sequence[parser.template.Typename],
 
  176         instantiations: Sequence[parser.Typename],
 
  177         cpp_typename: parser.Typename,
 
  178         instantiated_class: 
'InstantiatedClass' = 
None):
 
  179     """Instantiate the return type.""" 
  184                                  instantiated_class=instantiated_class)
 
  185     if return_type.type2:
 
  190                                      instantiated_class=instantiated_class)
 
  193     return parser.ReturnType(new_type1, new_type2)
 
  197                      instantiations: Sequence[parser.Typename]):
 
  199     Concatenate instantiated types with `original_name` to form a new 
  202     NOTE: To avoid conflicts, we should include the instantiation's 
  203     namespaces, but that is too verbose. 
  205     instantiated_names = []
 
  206     for inst 
in instantiations:
 
  208         name = inst.instantiated_name()
 
  210         instantiated_names.append(name.replace(name[0], name[0].capitalize()))
 
  212     return "{}{}".
format(original_name, 
"".join(instantiated_names))
 
  217     Helper class for instantiation templates. 
  218     Requires that `instantiation_type` defines a class method called 
  219     `construct` to generate the appropriate object type. 
  221     Signature for `construct` should be 
  225                   class_instantiations, 
  226                   method_instantiations, 
  231     def __init__(self, instantiation_type: InstantiatedMembers):
 
  234     def instantiate(self, instantiated_methods: List[InstantiatedMembers],
 
  235                     method: ClassMembers, typenames: Sequence[str],
 
  236                     class_instantiations: Sequence[parser.Typename],
 
  237                     method_instantiations: Sequence[parser.Typename],
 
  238                     parent: 
'InstantiatedClass'):
 
  240         Instantiate both the class and method level templates. 
  242         instantiations = class_instantiations + method_instantiations
 
  245                                                   typenames, instantiations,
 
  246                                                   parent.cpp_typename())
 
  248         instantiated_methods.append(
 
  251                                               class_instantiations,
 
  252                                               method_instantiations,
 
  256         return instantiated_methods
 
  259                                  typenames: Sequence[str],
 
  260                                  parent: 
'InstantiatedClass'):
 
  262         Helper to instantiate methods at both the class and method level. 
  265             methods_list: The list of methods in the class to instantiated. 
  266             typenames: List of class level template parameters, e.g. ['T']. 
  267             parent: The instantiated class to which `methods_list` belongs. 
  269         instantiated_methods = []
 
  271         for method 
in methods_list:
 
  273             method_typenames = deepcopy(typenames)
 
  275             if isinstance(method.template, parser.template.Template):
 
  276                 method_typenames.extend(method.template.typenames)
 
  279                 for instantiations 
in itertools.product(
 
  280                         *method.template.instantiations):
 
  283                         instantiated_methods,
 
  285                         typenames=method_typenames,
 
  286                         class_instantiations=parent.instantiations,
 
  287                         method_instantiations=
list(instantiations),
 
  293                     instantiated_methods,
 
  295                     typenames=method_typenames,
 
  296                     class_instantiations=parent.instantiations,
 
  297                     method_instantiations=[],
 
  300         return instantiated_methods