Пример #1
0
    def visit_BinOp(self, node):
        if node.op.__class__ in self.operators:
            sympy_class = self.operators[node.op.__class__]
            right = self.visit(node.right)

            if isinstance(node.op, ast.Sub):
                right = ast.UnaryOp(op=ast.USub(), operand=right)
            elif isinstance(node.op, ast.Div):
                right = ast.Call(
                    func=ast.Name(id='Pow', ctx=ast.Load()),
                    args=[right, ast.UnaryOp(op=ast.USub(), operand=ast.Num(1))],
                    keywords=[ast.keyword(arg='evaluate', value=ast.Name(id='False', ctx=ast.Load()))],
                    starargs=None,
                    kwargs=None
                )

            new_node = ast.Call(
                func=ast.Name(id=sympy_class, ctx=ast.Load()),
                args=[self.visit(node.left), right],
                keywords=[ast.keyword(arg='evaluate', value=ast.Name(id='False', ctx=ast.Load()))],
                starargs=None,
                kwargs=None
            )

            if sympy_class in ('Add', 'Mul'):
                # Denest Add or Mul as appropriate
                new_node.args = self.flatten(new_node.args, sympy_class)

            return new_node
        return node
Пример #2
0
 def test_BinOp(self):
     for node, op in self.operators.items():
         self.verify(ast.BinOp(ast.Num(2), node(), ast.Num(3)),
                     '2{}3'.format(op))
     # 1 + 2 * 3 = BinOp(2 + BinOp(2 * 3))
     mult = ast.BinOp(ast.Num(2), ast.Mult(), ast.Num(3))
     expr = ast.BinOp(ast.Num(1), ast.Add(), mult)
     self.verify(expr, '1+2*3')
     # (1 + 2) * 3 = BinOp(BinOp(1 + 2) * 3)
     add = ast.BinOp(ast.Num(1), ast.Add(), ast.Num(2))
     expr = ast.BinOp(add, ast.Mult(), ast.Num(3))
     self.verify(expr, '(1+2)*3')
     # 2 * 3 + 1 = BinOp(BinOp(2 * 3) + 1)
     expr = ast.BinOp(mult, ast.Add(), ast.Num(1))
     self.verify(expr, '2*3+1')
     # 3 * (1 + 2) = BinOp(3 * BinOp(1 + 2))
     expr = ast.BinOp(ast.Num(3), ast.Mult(), add)
     self.verify(expr, '3*(1+2)')
     # 3 - (1 + 2) = BinOp(3 - (BinOp1 + 2))
     expr = ast.BinOp(ast.Num(3), ast.Sub(), add)
     self.verify(expr, '3-(1+2)')
     # Deal with Pow's "special" precedence compared to unary operators.
     self.verify(ast.BinOp(ast.Num(-1), ast.Pow(), ast.Num(2)), '(-1)**2')
     self.verify(
         ast.UnaryOp(ast.USub(), ast.BinOp(ast.Num(1), ast.Pow(),
                                           ast.Num(2))), '-1**2')
     self.verify(
         ast.BinOp(ast.Num(1), ast.Pow(),
                   ast.UnaryOp(ast.USub(), ast.Num(2))), '1**(-2)')
Пример #3
0
    def to_node(n) -> ast.AST:
        if isinstance(n, int):
            return ast.Num(n) if n >= 0 else ast.UnaryOp(
                ast.USub(), ast.Num(abs(n)))
        elif isinstance(n, float):
            return ast.Num(n) if math.copysign(1.0, n) > 0.0 else ast.UnaryOp(
                ast.USub(), ast.Num(abs(n)))
        elif isinstance(n, complex):
            node = ast.parse(str(n), mode='eval')
            return node.body

        raise ValueError(n)
Пример #4
0
    def test_docexample(self):
        # used to fail on ironpython for various reason
        node = ast.UnaryOp(ast.USub(), ast.Num(5, lineno=0, col_offset=0),
                            lineno=0, col_offset=0)

        # the same with zero argument constructors
        node = ast.UnaryOp()
        node.op = ast.USub()
        node.operand = ast.Num()
        node.operand.n = 5
        node.operand.lineno = 0
        node.operand.col_offset = 0
        node.lineno = 0
        node.col_offset = 0
Пример #5
0
 def visitUnary_expression(self, ctx: PlSqlParser.Unary_expressionContext):
     ret = self.visitChildren(ctx)
     value = ret[0]
     sign = ctx.children[0].getText()
     if sign == "-":
         return ast.UnaryOp(op=ast.USub(), operand=value)
     return ret
Пример #6
0
def p_factor(p):
    '''factor : "+" factor
			| "-" factor
			| "~" factor
			| power'''

    if len(p) == 2:
        p[0] = p[1]

    else:
        item = p.get_item(1)
        if p[1] == "+":
            p[0] = ast.UnaryOp(op=ast.UAdd(),
                               operand=p[2],
                               lineno=item.lineno,
                               col_offset=item.lexpos)

        elif p[1] == "-":
            p[0] = ast.UnaryOp(op=ast.USub(),
                               operand=p[2],
                               lineno=item.lineno,
                               col_offset=item.lexpos)

        elif p[1] == "~":
            p[0] = ast.UnaryOp(op=ast.Invert(),
                               operand=p[2],
                               lineno=item.lineno,
                               col_offset=item.lexpos)

    return
Пример #7
0
def compile_subtract(p):
    if len(p) == 2:
        return ast.UnaryOp(ast.USub(), build_ast(p[1]))
    elif len(p) == 3:
        return ast.BinOp(build_ast(p[1]), ast.Sub(), build_ast(p[2]))
    else:
        return ast.BinOp(compile_subtract(p[:-1]), ast.Sub(), build_ast(p[-1]))
Пример #8
0
 def visit_Num(self, node):
     should_parenthesize = isinstance(node.n, int) and node.n >= 0 and \
         isinstance(self.get_parent_node(), ast.Attribute)
     should_parenthesize = should_parenthesize or (isinstance(node.n, complex) and
         node.n.real == 0.0 and (node.n.imag < 0 or node.n.imag == -0.0))
     if not should_parenthesize:
         parent_node = self.get_parent_node()
         should_parenthesize = isinstance(parent_node, ast.UnaryOp) and \
             isinstance(parent_node.op, ast.USub) and \
             hasattr(parent_node, 'lineno')
     with self.parenthesize_if(should_parenthesize):
         if isinstance(node.n, float) and abs(node.n) > sys.float_info.max:
             # otherwise we write inf, which won't be parsed back right
             # I don't know of any way to write nan with a literal
             self.write('1e1000' if node.n > 0 else '-1e1000')
         elif isinstance(node.n, (int, _long, float)) and node.n < 0:
             # needed for precedence to work correctly
             me = self.node_stack.pop()
             if isinstance(node.n, int):
                 val = str(-node.n)
             else:
                 val = repr(type(node.n)(-node.n))  # - of long may be int
             self.visit(ast.UnaryOp(op=ast.USub(), operand=ast.Name(id=val)))
             self.node_stack.append(me)
         else:
             self.write(repr(node.n))
Пример #9
0
    def test_visit_UnaryOp(self, get_logger_mock):
        node = MagicMock()
        node.operand = "operand"
        node.op = ast.Not()

        analyzer = ExpressionAnalyzer()
        self.assertIsNone(analyzer.visit_UnaryOp(node))
        self.assertEqual(analyzer.parts, ["not", " ", "operand"])

        node.op = ast.Invert()
        analyzer = ExpressionAnalyzer()
        self.assertIsNone(analyzer.visit_UnaryOp(node))
        self.assertEqual(analyzer.parts, ["~", "operand"])

        node.op = ast.UAdd()
        analyzer = ExpressionAnalyzer()
        self.assertIsNone(analyzer.visit_UnaryOp(node))
        self.assertEqual(analyzer.parts, ["+", "operand"])

        node.op = ast.USub()
        analyzer = ExpressionAnalyzer()
        self.assertIsNone(analyzer.visit_UnaryOp(node))
        self.assertEqual(analyzer.parts, ["-", "operand"])

        node.op = ast.Import()
        analyzer = ExpressionAnalyzer()
        self.assertIsNone(analyzer.visit_UnaryOp(node))
        self.assertEqual(analyzer.parts, ["...", "operand"])
        get_logger_mock().warning.assert_called_once_with(ANY)
Пример #10
0
 def write_number(self, number):
     should_parenthesize = isinstance(number, int) and number >= 0 and \
         isinstance(self.get_parent_node(), ast.Attribute)
     should_parenthesize = should_parenthesize or (
         isinstance(number, complex) and number.real == 0.0 and
         (number.imag < 0 or number.imag == -0.0))
     # Always parenthesize in Python 2, because there "-(1)" and "-1" produce a different AST.
     if not should_parenthesize and (isinstance(number, complex)
                                     or number < 0 or sys.version_info <
                                     (3, 0)):
         parent_node = self.get_parent_node()
         should_parenthesize = isinstance(parent_node, ast.UnaryOp) and \
             isinstance(parent_node.op, ast.USub) and \
             hasattr(parent_node, 'lineno')
     with self.parenthesize_if(should_parenthesize):
         if isinstance(number, float) and abs(number) > sys.float_info.max:
             # otherwise we write inf, which won't be parsed back right
             # I don't know of any way to write nan with a literal
             self.write('1e1000' if number > 0 else '-1e1000')
         elif isinstance(number, (int, _long, float)) and number < 0:
             # needed for precedence to work correctly
             me = self.node_stack.pop()
             if isinstance(number, int):
                 val = str(-number)
             else:
                 val = repr(type(number)(-number))  # - of long may be int
             self.visit(ast.UnaryOp(op=ast.USub(),
                                    operand=ast.Name(id=val)))
             self.node_stack.append(me)
         else:
             self.write(repr(number))
Пример #11
0
 def factor(self):
     """factor: (PLUS | MINUS) factor
              | INTEGER
              | LPAREN expr RPAREN
              | proccall_statement
              | variable"""
     print("BEGIN factor")
     token = self.current_token
     node = None
     if token.token_type == TokenType.PLUS:
         self.eat(TokenType.PLUS)
         node = ast.UnaryOp(ast.UAdd(), self.factor())
     elif token.token_type == TokenType.MINUS:
         self.eat(TokenType.MINUS)
         node = ast.UnaryOp(ast.USub(), self.factor())
     elif token.token_type == TokenType.INTEGER:
         self.eat(TokenType.INTEGER)
         node = ast.Num(token.value)
     elif token.token_type == TokenType.LPAR:
         self.eat(TokenType.LPAR)
         node = self.expr()
         self.eat(TokenType.RPAR)
     elif token.token_type == TokenType.ID and self.lexer.current_char == "(":
         node = self.proccall_statement()
     else:
         node = self.variable()
     print("END factor")
     return node
Пример #12
0
    def visit_UnaryOp(self, node):
        'Change ~x to - x - 1'

        if isinstance(node.op, ast.Invert):
            return ast.BinOp(ast.UnaryOp(ast.USub(), node.operand),
                             ast.Add(),
                             ast.Num(-1))
        return self.generic_visit(node)
    def visit_Index(self, node: ast.Index) -> ast.AST:
        """Index visit e.g. ``i[0], i[0][1]``."""
        self.generic_visit(node)
        log_header = f"visit_Index: {self.src_file}:"

        # Index Node has a value attribute that can be either Num node or UnaryOp node
        # depending on whether the value is positive or negative.
        n_value = node.value
        idx = None

        index_mutations = {
            "Index_NumZero": ast.Num(n=0),
            "Index_NumPos": ast.Num(n=1),
            "Index_NumNeg": ast.UnaryOp(op=ast.USub(), operand=ast.Num(n=1)),
        }

        node_span = NodeSpan(n_value)
        locidx_kwargs = {
            "ast_class": "Index",
            "lineno": node_span.lineno,
            "col_offset": node_span.col_offset,
            "end_lineno": node_span.end_lineno,
            "end_col_offset": node_span.end_col_offset,
        }

        # index is a non-negative number e.g. i[0], i[1]
        if isinstance(n_value, ast.Num):
            # positive integer case
            if n_value.n != 0:
                idx = LocIndex(op_type="Index_NumPos",
                               **locidx_kwargs)  # type: ignore
                self.locs.add(idx)

            # zero value case
            else:
                idx = LocIndex(op_type="Index_NumZero",
                               **locidx_kwargs)  # type: ignore
                self.locs.add(idx)

        # index is a negative number e.g. i[-1]
        if isinstance(n_value, ast.UnaryOp):
            idx = LocIndex(op_type="Index_NumNeg",
                           **locidx_kwargs)  # type: ignore
            self.locs.add(idx)

        if idx == self.target_idx and self.mutation and not self.readonly:
            LOGGER.debug("%s mutating idx: %s with %s", log_header,
                         self.target_idx, self.mutation)
            mutation = index_mutations[self.mutation]

            # uses AST.fix_missing_locations since the values of ast.Num and  ast.UnaryOp also need
            # lineno and col-offset values. This is a recursive fix.
            return ast.fix_missing_locations(
                ast.copy_location(ast.Index(value=mutation), node))

        LOGGER.debug("%s (%s, %s): no mutations applied.", log_header,
                     n_value.lineno, n_value.col_offset)
        return node
Пример #14
0
def resolve_literal_binop(node, ctxt):
    left = _resolve_literal(node.left, ctxt)
    right = _resolve_literal(node.right, ctxt)
    lliteral = not isinstance(left, ast.AST)
    rliteral = not isinstance(right, ast.AST)
    if lliteral and rliteral:
        try:
            return _collapse_map[type(node.op)](left, right)
        except Exception:
            warnings.warn(
                "Binary op collapse failed. Collapsing skipped, but executing this function will likely fail."
                " Error was:\n{}".format(traceback.format_exc()))
            return node
    else:
        if lliteral or rliteral:
            for operand, other_operand in zip([left, right], [right, left]):
                if isinstance(operand, ast.AST):
                    continue

                # Math deduction (symmetric)
                if (isinstance(node.op, ast.Add) and operand == 0):
                    return other_operand
                if isinstance(node.op, ast.Mult):
                    if operand == 0:
                        return 0
                    if operand == 1:
                        return other_operand
                    if operand == -1:
                        return ast.UnaryOp(ast.USub(), operand=other_operand)
            # Math deduction (asymmetric)
            if (isinstance(node.op, (ast.Div, ast.FloorDiv, ast.Pow, ast.Mod))
                    and left == 0):
                return 0
            if (isinstance(node.op, (ast.Div, ast.Pow)) and right == 1):
                return left
            if (isinstance(node.op, ast.Sub) and left == 0):
                return ast.UnaryOp(op=ast.USub(), operand=right)
            if (isinstance(node.op, ast.Sub) and right == 0):
                return left

        # Get the best resolution of the left and right, as AST nodes
        left = resolve_literal(node.left, ctxt)
        right = resolve_literal(node.right, ctxt)

        return ast.BinOp(left=left, right=right, op=node.op)
Пример #15
0
 def UnaryopInvert(self, node: Type[ast.AST]) -> Type[ast.AST]:
     if type(node.op) == ast.UAdd:
         return ast.UnaryOp(op=ast.USub(), operand=node.operand)
     elif type(node.op) == ast.USub:
         return ast.UnaryOp(op=ast.UAdd(), operand=node.operand)
     elif type(node.op) == ast.Invert:
         return ast.UnaryOp(op=ast.Not(), operand=node)
     else:
         return node.operand
Пример #16
0
 def compile_maths_expression_sub(self, expression):
     if len(expression) > 2:
         return self.compile_maths_expression(expression)
     else:
         arg = expression[1]
         return ast.UnaryOp(op=ast.USub(),
                            operand=self.compile(arg),
                            lineno=arg.start_line,
                            col_offset=arg.start_column)
Пример #17
0
 def test_UnaryOp(self):
     self.verify(ast.UnaryOp(ast.Invert(), ast.Num(42)), '~42')
     self.verify(ast.UnaryOp(ast.Not(), ast.Num(42)), 'not 42')
     self.verify(ast.UnaryOp(ast.UAdd(), ast.Num(42)), '+42')
     self.verify(ast.UnaryOp(ast.USub(), ast.Num(42)), '-42')
     precedence = ast.UnaryOp(
         ast.Not(), ast.BoolOp(ast.Or(),
                               [ast.Num(n=1), ast.Num(2)]))
     self.verify(precedence, 'not (1 or 2)')
Пример #18
0
def p_unary_expr_minus_primary(t):
    #'''unary_expr : MINUS primary %prec UMINUS'''
    '''unary_expr : MINUS primary'''
    usub = ast.USub()
    usub.lineno = t.lineno(1)
    usub.col_offset = -1  # XXX
    t[0] = ast.UnaryOp(usub, t[2])
    t[0].lineno = t.lineno(2)
    t[0].col_offset = -1  # XXX
Пример #19
0
def unary_action(s, loc, tokens):
    op_char, operand = tokens[0], tokens[1]
    if op_char == '+':
        return operand
    elif op_char == '-':
        return ast.UnaryOp(op=ast.USub(), operand=operand)
    elif op_char == '~':
        return ast.UnaryOp(op=ast.Invert(), operand=operand)
    else:  # not
        return ast.UnaryOp(op=ast.Not(), operand=operand)
Пример #20
0
 def create_exponentiation_exponent_node(self, exponent):
     node = self.to_node(exponent.operand)
     if exponent.sign in ['-', 'minus']:
         return ast.UnaryOp(ast.USub(), node)
     elif exponent.sign in ['+', 'plus']:
         return ast.UnaryOp(ast.UAdd(), node)
     elif exponent.sign is None:
         return node
     else:
         raise
Пример #21
0
    def __init__(self, base_node):
        BaseMutator.__init__(self, base_node)
        self.original_unary_op = base_node.op

        if type(base_node.op) in [ast.UAdd, ast.USub]:
            if type(base_node.op) is ast.UAdd:
                self.mutations.append({"op": ast.USub()})

            if type(base_node.op) is ast.USub:
                self.mutations.append({"op": ast.UAdd()})
def test_bad_ast_no_call(tmp_path):
    'Pass a really bogus ast to the executor'
    # Get the ast to play with
    q = query_as_ast()
    a = ast.UnaryOp(op=ast.USub(), operand=q.query_ast)

    exe = atlas_xaod_executor()
    with pytest.raises(ValueError) as e:
        exe.write_cpp_files(exe.apply_ast_transformations(a), tmp_path)

    assert 'func_adl ast' in str(e.value)
Пример #23
0
 def to_node(self):
     value = self.value
     operator = self.operator
     if operator in ('+', 'plus'):
         return ast.UnaryOp(ast.UAdd(), value.to_node())
     elif operator in ('-', 'minus'):
         return ast.UnaryOp(ast.USub(), value.to_node())
     elif operator == '~':
         return ast.UnaryOp(ast.Invert(), value.to_node())
     else:
         return value.to_node()
def make_usub(cursor_trail, tree):
    selected_node = core_logic.get_node_at_cursor(cursor_trail, tree)
    expr = selected_node if isinstance(selected_node,
                                       ast.expr) else make_expression()

    if isinstance(expr, ast.UnaryOp) and isinstance(expr.op, ast.USub):
        # Having - - x doesn't really make sense
        # So let's just remove the minus in this case
        return expr.operand

    return ast.UnaryOp(op=ast.USub(), operand=expr)
Пример #25
0
 def test_withUnaryOp(self):
     'Test with UnaryOp involved'
     tests = [("5 + (-(6 + 2)) + 3",
               ast.BoolOp(ast.Add(),
                          [ast.Num(5),
                           ast.UnaryOp(ast.USub(), ast.BinOp(ast.Num(6),
                                                             ast.Add(),
                                                             ast.Num(2))),
                           ast.Num(3)]))]
     for teststring, ref_ast in tests:
         test_ast = ast.parse(teststring, mode="eval").body
         test_ast = asttools.LevelOperators(ast.Add).visit(test_ast)
         self.assertTrue(asttools.Comparator().visit(test_ast, ref_ast))
Пример #26
0
    def p_complex_number(self, p):
        """
        complex_number : number
                       | MINUS number
                       | number PLUS number
                       | number MINUS number
                       | MINUS number PLUS number
                       | MINUS number MINUS number
        """

        ops = {"+": ast.Add(), "-": ast.Sub()}
        build_complex = False
        loc = self.get_line_cols(p, 1)

        match list(p):
            case [_, x]:
                p[0] = x
            case [_, "-", x]:
                p[0] = ast.UnaryOp(op=ast.USub(), operand=x, **loc)
            case [_, left, ("+" | "-") as op_char, right]:
                build_complex = True
                negate_left_side = False
            case [_, "-", left, ("+" | "-") as op_char, right]:
                build_complex = True
                negate_left_side = True
            case _:
                raise AssertionError()

        if build_complex:
            # TODO raise syntax error instead (see reason in p_literal_expr_number_or_string_literal_list)
            assert isinstance(
                right.value, complex
            ), "right part of complex literal must be imaginary"

            if negate_left_side:
                left = ast.UnaryOp(op=ast.USub(), operand=left, **loc)

            p[0] = ast.BinOp(left=left, op=ops[op_char], right=right, **loc)
Пример #27
0
    def p_expr_unaryop(self, p):
        '''expr : MINUS expr %prec UNARYOP
                | TILDE expr %prec UNARYOP
                | NOT expr %prec UNARYOP
        '''
        op = None
        if p[1] == '-':
            op = ast.USub()
        elif p[1] == '~':
            op = ast.Invert()
        elif p[1] == 'not':
            op = ast.Not()

        p[0] = ast.UnaryOp(op=op, operand=p[2])
Пример #28
0
def branch_dist(test):
    if isinstance(test.ops[0], ast.Eq):
        return 0, ast.Call(func=ast.Name(id='abs'),
                           args=[
                               ast.BinOp(left=test.left,
                                         op=ast.Sub(),
                                         right=test.comparators[0])
                           ],
                           keywords=[],
                           starags=None,
                           kwargs=None)

    elif isinstance(test.ops[0], ast.NotEq):
        return 1, ast.UnaryOp(op=ast.USub(),
                              operand=ast.Call(
                                  func=ast.Name(id='abs'),
                                  args=[
                                      ast.BinOp(left=test.left,
                                                op=ast.Sub(),
                                                right=test.comparators[0])
                                  ],
                                  keywords=[],
                                  starags=None,
                                  kwargs=None))

    elif isinstance(test.ops[0], ast.Lt):
        return 1, ast.BinOp(left=test.left,
                            op=ast.Sub(),
                            right=test.comparators[0])

    elif isinstance(test.ops[0], ast.LtE):
        return 0, ast.BinOp(left=test.left,
                            op=ast.Sub(),
                            right=test.comparators[0])

    elif isinstance(test.ops[0], ast.Gt):
        return 1, ast.BinOp(left=test.comparators[0],
                            op=ast.Sub(),
                            right=test.left)

    elif isinstance(test.ops[0], ast.GtE):
        return 0, ast.BinOp(left=test.comparators[0],
                            op=ast.Sub(),
                            right=test.left)
Пример #29
0
    def create_factor_node(self, factor):
        base_node = self.to_node(factor.base)
        # When no parenthesis, exponentiations are read from right to left
        if len(factor.exponents) != 0:
            last_exponent_index = len(factor.exponents) - 1
            right_node = self.to_node(factor.exponents[last_exponent_index])
            for i in range(last_exponent_index - 1, -1, -1):
                right_node = ast.BinOp(self.to_node(factor.exponents[i]),
                                       ast.Pow(), right_node)
            base_node = ast.BinOp(base_node, ast.Pow(), right_node)

        if factor.sign in ['-', 'minus']:
            return ast.UnaryOp(ast.USub(), base_node)
        elif factor.sign in ['+', 'plus']:
            return ast.UnaryOp(ast.UAdd(), base_node)
        elif factor.sign is None:
            return base_node
        else:
            raise
Пример #30
0
    def generate(self, element: Element, GC: GenerationContext):

        acode = element.code

        if len(acode) == 2:
            arg = acode[1]

            with GC.let(domain=ExDom):
                arg_code = GC.generate(arg)

            return expr_wrap(ast.UnaryOp(op=ast.USub(), operand=arg_code), GC)

        else:
            assert len(acode) == 3

            left_element, right_element = acode[1], acode[2]

            with GC.let(domain=ExDom):
                left_code = GC.generate(left_element)
                right_code = GC.generate(right_element)

            return expr_wrap(ast.BinOp(left_code, ast.Sub(), right_code), GC)