def _unpack_if_variable( expr: ir.Expr, var_names: Set[str], literal_expr_by_unique_name: MutableMapping[str, ir.AtomicTypeLiteral]): if isinstance(expr, ir.VariadicTypeExpansion): return ListExpansion( _unpack_if_variable(expr.expr, var_names, literal_expr_by_unique_name)) if isinstance(expr, ir.AtomicTypeLiteral) and expr.cpp_type in var_names: # We keep track of the expr so that we can re-pack this later. # If there are multiple they must be the same. if expr.cpp_type in literal_expr_by_unique_name: assert expr == literal_expr_by_unique_name[ expr.cpp_type], '%s vs %s. Detailed:\n%s\n-- vs --\n%s' % ( expr_to_cpp_simple(expr), expr_to_cpp_simple( literal_expr_by_unique_name[expr.cpp_type]), ir_to_string(expr), ir_to_string(literal_expr_by_unique_name[expr.cpp_type])) else: literal_expr_by_unique_name[expr.cpp_type] = expr return expr.cpp_type else: return expr
def __post_init__(self) -> None: if self.body: for arg in self.args: assert arg.name assert (not self.body or not self.is_metafunction or any( isinstance(elem, Typedef) and elem.name in ('type', 'error', 'value') for elem in self.body) or any( isinstance(elem, ConstantDef) and elem.name == 'value' for elem in self.body)), ir_to_string(self)
def _compile(module_name: str, object_files: List[str], filename: str, verbose): object_file_content = compile( module_name=module_name, file_name=filename, context_object_files=object_files, include_intermediate_irs_for_debugging=verbose) if verbose: main_module = object_file_content.modules_by_name[module_name] print('TMPPy IR2:') print(ir_to_string(main_module.ir2_module)) print() print('TMPPy IR1:') print(ir_to_string(main_module.ir1_module)) print() print('TMPPy IR0:') print(ir_to_string(main_module.ir0_header)) print() return object_file_content
def convert_to_cpp(python_source, filename='<unknown>', verbose=False): source_ast = ast.parse(python_source, filename=filename) compilation_context = ast2highir.CompilationContext(ast2highir.SymbolTable(), ast2highir.SymbolTable(), filename, python_source.splitlines()) def identifier_generator_fun(): for i in itertools.count(): yield 'TmppyInternal_%s' % i identifier_generator = iter(identifier_generator_fun()) module_high_ir = ast2highir.module_ast_to_ir(source_ast, compilation_context) if verbose: print('TMPPy high IR:') print(utils.ir_to_string(module_high_ir)) print() module_ir = highir2ir.module_to_ir(module_high_ir, identifier_generator) if verbose: print('TMPPy IR:') print(utils.ir_to_string(module_ir)) print() header = ir2lowir.module_to_low_ir(module_ir, identifier_generator) if verbose: print('TMPPy low IR:') print(utils.ir_to_string(header)) print() result = lowir2cpp.header_to_cpp(header, identifier_generator) result = utils.clang_format(result) if verbose: print('Conversion result:') print(result) return result
def convert_to_cpp(python_source, filename='<unknown>', verbose=False): source_ast = ast.parse(python_source, filename=filename) def identifier_generator_fun(): for i in itertools.count(): yield 'TmppyInternal_%s' % i identifier_generator = iter(identifier_generator_fun()) module_ir3 = ast_to_ir3.module_ast_to_ir3(source_ast, filename, python_source.splitlines()) if verbose: print('TMPPy IR3:') print(utils.ir_to_string(module_ir3)) print() module_ir3 = optimize_ir3.optimize_module(module_ir3) if verbose: print('TMPPy IR3 after optimization:') print(utils.ir_to_string(module_ir3)) print() module_ir2 = ir3_to_ir2.module_to_ir2(module_ir3, identifier_generator) if verbose: print('TMPPy IR2:') print(utils.ir_to_string(module_ir2)) print() module_ir1 = ir2_to_ir1.module_to_ir1(module_ir2) if verbose: print('TMPPy IR1:') print(utils.ir_to_string(module_ir1)) print() header_ir0 = ir1_to_ir0.module_to_ir0(module_ir1, identifier_generator) if verbose: print('TMPPy IR0:') print(utils.ir_to_string(header_ir0)) print() header_ir0 = optimize_ir0.optimize_header(header_ir0, identifier_generator) if verbose: print('TMPPy IR0 after optimization:') print(utils.ir_to_string(header_ir0)) print() result = ir0_to_cpp.header_to_cpp(header_ir0, identifier_generator) result = utils.clang_format(result) if verbose: print('Conversion result:') print(result) return result
def __init__(self, args: Sequence[TemplateArgDecl], patterns: 'Optional[Sequence[Expr]]', body: Sequence[TemplateBodyElement], is_metafunction: bool): self.args = tuple(args) self.is_metafunction = is_metafunction if body: for arg in args: assert arg.name self.patterns = tuple(patterns) if patterns is not None else None self.body = tuple(body) assert (not body or not is_metafunction or any( isinstance(elem, Typedef) and elem.name in ('type', 'error', 'value') for elem in body) or any( isinstance(elem, ConstantDef) and elem.name == 'value' for elem in body)), 'body was:\n%s' % '\n'.join( ir_to_string(elem) for elem in body)
def term_to_string(self, term: ir.Expr): return '"' + expr_to_cpp_simple(term) + '"\n' + ir_to_string(term)
def _transform_template_body_elems( self, elems: Tuple[ir.TemplateBodyElement, ...], result_element_names: FrozenSet[str], template_specialization_args: Tuple[ir.TemplateArgDecl, ...], is_metafunction: bool): name_by_expr: Dict[ir.Expr, str] = dict() replacements: Dict[str, str] = dict() type_by_name: Dict[str, ir.ExprType] = dict() # First we process all args, so that we'll remove assignments of the form: # x1 = arg1 for arg in template_specialization_args: name_by_expr[ir.AtomicTypeLiteral.for_local( cpp_type=arg.name, expr_type=arg.expr_type, is_variadic=arg.is_variadic)] = arg.name type_by_name[arg.name] = arg.expr_type result_elems = [] for elem in elems: assert isinstance(self.writer, ToplevelWriter) writer = TemplateBodyWriter(self.writer) transformation = NameReplacementTransformation(replacements) with transformation.set_writer(writer): transformation.transform_template_body_elem(elem) [elem] = writer.elems if isinstance( elem, (ir.ConstantDef, ir.Typedef)) and elem.expr in name_by_expr: replacements[elem.name] = name_by_expr[elem.expr] type_by_name[elem.name] = elem.expr.expr_type else: result_elems.append(elem) if isinstance(elem, (ir.ConstantDef, ir.Typedef)): name_by_expr[elem.expr] = elem.name additional_result_elems = [] # This second pass will rename "result elements" back to the correct names if they were deduped. replacements2 = dict() arg_names = {arg.name for arg in template_specialization_args} for result_elem_name in result_element_names: if result_elem_name in replacements: replacement = replacements[result_elem_name] if replacement in replacements2: # We've already added a replacement in `replacements2`, so we need to emit an extra "assignment" assigning # a result element to another. additional_result_elems.append( _create_var_to_var_assignment( lhs=result_elem_name, rhs=replacements2[replacement], expr_type=type_by_name[replacement])) elif replacement in result_element_names: # We've eliminated the assignment to the result var against another result var, so we need to emit an # extra "assignment" assigning a result element to another. if replacement in type_by_name: expr_type = type_by_name[replacement] elif result_elem_name in type_by_name: expr_type = type_by_name[result_elem_name] else: raise NotImplementedError( 'Unable to determine type. This should never happen.' ) additional_result_elems.append( _create_var_to_var_assignment(lhs=result_elem_name, rhs=replacement, expr_type=expr_type)) elif replacement in arg_names: # We've eliminated the assignment to the result var against the definition of an argument. # So we need to add it back. additional_result_elems.append( _create_var_to_var_assignment( lhs=result_elem_name, rhs=replacement, expr_type=type_by_name[replacement])) else: replacements2[replacement] = result_elem_name result_elems = NameReplacementTransformation( replacements2).transform_template_body_elems(tuple(result_elems)) result_elems = (*result_elems, *additional_result_elems) if is_metafunction and result_elems: assert ( any( isinstance(elem, ir.Typedef) and elem.name in ('type', 'error', 'value') for elem in result_elems) or any( isinstance(elem, ir.ConstantDef) and elem.name == 'value' for elem in result_elems) ), 'type_by_name == %s\nreplacements2 == %s\nbody was:\n%s' % ( type_by_name, replacements2, '\n'.join( ir_to_string(elem) for elem in result_elems)) return tuple(result_elems)