def visit_BinOp(self, node: ast.BinOp): """ Transforms a string concat to an f-string """ if is_string_concat(node): self.counter += 1 left, right = node.left, node.right left = self.visit(left) right = self.visit(right) if not check_sns_depth(left) or not check_sns_depth(right): node.left = left node.right = right return node parts = [] for p in [left, right]: if isinstance(p, ast.JoinedStr): parts += p.values else: parts.append(p) segments = [] for p in parts: if isinstance(p, ast.Constant): segments.append(ast_string_node(p.value)) else: segments.append(ast_formatted_value(p)) return ast.JoinedStr(segments) else: return self.generic_visit(node)
def bcmpr(self): if self.current_token.type == '¬': self.eat('¬') b = self.b_or() return Neg(b) if self.current_token.type == LPAREN: self.eat(LPAREN) node = self.b_or() self.eat(RPAREN) return node if self.current_token.type == BOOLEAN: b = Bool(self.current_token) self.eat(BOOLEAN) return b node = self.aexp() if self.current_token.type == '=': self.eat('=') return BinOp(left=node, op=Token('=', '='), right=self.aexp()) if self.current_token.type == '<': self.eat('<') return BinOp(left=node, op=Token('<','<'), right=self.aexp()) if self.current_token.type == '>': self.eat('>') return BinOp(left=node, op=Token('>','>'), right=self.aexp()) if self.current_token.type == '<=': self.eat('<=') return BinOp(left=node, op=Token('<=','<='), right=self.aexp()) if self.current_token.type == '>=': self.eat('>=') return BinOp(left=node, op=Token('>=','>='), right=self.aexp())
def p_expression_binop(self, p): '''expression : expression PLUS expression | expression MINUS expression | expression STAR expression | expression DIVIDE expression''' t = None if p[2] == '+': t = Token('PLUS', '+') elif p[2] == '-': t = Token('MINUS', '-') elif p[2] == '*': t = Token('MUL', '*') elif p[2] == '/': t = Token('DIV', '/') p[0] = BinOp(p[1], p[3], t) check_direct_access(p[1]) check_direct_access(p[3]) if p[1].dtype != p[3].dtype or\ p[1].dtype[1] != 0 or\ p[1].dtype[0] == 'void': print_op_error(p[2], p[1].dtype, p[3].dtype) p[0].dtype = p[1].dtype
def test_ast_pattern_matching(self): binop_ast = BinOp(3, 4, 5) with patterns: BinOp(left=x, op=op, right=y) << binop_ast self.assertEquals(3, x) self.assertEquals(4, op) self.assertEquals(5, y)
def p_assignment_lhs(self, p): '''assignment : lhs EQUALS expression''' t = Token('ASGN', '=') p[0] = BinOp(p[1], p[3], t) check_direct_access(p[1]) check_direct_access(p[3]) if p[1].dtype != p[3].dtype: print_op_error(p[2], p[1].dtype, p[3].dtype) p[0].dtype = p[1].dtype
def AugAssignToAssign(node): store_var = node.target load_var = Name(id=store_var.id, ctx=Load()) return Assign(targets=[store_var], value=BinOp(left=load_var, op=node.op, right=node.value))
def visit_BinOp(self, node: ast.BinOp) -> Union[ast.BinOp, ast.Num]: """Evaluate binary operation and return ast.Num if operands are bound. Args: node: Binary operation to evaluate. Returns: Evaluated value. """ node.left = self.visit(node.left) node.right = self.visit(node.right) if isinstance(node.left, ast.Num) and isinstance(node.right, ast.Num): val = ast.Num(n=self._match_ops(node.op, self._binary_ops, node.left.n, node.right.n)) return ast.copy_location(val, node) return node
def p_logical_expression_binop(self, p): '''logical_expression : expression LT expression | expression LE expression | expression GT expression | expression GE expression | expression EQ expression | expression NE expression | logical_expression BOOL_AND logical_expression | logical_expression BOOL_OR logical_expression''' t = None if p[2] == '<': t = Token('LT', p[2]) elif p[2] == '<=': t = Token('LE', p[2]) elif p[2] == '>': t = Token('GT', p[2]) elif p[2] == '>=': t = Token('GE', p[2]) elif p[2] == '==': t = Token('EQ', p[2]) elif p[2] == '!=': t = Token('NE', p[2]) elif p[2] == '&&': t = Token('AND', p[2]) elif p[2] == '||': t = Token('OR', p[2]) p[0] = BinOp(p[1], p[3], t)
def term(self): term = self.factor() while self.current_token.type in (MUL, DIV): token = self.current_token self.consume(token.type) term = BinOp(term, token.value, self.factor()) return term
def parse_equation(eq_string, vars, substract_lhs=True, to_sympy=False): sds = StandardizeDatesSimple(vars) eq = eq_string.split('|')[0] # ignore complentarity constraints if '==' not in eq: eq = eq.replace('=', '==') expr = ast.parse(eq).body[0].value expr_std = sds.visit(expr) from dolo.compiler.codegen import to_source if isinstance(expr_std, Compare): lhs = expr.left rhs = expr.comparators[0] if substract_lhs: expr_std = BinOp(left=rhs, right=lhs, op=Sub()) else: if to_sympy: return [ast_to_sympy(lhs), ast_to_sympy(rhs)] return [lhs, rhs] if to_sympy: return ast_to_sympy(expr_std) else: return expr_std
def test__set_name_and_type(self) -> None: """ Tests that `_set_name_and_type` parsed AST code into a code str. Not working since I explicitly deleted the typ from ``` quoted defaults. Changed mock to match. """ self.assertTupleEqual( _set_name_and_type( ( "adder", { "default": BinOp( set_value(5), Mult(), set_value(5), ), }, ), infer_type=True, word_wrap=True, ), ("adder", { "default": "```(5 * 5)```" }), ) self.assertTupleEqual( _set_name_and_type( ( "adder", { "default": BinOp( set_value(5), Mult(), set_value(5), ), "doc": ["5", "b"], }, ), infer_type=True, word_wrap=True, ), ("adder", { "default": "```(5 * 5)```", "doc": "5b" }), )
def visit_BinOp(self, node: ast.BinOp): node.left = self.visit(node.left) node.right = self.visit(node.right) if not isinstance(node.left, ast.Num) or not isinstance( node.right, ast.Num): return node result = node try: op_type = type(node.op) result = ast.Num( n=self.binop_dict[op_type](node.left.n, node.right.n)) except: print("Error: undefined type") return ast.copy_location(result, node)
def _trace_print_function(self, existing_node): values = existing_node.args message_format = 'print(' + ', '.join(['%r'] * len(values)) + ') ' return self._create_bare_context_call('add_message', [ BinOp(left=Str(message_format), op=Mod(), right=Tuple(elts=values, ctx=Load())), Num(existing_node.lineno) ])
def visit_Print(self, node): existing_node = self.generic_visit(node) values = existing_node.values message_format = 'print' + ','.join([' %r']*len(values)) + ' ' return self._create_context_call('add_message', [BinOp(left=Str(message_format), op=Mod(), right=Tuple(elts=values, ctx=Load())), Num(existing_node.lineno)])
def cond(self): """ cond = expr > expr | expr < expr | expr = expr """ left = self.expr() op = self.current_token if op.type in (GT, LT, EQL): self.eat(op.type) right = self.expr() return BinOp(left, op, right)
def p_assignment_id(self, p): '''assignment : id EQUALS expression''' # check if expression has only const leaves if not p[3].const_leaves: t = Token('ASGN', '=') p[0] = BinOp(p[1], p[3], t) else: print('Syntax error at %s =\n' % (p[1].token.value)) sys.exit(0)
def zero_Multiplier(node): # 0 -> int(n * 0) return Call(func=Name(id='int', ctx=Load()), args=[ BinOp(left=Num(n=random.random()), right=Num(n=0), op=Mult()) ], keywords=[], starargs=None, kwargs=None)
def split_expr(self, expr_ast): if isinstance(expr_ast, BinOp): tl = self.split_expr(expr_ast.left_child) tr = self.split_expr(expr_ast.right_child) if expr_ast.token.type == 'ASGN': self.temp_body.append(BinOp(tl, tr, expr_ast.token)) return None temp_var = Var('t' + str(self.temp_count + self.temp_start)) self.temp_count += 1 self.temp_body.append( BinOp(temp_var, BinOp(tl, tr, expr_ast.token), Token('ASGN', '='))) return temp_var elif isinstance(expr_ast, UnaryOp): if expr_ast.token.type in ('NOT', 'UMINUS'): t = self.split_expr(expr_ast.child) temp_var = Var('t' + str(self.temp_count + self.temp_start)) self.temp_count += 1 self.temp_body.append( BinOp(temp_var, UnaryOp(t, expr_ast.token), Token('ASGN', '='))) return temp_var else: t = self.split_expr(expr_ast.child) return UnaryOp(t, expr_ast.token) elif isinstance(expr_ast, FunctionCall): t_params = [self.split_expr(x) for x in expr_ast.actual_params] # temp_var = Var('t' + str(self.temp_count + self.temp_start)) # self.temp_count += 1 # self.temp_body.append(BinOp(temp_var, FunctionCall(expr_ast.id, t_params), Token('ASGN', '='))) # return temp_var return FunctionCall(expr_ast.id, t_params) else: return expr_ast
def expr(self): '''expr : term ((ADD|SUB) term)* term : factor ((MUL|DIV) factor)* factor : NUM | LPAREN factor RPAREN ''' expr = self.term() while self.current_token.type in (ADD, SUB): token = self.current_token self.consume(token.type) expr = BinOp(expr, token.value, self.term()) return expr
def infix(self, tree): from ast import BinOp left = tree[0] if isinstance(left, list): left = left[0] right = tree[2] if isinstance(right, list): right = right[0] res = BinOp(left, tree[1], right) return res
def visit_AugAssign(self, node): from ast import BinOp, copy_location from copy import copy load_target = copy(node.target) load_target.ctx = ast.Load() op_node = BinOp(left=load_target, right=node.value, op=node.op) assign = ast.Assign(targets=[node.target], value=copy_location(op_node, node)) return copy_location(assign, node)
def _make_product(terms): """ Return an AST expressing the product of all the terms. """ if terms: product = terms[0] for term in terms[1:]: product = BinOp(left=product, op=Mult(), right=term) return product else: return Constant(value=1)
def visit_BinOp(self, node: ast.BinOp) -> ast.BinOp: node = self.generic_visit(node) if self._is_numeric_mult(node): if isinstance(node.right, ast.Num): if node.right.n == 0: node = ast.copy_location(ast.Num(n = 0), node) elif node.right.n == 1: node = node.left elif node.right.n == 2: node.op = ast.copy_location(ast.Add(), node.op) node.right = copy(node.left) elif isinstance(node.left , ast.Num): if node.left.n == 0: node = ast.copy_location(ast.Num(n = 0), node) elif node.left.n == 1: node = node.right elif node.left.n == 2: node.op = ast.copy_location(ast.Add(), node.op) node.left = copy(node.right) return node
def term(self): """term : factor ((MUL | DIV) factor)*""" node = self.factor() while self.current_token.type in (MUL, DIV): op = self.current_token if op.type == MUL: self.eat(MUL) if op.type == DIV: self.eat(DIV) node = BinOp(node, op, self.factor()) return node
def b_or(self): """ b_or : b_and (∨ b_and)* b_and : bterm (∧ bterm)* bterm : bfactor ((< | =) bfactor)* bfactor : BOOLEAN | LPAREN expr RPAREN """ node = self.b_and() if self.current_token.type == '∨': self.eat('∨') node = BinOp(left=node, op=Token('∨','∨'), right=self.b_and()) return node
def aexp(self): node = self.term() while self.current_token.type in (PLUS, MINUS): token = self.current_token if token.type == PLUS: self.eat(PLUS) elif token.type == MINUS: self.eat(MINUS) node = BinOp(left=node, op=token, right=self.term()) return node
def reorder_operations(self, outer_bin_op: ast.BinOp, inner_bin_op: ast.BinOp) -> Tuple[Any, Any]: inner_first_value = self.literal_eval(inner_bin_op.left) inner_second_value = self.literal_eval(inner_bin_op.right) if (not (isinstance(outer_bin_op.op, BinaryOperation) and outer_bin_op.op.is_symmetric) or not (isinstance(outer_bin_op.op, BinaryOperation) and outer_bin_op.op.is_symmetric)): return inner_first_value, inner_second_value is_left_operand: bool = inner_bin_op is outer_bin_op.left other_value = self.literal_eval( outer_bin_op.right if is_left_operand else outer_bin_op.left) if inner_first_value is not Undefined or inner_second_value is not Undefined: if inner_first_value is Undefined: if other_value is Undefined: if is_left_operand: # (x + 1) + y -> (x + y) + 1 inner_bin_op.right, outer_bin_op.right = outer_bin_op.right, inner_bin_op.right else: # y + (x + 1) -> 1 + (x + y) inner_bin_op.right, outer_bin_op.left = outer_bin_op.left, inner_bin_op.right else: if is_left_operand: # (x + 2) + 1 -> (1 + 2) + x inner_bin_op.left, outer_bin_op.right = outer_bin_op.right, inner_bin_op.left else: # 1 + (x + 2) -> x + (1 + 2) inner_bin_op.left, outer_bin_op.left = outer_bin_op.left, inner_bin_op.left else: if other_value is Undefined: if is_left_operand: # (1 + x) + y -> (y + x) + 1 inner_bin_op.left, outer_bin_op.right = outer_bin_op.right, inner_bin_op.left else: # y + (1 + x) -> 1 + (y + x) inner_bin_op.left, outer_bin_op.left = outer_bin_op.left, inner_bin_op.left else: if is_left_operand: # (2 + x) + 1 -> (2 + 1) + x inner_bin_op.right, outer_bin_op.right = outer_bin_op.right, inner_bin_op.right else: # 1 + (2 + x) -> x + (2 + 1) inner_bin_op.right, outer_bin_op.left = outer_bin_op.left, inner_bin_op.right super().generic_visit(outer_bin_op) return self.literal_eval(outer_bin_op), self.literal_eval(outer_bin_op)
def visit_BinOp( self, ast_node_BinOp: ast.BinOp) -> Union[ast.BinOp, ast.Constant]: """ Evaluate binary operation and return ast.BinOp or ast.Constant if operands are bound. :param ast_node_BinOp: the AST node on which the binary operation is performed. :return: evaluated value. """ ast_node_BinOp.left = self.visit(ast_node_BinOp.left) ast_node_BinOp.right = self.visit(ast_node_BinOp.right) left, right = ast_node_BinOp.left, ast_node_BinOp.right if isinstance(left, ast.Constant) and isinstance(right, ast.Constant): new_ast_node_BinOp = ast.Constant(value=self._match_operator( ast_node_BinOp.op, self._ast_math_BinaryOperators, left.value, right.value)) return ast.copy_location(new_ast_node_BinOp, ast_node_BinOp) return ast_node_BinOp
def term(self): node = self.factor() while self.current_token.type in (TokenTypes.MULTIPLY, TokenTypes.DIVIDE): token = self.current_token if token.type == TokenTypes.MULTIPLY: self.eat(TokenTypes.MULTIPLY) elif token.type == TokenTypes.DIVIDE: self.eat(TokenTypes.DIVIDE) node = BinOp(left=node, op=token, right=self.factor()) return node
def expr(self): node = self.term() while self.current_token.type in (TokenTypes.PLUS, TokenTypes.MINUS): token = self.current_token if token.type == TokenTypes.PLUS: self.eat(TokenTypes.PLUS) elif token.type == TokenTypes.MINUS: self.eat(TokenTypes.MINUS) node = BinOp(left=node, op=token, right=self.term()) return node
def _simpleparser(tokens): if len(tokens) == 0: return None while tokens[0] == '(' and tokens[len(tokens) - 1] == ')': if not validparens(tokens[1:-1]): break tokens = tokens[1:-1] if len(tokens) == 1: return token2obj(tokens[0]) i = indexOfLowestOrderOp(tokens) return BinOp(op=token2obj(tokens[i]), left=_simpleparser(tokens[0:i]), right=_simpleparser(tokens[i + 1:]))