def _create_is_same_expr(self, lhs: ir.Expr, rhs: ir.Expr): return ir.ClassMemberAccess(inner_expr=ir.TemplateInstantiation( template_expr=GlobalLiterals.STD_IS_SAME, args=(lhs, rhs), instantiation_might_trigger_static_asserts=False), expr_type=ir.BoolType(), member_name='value')
def transform_select1st(self, args: Tuple[ir.Expr, ...]): lhs, rhs = args best_var = None # First preference to non-expanded variadic vars, to keep the Select1st* expression variadic if it is now. for var_name in compute_non_expanded_variadic_vars(rhs): [best_var] = (var for var in rhs.free_vars if var.cpp_type == var_name) break # If there are none, then any non-variadic var is also ok. if not best_var: for var in rhs.free_vars: if not var.is_variadic and isinstance( var.expr_type, (ir.BoolType, ir.Int64Type, ir.TypeType)): best_var = var break if best_var: rhs = best_var return ir.ClassMemberAccess(inner_expr=ir.TemplateInstantiation( template_expr=select1st_literal(lhs.expr_type, rhs.expr_type), args=(lhs, rhs), instantiation_might_trigger_static_asserts=False), expr_type=lhs.expr_type, member_name='value')
def transform_get_first_error(self, args: Tuple[ir.Expr, ...]): new_args = [] for arg in args: if isinstance(arg, ir.AtomicTypeLiteral) and arg.cpp_type == 'void': pass elif (isinstance(arg, ir.VariadicTypeExpansion) and isinstance(arg.inner_expr, ir.ClassMemberAccess) and isinstance(arg.inner_expr.inner_expr, ir.TemplateInstantiation) and isinstance(arg.inner_expr.inner_expr.template_expr, ir.AtomicTypeLiteral) and arg.inner_expr. inner_expr.template_expr.cpp_type.startswith('Select1stType') and len(arg.inner_expr.inner_expr.args) == 2 and isinstance( arg.inner_expr.inner_expr.args[0], ir.AtomicTypeLiteral) and arg.inner_expr.inner_expr.args[0].cpp_type == 'void'): # Select1stType*<void, expr>... pass else: new_args.append(arg) return ir.ClassMemberAccess(inner_expr=ir.TemplateInstantiation( template_expr=GlobalLiterals.GET_FIRST_ERROR, args=tuple(new_args), instantiation_might_trigger_static_asserts=False), expr_type=ir.TypeType(), member_name='type')
def transform_class_member_access( self, class_member_access: ir.ClassMemberAccess): if (isinstance(class_member_access.inner_expr, ir.TemplateInstantiation) and isinstance(class_member_access.inner_expr.template_expr, ir.AtomicTypeLiteral) and (class_member_access.inner_expr.template_expr.cpp_type, class_member_access.member_name) in self.split_template_name_by_old_name_and_result_element_name): split_template_name = self.split_template_name_by_old_name_and_result_element_name[ (class_member_access.inner_expr.template_expr.cpp_type, class_member_access.member_name)] class_member_access = ir.ClassMemberAccess( inner_expr=ir.TemplateInstantiation( template_expr=ir.AtomicTypeLiteral.for_nonlocal_template( cpp_type=split_template_name, args=class_member_access.inner_expr.template_expr. expr_type.args, is_metafunction_that_may_return_error= class_member_access.inner_expr.template_expr. is_metafunction_that_may_return_error, may_be_alias=False), args=class_member_access.inner_expr.args, instantiation_might_trigger_static_asserts= class_member_access.inner_expr. instantiation_might_trigger_static_asserts), member_name=class_member_access.member_name, expr_type=class_member_access.expr_type) return super().transform_class_member_access(class_member_access)
def transform_class_member_access( self, class_member_access: ir.ClassMemberAccess) -> ir.Expr: class_type_expr = self.transform_expr(class_member_access.expr) return ir.ClassMemberAccess( class_type_expr=class_type_expr, member_name=class_member_access.member_name, member_type=class_member_access.expr_type)
def _ensure_remains_variadic_if_it_was(original_expr: ir.Expr, transformed_expr: ir.Expr): non_expanded_vars_in_original = compute_non_expanded_variadic_vars( original_expr) if not non_expanded_vars_in_original: # No non-expanded variadic vars in the original expr, nothing to do. return transformed_expr if compute_non_expanded_variadic_vars(transformed_expr): # The transformed expr already contains non-expanded variadic vars, nothing to do. return transformed_expr variadic_var = next(iter(non_expanded_vars_in_original.values())) return ir.ClassMemberAccess(class_type_expr=ir.TemplateInstantiation( template_expr=select1st_literal(transformed_expr.expr_type, variadic_var.expr_type), args=[transformed_expr, variadic_var], instantiation_might_trigger_static_asserts=False), member_type=transformed_expr.expr_type, member_name='value')
def split_template_defn_with_multiple_outputs( template_defn: ir.TemplateDefn, split_template_name_by_old_name_and_result_element_name: MutableMapping[ Tuple[str, str], str], identifier_generator: Iterator[str] ) -> Tuple[Tuple[ir.TemplateDefn, ...], bool]: type_by_result_elem_name = { elem.name: elem.expr.expr_type for specialization in template_defn.all_definitions for elem in specialization.body if isinstance(elem, (ir.ConstantDef, ir.Typedef)) and elem.name in template_defn.result_element_names } actual_result_elem_names = tuple(sorted(type_by_result_elem_name.keys())) if len(type_by_result_elem_name) <= 1 or any( not specialization.is_metafunction for specialization in template_defn.all_definitions): return (template_defn, ), False new_template_defns = [] if template_defn.main_definition: args = template_defn.main_definition.args else: args = template_defn.args arg_decls = tuple( ir.TemplateArgType(expr_type=arg.expr_type, is_variadic=arg.is_variadic) for arg in args) template_defn_by_result_elem_name = { result_elem: ir.TemplateDefn( main_definition=template_defn.main_definition, specializations=template_defn.specializations, name=split_template_name_by_old_name_and_result_element_name. setdefault((template_defn.name, result_elem), next(identifier_generator)), description='Split that generates %s of: %s' % (result_elem, template_defn.description or template_defn.name), result_element_names=frozenset((result_elem, )), args=args) for result_elem in actual_result_elem_names } for new_template_defn in template_defn_by_result_elem_name.values(): new_template_defns.append(new_template_defn) dispatcher_body = [] for result_elem_name in actual_result_elem_names: expr_type = type_by_result_elem_name[result_elem_name] split_template_literal = ir.AtomicTypeLiteral.for_nonlocal_template( cpp_type=template_defn_by_result_elem_name[result_elem_name].name, args=arg_decls, is_metafunction_that_may_return_error=False, may_be_alias=False) inner_expr = ir.ClassMemberAccess(inner_expr=ir.TemplateInstantiation( template_expr=split_template_literal, args=tuple( ir.AtomicTypeLiteral.for_local(cpp_type=arg.name, expr_type=arg.expr_type, is_variadic=arg.is_variadic) for arg in args), instantiation_might_trigger_static_asserts=True), member_name=result_elem_name, expr_type=expr_type) if expr_type.kind in (ir.ExprKind.TYPE, ir.ExprKind.TEMPLATE): dispatcher_body.append( ir.Typedef(name=result_elem_name, expr=inner_expr)) else: dispatcher_body.append( ir.ConstantDef(name=result_elem_name, expr=inner_expr)) new_template_defns.append( ir.TemplateDefn( main_definition=ir.TemplateSpecialization( args=args, patterns=None, body=tuple(dispatcher_body), is_metafunction=True), specializations=(), name=template_defn.name, description=template_defn.description, result_element_names=frozenset(actual_result_elem_names), args=args)) return tuple(new_template_defns), False