def write_cpp_files(self, ast: ast.AST, output_path: str) -> xAODExecutionInfo: r""" Given the AST generate the C++ files that need to run. Return them along with the input files. """ # Find the base file dataset and mark it. from func_adl.xAOD.backend.util_LINQ import find_dataset file = find_dataset(ast) iterator = crep.cpp_variable("bogus-do-not-use", top_level_scope(), cpp_type=None) file.rep = crep.cpp_sequence(iterator, iterator) # Visit the AST to generate the code structure and find out what the # result is going to be. qv = query_ast_visitor() result_rep = qv.get_rep(ast) # Emit the C++ code into our dictionaries to be used in template generation below. query_code = cpp_source_emitter() qv.emit_query(query_code) book_code = cpp_source_emitter() qv.emit_book(book_code) class_dec_code = qv.class_declaration_code() includes = qv.include_files() # The replacement dict to pass to the template generator can now be filled info = {} info['query_code'] = query_code.lines_of_query_code() info['book_code'] = book_code.lines_of_query_code() info['class_dec'] = class_dec_code info['include_files'] = includes # We use jinja2 templates. Write out everything. template_dir = find_dir("func_adl/xAOD/backend/R21Code") j2_env = jinja2.Environment( loader=jinja2.FileSystemLoader(template_dir)) self.copy_template_file(j2_env, info, 'ATestRun_eljob.py', output_path) self.copy_template_file(j2_env, info, 'package_CMakeLists.txt', output_path) self.copy_template_file(j2_env, info, 'query.cxx', output_path) self.copy_template_file(j2_env, info, 'query.h', output_path) self.copy_template_file(j2_env, info, 'runner.sh', output_path) os.chmod(os.path.join(str(output_path), 'runner.sh'), 0o755) # Build the return object. return xAODExecutionInfo( file.url, result_rep, output_path, 'runner.sh', [ 'ATestRun_eljob.py', 'package_CMakeLists.txt', 'query.cxx', 'query.h', 'runner.sh' ])
async def exe_for_test(a: ast.AST): 'Dummy executor that will return the ast properly rendered' # Setup the rep for this filter file = find_dataset(a) iterator = cpp_variable("bogus-do-not-use", top_level_scope(), cpp_type=None) file.rep = cpp_sequence(iterator, iterator) # Use the dummy executor to process this, and return it. exe = dummy_executor() rnr = atlas_xaod_executor() exe.evaluate(rnr.apply_ast_transformations(a)) return exe
def make_sequence_from_collection(self, rep): ''' Take a collection and produce a sequence. Eventually this should likely be some sort of plug-in architecture. But for now, we will just assume everything looks like a vector. When it comes time for a new type, this is where it should go. ''' element_type = rep.cpp_type().element_type() iterator_value = crep.cpp_value(unique_name("i_obj"), None, element_type) l_statement = statement.loop(iterator_value, crep.dereference_var(rep)) self._gc.add_statement(l_statement) iterator_value.reset_scope(self._gc.current_scope()) # For a new sequence like this the sequence and iterator value are the same return crep.cpp_sequence(iterator_value, iterator_value)
def visit_Select(self, select_ast): 'Transform the iterable from one form to another' # Make sure we are in a loop seq = self.as_sequence(select_ast.source) # Simulate this as a "call" selection = lambda_unwrap(select_ast.selection) c = ast.Call(func=selection, args=[seq.sequence_value().as_ast()]) new_sequence_value = self.get_rep(c) # We need to build a new sequence. rep = crep.cpp_sequence(new_sequence_value, seq.iterator_value()) select_ast.rep = rep self._result = rep
def visit_Where(self, node): 'Apply a filtering to the current loop.' # Make sure we are in a loop seq = self.as_sequence(node.source) # Simulate the filtering call - we want the resulting value to test. filter = lambda_unwrap(node.filter) c = ast.Call(func=filter, args=[seq.sequence_value().as_ast()]) rep = self.get_rep(c) # Create an if statement self._gc.add_statement(statement.iftest(rep)) # Ok - new sequence. This the same as the old sequence, only the sequence value is updated. # Protect against sequence of sequences (LOVE type checkers, which caught this as a possibility) w_val = seq.sequence_value() if isinstance(w_val, crep.cpp_sequence): raise BaseException( "Internal error: don't know how to look at a sequence") new_sequence_var = w_val.copy_with_new_scope(self._gc.current_scope()) node.rep = crep.cpp_sequence(new_sequence_var, seq.iterator_value()) self._result = node.rep