Esempio n. 1
0
def test_lambda_replace_simple_expression():
    a1 = ast.parse("lambda x: x")

    nexpr = ast.parse("lambda y: y + 1")
    expr = lambda_unwrap(nexpr).body

    a2 = lambda_body_replace(lambda_unwrap(a1), expr)
    a2_txt = ast.dump(a2)
    assert "op=Add(), right=Num(n=1))" in a2_txt
Esempio n. 2
0
def test_lambda_replace_simple_expression():
    a1 = ast.parse("lambda x: x")

    nexpr = ast.parse("lambda y: y + 1")
    expr = lambda_unwrap(nexpr).body

    a2 = lambda_body_replace(lambda_unwrap(a1), expr)
    a2_txt = ast.dump(a2)
    if sys.version_info < (3, 8):
        assert "op=Add(), right=Num(n=1))" in a2_txt
    elif sys.version_info < (3, 9):
        assert "op=Add(), right=Constant(value=1, kind=None))" in a2_txt
    else:
        assert "op=Add(), right=Constant(value=1))" in a2_txt
Esempio n. 3
0
def convolute(ast_g: ast.Lambda, ast_f: ast.Lambda):
    "Return an AST that represents g(f(args))"
    # Combine the lambdas into a single call by calling g with f as an argument
    l_g = make_args_unique(lambda_unwrap(ast_g))
    l_f = make_args_unique(lambda_unwrap(ast_f))

    x = arg_name()
    f_arg = ast.Name(x, ast.Load())
    call_g = ast.Call(l_g, [ast.Call(l_f, [f_arg], [])], [])

    call_g_lambda = lambda_build(x, call_g)

    # Build a new call to nest the functions
    return call_g_lambda
Esempio n. 4
0
    def call_Where(self, node: ast.AST, args: List[ast.AST]):
        'Apply a filtering to the current loop.'

        assert len(args) == 2
        source = args[0]
        filter = args[1]
        assert isinstance(filter, ast.Lambda)

        # Make sure we are in a loop
        seq = self.as_sequence(source)

        # Simulate the filtering call - we want the resulting value to test.
        filter = lambda_unwrap(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 Exception("Error: A Where clause must evaluate to a value, not 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._gc.current_scope())  # type: ignore

        self._result = node.rep  # type: ignore
Esempio n. 5
0
    def call_SelectMany(self, node: ast.AST, args: List[ast.AST]):
        r'''
        Apply the selection function to the base to generate a collection, and then
        loop over that collection.
        '''
        assert len(args) == 2
        source = args[0]
        selection = args[1]
        assert isinstance(selection, ast.Lambda)

        # Make sure the source is around. We have to do this because code generation in this
        # framework is lazy. And if the `selection` function does not use the source, and
        # looking at that source might generate a loop, that loop won't be generated! Ops!
        _ = self.as_sequence(source)

        # We need to "call" the source with the function. So build up a new
        # call, and then visit it.

        c = ast.Call(func=lambda_unwrap(selection), args=[source])

        # Get the collection, and then generate the loop over it.
        # It could be that this comes back from something that is already iterating (like a Select statement),
        # in which case we are already looping.
        seq = self.as_sequence(c)

        node.rep = seq  # type: ignore
        self._result = seq
        return seq
def convolute(ast_g: ast.Lambda, ast_f: ast.Lambda):
    'Return an AST that represents g(f(args))'
    # TODO: fix up the ast.Calls to use lambda_call if possible

    # Combine the lambdas into a single call by calling g with f as an argument
    l_g = copy.deepcopy(lambda_unwrap(ast_g))
    l_f = copy.deepcopy(lambda_unwrap(ast_f))

    x = arg_name()
    f_arg = ast.Name(x, ast.Load())
    call_g = ast.Call(l_g, [ast.Call(l_f, [f_arg], [])], [])

    # TODO: Rewrite with lambda_build
    args = ast.arguments(args=[ast.arg(arg=x)])
    call_g_lambda = ast.Lambda(args=args, body=call_g)

    # Build a new call to nest the functions
    return call_g_lambda
Esempio n. 7
0
def convolute(ast_g, ast_f):
    'Return an AST that represents g(f(args))'
    # TODO: fix up the ast.Calls to use lambda_call if possible

    # Sanity checks. For example, g can have only one input argument (e.g. f's result)
    if (not lambda_test(ast_g)) or (not lambda_test(ast_f)):
        raise BaseException("Only lambdas in Selects!")

    # Combine the lambdas into a single call by calling g with f as an argument
    l_g = copy.deepcopy(lambda_unwrap(ast_g))
    l_f = copy.deepcopy(lambda_unwrap(ast_f))

    x = arg_name()
    f_arg = ast.Name(x, ast.Load())
    call_g = ast.Call(l_g, [ast.Call(l_f, [f_arg], [])], [])

    # TODO: Rewrite with lambda_build
    args = ast.arguments(args=[ast.arg(arg=x)])
    call_g_lambda = ast.Lambda(args=args, body=call_g)

    # Build a new call to nest the functions
    return call_g_lambda
    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
Esempio n. 9
0
    def call_Select(self, node: ast.Call, args: List[ast.arg]):
        'Transform the iterable from one form to another'

        assert len(args) == 2
        source = args[0]
        selection = cast(ast.Lambda, args[1])

        # Make sure we are in a loop
        seq = self.as_sequence(source)

        # Simulate this as a "call"
        selection = lambda_unwrap(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(), self._gc.current_scope())

        node.rep = rep  # type: ignore
        self._result = rep
        return 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
Esempio n. 11
0
def test_parse_as_ast_lambda():
    ln = lambda_unwrap(ast.parse("lambda x: x + 1"))
    r = parse_as_ast(ln)
    assert isinstance(r, ast.Lambda)