Beispiel #1
0
def test_variable_type_update():
    tc = gc_scope_top_level()
    expr = "a"
    ctype = ctyp.terminal('int', False)

    v = crep.cpp_variable(expr, tc, ctype)
    v.update_type(ctyp.terminal('float', False))

    assert v.cpp_type().type == 'float'
Beispiel #2
0
def test_deref_simple_ptr():
    tc = gc_scope_top_level()
    expr = "a"
    c_type = ctyp.terminal('int', 1)

    v = crep.cpp_variable(expr, tc, c_type)

    d = crep.dereference_var(v)

    assert d.cpp_type().type == 'int'
    assert d.cpp_type().p_depth == 0
    assert d.as_cpp() == '*a'
Beispiel #3
0
def test_variable_type__with_initial_update():
    tc = gc_scope_top_level()
    expr = "a"
    c_type = ctyp.terminal('int', False)
    c_init = crep.cpp_value('0.0', tc, ctyp.terminal('int', False))

    v = crep.cpp_variable(expr, tc, c_type, c_init)
    v.update_type(ctyp.terminal('float', False))

    assert v.cpp_type().type == 'float'
    iv = v.initial_value()
    assert iv is not None
    assert iv.cpp_type().type == 'float'
Beispiel #4
0
async def exe_from_qastle(q: str):
    'Dummy executor that will return the ast properly rendered. If qastle_roundtrip is true, then we will round trip the ast via qastle first.'
    # Round trip qastle if requested.
    import qastle
    a = qastle.text_ast_to_python_ast(q).body[0].value

    # Setup the rep for this filter
    from func_adl import find_EventDataset
    file = find_EventDataset(a)
    iterator = cpp_variable("bogus-do-not-use", top_level_scope(), cpp_type=None)
    set_rep(file, cpp_sequence(iterator, iterator, top_level_scope()))

    # Use the dummy executor to process this, and return it.
    exe = atlas_xaod_dummy_executor()
    exe.evaluate(a)
    return exe
Beispiel #5
0
    def get_collection(self, md: EventCollectionSpecification,
                       call_node: ast.Call):
        r'''
        Return a cpp ast for accessing the jet collection with the given arguments.
        '''
        # Get the name jet collection to look at.
        if len(call_node.args) != 1:
            raise ValueError(
                f"Calling {md.name} - only one argument is allowed")
        if not isinstance(call_node.args[0], ast.Str):
            raise ValueError(
                f"Calling {md.name} - only acceptable argument is a string")

        # Fill in the CPP block next.
        r = cpp_ast.CPPCodeValue()
        r.args = [
            'collection_name',
        ]
        r.include_files += md.include_files
        r.link_libraries += md.libraries

        r.running_code += self.get_running_code(md.container_type)
        r.result = 'result'

        if issubclass(type(md.container_type),
                      event_collection_collection_container):
            r.result_rep = lambda scope: crep.cpp_collection(
                unique_name(md.name.lower()),
                scope=scope,
                collection_type=md.container_type)  # type: ignore
        else:
            r.result_rep = lambda scope: crep.cpp_variable(
                unique_name(md.name.lower()),
                scope=scope,
                cpp_type=md.container_type)

        # Replace it as the function that is going to get called.
        call_node.func = r  # type: ignore

        return call_node
Beispiel #6
0
    async def execute_result_async(self, a: ast.AST, title: str) -> Any:
        'Dummy executor that will return the ast properly rendered. If qastle_roundtrip is true, then we will round trip the ast via qastle first.'
        # Round trip qastle if requested.
        if self._q_roundtrip:
            import qastle
            print(f'before: {ast.dump(a)}')
            a_text = qastle.python_ast_to_text_ast(a)
            a = qastle.text_ast_to_python_ast(a_text).body[0].value
            print(f'after: {ast.dump(a)}')

        # Setup the rep for this dataset
        from func_adl import find_EventDataset
        file = find_EventDataset(a)
        iterator = cpp_variable("bogus-do-not-use",
                                top_level_scope(),
                                cpp_type=None)
        set_rep(file, cpp_sequence(iterator, iterator, top_level_scope()))

        # Use the dummy executor to process this, and return it.
        exe = self.get_dummy_executor_obj()
        exe.evaluate(a)
        return exe
Beispiel #7
0
def isNonnullAst(call_node):
    r'''
    User is trying to test, on certian objects, if the object, when dereferenced, will be a null
    pointer. This is tricky for our data model because it treats an object as both a pointer and
    a object. Most of `func_adl_xAOD` is setup to deal with it as a pointer. This allows us to
    get around ths.
    '''

    if len(call_node.args) != 1:
        raise ValueError("Calling isNonnull(object) has incorrect number of arguments")

    # Create an AST to hold onto all of this.
    r = cpp_ast.CPPCodeValue()

    # We need all four arguments pushed through.
    r.args = ['cms_object']

    # The code is three steps
    r.running_code += ['auto result = (cms_object).isNonnull();']
    r.result = 'result'
    r.result_rep = lambda scope: cpp_variable(unique_name('is_non_null'), scope=scope, cpp_type=ctyp.terminal('bool'))

    call_node.func = r
    return call_node
Beispiel #8
0
    def write_cpp_files(self, ast: ast.AST,
                        output_path: Path) -> ExecutionInfo:
        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 import find_EventDataset
        file = find_EventDataset(ast)
        iterator = crep.cpp_variable("bogus-do-not-use",
                                     top_level_scope(),
                                     cpp_type=None)
        crep.set_rep(file,
                     crep.cpp_sequence(iterator, iterator, top_level_scope()))

        # Visit the AST to generate the code structure and find out what the
        # result is going to be.
        qv = self.get_visitor_obj()
        result_rep = qv.get_rep(ast) if _is_format_request(ast) \
            else qv.get_as_ROOT(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_decl_code = qv.class_declaration_code()
        includes = qv.include_files() + self.body_include_files
        link_libraries = qv.link_libraries() + self.link_libraries

        # The replacement dict to pass to the template generator can now be filled
        info = {}
        info['query_code'] = query_code.lines_of_query_code()
        info['class_decl'] = class_decl_code
        info['book_code'] = book_code.lines_of_query_code()
        info['body_include_files'] = includes
        info['header_include_files'] = self.header_include_files
        info['private_members'] = self.private_members
        info['instance_initialization'] = self.instance_initialization
        info['initialize_lines'] = self.initialize_lines
        info['ctor_lines'] = self.ctor_lines
        info['link_libraries'] = link_libraries
        info.update(self.add_to_replacement_dict())

        # We use jinja2 templates. Write out everything.
        template_dir = _find_dir(self._template_dir_name)
        j2_env = jinja2.Environment(
            loader=jinja2.FileSystemLoader(template_dir))

        for file_name in self._file_names:
            self._copy_template_file(j2_env, info, file_name, output_path)

        (output_path / self._runner_name).chmod(0o755)

        # Reset our object for the next call (e.g. reset global state)
        self.reset()

        # Build the return object.
        return ExecutionInfo(result_rep, output_path, self._runner_name,
                             self._file_names)
Beispiel #9
0
def build_CPPCodeValue(spec: CPPCodeSpecification,
                       call_node: ast.Call) -> ast.Call:
    '''
    Given the specification for a C++ code block, invoked as a function in our AST, replace
    the call node with a cpp spec callback AST so the C++ code is properly inserted into the
    call stream.


    Args:
        spec (CPPCodeSpecification): The specification, including the code, that we should insert at this call node
        call_node (ast.Call): The call node (with arguments) that we are going to replace with this
        C++ code.

    Raises:
        ValueError: Raised if something is wrong with the call site

    Returns:
        [type]: The C++ ast that can easily be emitted as code
    '''

    if len(call_node.args) != len(spec.arguments):
        raise ValueError(
            f"The call of {spec.name}({', '.join(spec.arguments)}) has insufficient arguments ({len(call_node.args)})."
        )

    if isinstance(call_node.func,
                  ast.Attribute) and spec.method_object is None:
        raise ValueError(
            f"The {spec.name} is a function, but it is invoked like a method.")

    if isinstance(call_node.func, ast.Name) and spec.method_object is not None:
        raise ValueError(
            f"The {spec.name} is a method, but it is invoked like a function.")

    # Create an AST to hold onto all of this.
    r = CPPCodeValue()
    # We need TVector2 included here
    r.include_files += spec.include_files

    # We need all four arguments pushed through.
    r.args = spec.arguments

    # The code is three steps
    r.running_code += spec.code
    r.result = spec.result
    if spec.cpp_return_is_collection:
        r.result_rep = lambda scope: cpp_collection(
            unique_name(spec.name),
            scope=scope,
            collection_type=ctyp.collection(ctyp.terminal(spec.cpp_return_type)
                                            ))  # type: ignore
    else:
        r.result_rep = lambda scope: cpp_variable(unique_name(spec.name),
                                                  scope=scope,
                                                  cpp_type=ctyp.terminal(
                                                      spec.cpp_return_type))

    # If this is a mehtod, copy the info over to generate the obj reference.
    if spec.method_object is not None:
        r.replacement_instance_obj = (spec.method_object,
                                      call_node.func.value.id)  # type: ignore

    call_node.func = r  # type: ignore
    return call_node