def transform_typedef(self, typedef: ir0.Typedef, writer: transform_ir0.Writer): writer.write( ir0.Typedef( name=typedef.name, expr=self.transform_expr(typedef.expr, writer, split_nontrivial_exprs=False)))
def create_var_to_var_assignment(lhs: str, rhs: str, type: ir0.ExprType): if type.kind in (ir0.ExprKind.BOOL, ir0.ExprKind.INT64): return ir0.ConstantDef(name=lhs, expr=ir0.AtomicTypeLiteral.for_local( cpp_type=rhs, type=type)) elif type.kind in (ir0.ExprKind.TYPE, ir0.ExprKind.TEMPLATE): return ir0.Typedef(name=lhs, expr=ir0.AtomicTypeLiteral.for_local(cpp_type=rhs, type=type)) else: # TODO: consider handling VARIADIC_TYPE too. raise NotImplementedError('Unexpected kind: %s' % str(type.kind))
def new_constant_or_typedef(self, expr: ir0.Expr) -> ir0.AtomicTypeLiteral: id = self.new_id() if expr.type.kind in (ir0.ExprKind.BOOL, ir0.ExprKind.INT64): self.write(ir0.ConstantDef(name=id, expr=expr)) elif expr.type.kind in (ir0.ExprKind.TYPE, ir0.ExprKind.TEMPLATE): self.write(ir0.Typedef(name=id, expr=expr)) else: # TODO: consider handling VARIADIC_TYPE too. raise NotImplementedError('Unexpected kind: ' + str(expr.type.kind)) return ir0.AtomicTypeLiteral.for_local(cpp_type=id, type=expr.type)
def template_instantiation_to_cpp( instantiation_expr: ir0.TemplateInstantiation, enclosing_function_defn_args: List[ir0.TemplateArgDecl], writer: Writer, omit_typename=False): args = instantiation_expr.args if instantiation_expr.instantiation_might_trigger_static_asserts and enclosing_function_defn_args: bound_variables = { arg_decl.name for arg_decl in enclosing_function_defn_args } assert bound_variables # TODO: We could avoid adding a param dependency in more cases by checking for references to local variables # that depend (directly or indirectly) on a param. if not any(arg.references_any_of(bound_variables) for arg in args): # All template arguments are (or might be) constants, we need to add a reference to a variable bound in this # function to prevent the instantiation from happening early, potentially triggering static asserts. arg_decl = _select_best_arg_decl_for_select1st( enclosing_function_defn_args) arg_index = _select_best_arg_expr_index_for_select1st(args) arg_to_replace = args[arg_index] if arg_decl.type.kind != ir0.ExprKind.TEMPLATE and arg_to_replace.type.kind != ir0.ExprKind.TEMPLATE: # We use lambdas here just to make sure we collect code coverage of each "branch". They are not necessary. # Note that we use the *Type variants for variadic types too. That's ok, since e.g. # Select1stBoolType<b, Args> will be expanded as e.g. Select1stBoolType<b, Args>... so it's exactly what # we want in the variadic case too. select1st_variant = { (ir0.ExprKind.BOOL, ir0.ExprKind.BOOL): lambda: 'Select1stBoolBool', (ir0.ExprKind.BOOL, ir0.ExprKind.INT64): lambda: 'Select1stBoolInt64', (ir0.ExprKind.BOOL, ir0.ExprKind.TYPE): lambda: 'Select1stBoolType', (ir0.ExprKind.BOOL, ir0.ExprKind.VARIADIC_TYPE): lambda: 'Select1stBoolType', (ir0.ExprKind.INT64, ir0.ExprKind.BOOL): lambda: 'Select1stInt64Bool', (ir0.ExprKind.INT64, ir0.ExprKind.INT64): lambda: 'Select1stInt64Int64', (ir0.ExprKind.INT64, ir0.ExprKind.TYPE): lambda: 'Select1stInt64Type', (ir0.ExprKind.INT64, ir0.ExprKind.VARIADIC_TYPE): lambda: 'Select1stInt64TypeType', (ir0.ExprKind.TYPE, ir0.ExprKind.BOOL): lambda: 'Select1stTypeBool', (ir0.ExprKind.TYPE, ir0.ExprKind.INT64): lambda: 'Select1stTypeInt64', (ir0.ExprKind.TYPE, ir0.ExprKind.TYPE): lambda: 'Select1stTypeType', (ir0.ExprKind.TYPE, ir0.ExprKind.VARIADIC_TYPE): lambda: 'Select1stTypeType', }[(arg_to_replace.type.kind, arg_decl.type.kind)]() else: # We need to define a new Select1st variant for the desired function type. select1st_variant = writer.new_id() forwarded_param_id = writer.new_id() template_param_decl1 = _type_to_template_param_declaration( type=arg_to_replace.type) template_param_decl2 = _type_to_template_param_declaration( type=arg_decl.type) select1st_variant_body_writer = TemplateElemWriter( writer.get_toplevel_writer()) if arg_to_replace.type.kind in (ir0.ExprKind.BOOL, ir0.ExprKind.INT64): select1st_variant_body = ir0.ConstantDef( name='value', expr=ir0.AtomicTypeLiteral.for_local( cpp_type=forwarded_param_id, type=arg_to_replace.type)) constant_def_to_cpp(select1st_variant_body, enclosing_function_defn_args, select1st_variant_body_writer) else: replaced_type = arg_to_replace.type if replaced_type.kind == ir0.ExprKind.VARIADIC_TYPE: replaced_type = ir0.TypeType() assert replaced_type.kind in (ir0.ExprKind.TYPE, ir0.ExprKind.TEMPLATE) select1st_variant_body = ir0.Typedef( name='value', expr=ir0.AtomicTypeLiteral.for_local( cpp_type=forwarded_param_id, type=replaced_type)) typedef_to_cpp(select1st_variant_body, enclosing_function_defn_args, select1st_variant_body_writer) select1st_variant_body_str = ''.join( select1st_variant_body_writer.strings) writer.write_template_body_elem(''' // Custom Select1st* template template <{template_param_decl1} {forwarded_param_id}, {template_param_decl2}> struct {select1st_variant} {{ {select1st_variant_body_str} }}; '''.format(**locals())) select1st_type = ir0.TemplateType( argtypes=[arg_to_replace.type, arg_decl.type]) select1st_instantiation = ir0.TemplateInstantiation( template_expr=ir0.AtomicTypeLiteral.for_local( cpp_type=select1st_variant, type=select1st_type), args=[ arg_to_replace, ir0.AtomicTypeLiteral.for_local(cpp_type=arg_decl.name, type=arg_decl.type) ], instantiation_might_trigger_static_asserts=False) new_arg = ir0.ClassMemberAccess( class_type_expr=select1st_instantiation, member_name='value', member_type=arg_to_replace.type) args = args[:arg_index] + (new_arg, ) + args[arg_index + 1:] template_params = ', '.join( expr_to_cpp(arg, enclosing_function_defn_args, writer) for arg in args) if isinstance(instantiation_expr.template_expr, ir0.ClassMemberAccess): cpp_fun = class_member_access_to_cpp( instantiation_expr.template_expr, enclosing_function_defn_args, writer, omit_typename=omit_typename, parent_expr_is_template_instantiation=True) else: cpp_fun = expr_to_cpp(instantiation_expr.template_expr, enclosing_function_defn_args, writer) return '{cpp_fun}<{template_params}>'.format(**locals())
def transform_typedef(self, typedef: ir0.Typedef, writer: transform_ir0.Writer): writer.write( ir0.Typedef(name=self._transform_name(typedef.name), expr=self.transform_expr(typedef.expr, writer)))
def transform_typedef(self, typedef: ir0.Typedef, writer: Writer): writer.write( ir0.Typedef(name=typedef.name, expr=self.transform_expr(typedef.expr, writer)))