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)
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
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
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
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)')
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 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
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 swap_Op(self, node): if (isinstance(node.op, ast.Add)): #BinOp node.op = ast.Sub() elif (isinstance(node.op, ast.Sub)): #BinOp node.op = ast.Add() elif (isinstance(node.op, ast.Mult)): #BinOp node.op = ast.Div() elif (isinstance(node.op, ast.Div)): #BinOp node.op = ast.Mult() elif (isinstance(node.op, ast.FloorDiv)): #BinOp node.op = ast.Div() # elif(isinstance(node.op, ast.And)): #BoolOp # node.op = ast.Or() # elif(isinstance(node.op, ast.Or)): #BoolOp # node.op = ast.And() # elif(isinstance(node.op, ast.UAdd)): #UnaryOp # node.op = ast.USub() # elif(isinstance(node.op, ast.USub)): #UnaryOp node.op = ast.UAdd()
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
def visit_UnaryOp(self, node): # unaryop = Invert | Not | UAdd | USub print(" in MyTransformer.visit_UnaryOp()") print(" node =", node) print(" op =", node.op) curr_op = node.op unary_negate = node.op if isinstance(curr_op, ast.UAdd): unary_negate = ast.USub() elif isinstance(curr_op, ast.USub): unary_negate = ast.UAdd() elif isinstance(curr_op, ast.Invert): unary_negate = ast.Not() elif isinstance(curr_op, ast.Not): unary_negate = ast.Invert() else: print(" did not find negation for", curr_op) print(" negation =", unary_negate) # create negated node | UnaryOp(unaryop op, expr operand) new_node = node new_node.op = unary_negate ast.copy_location(new_node, node) ast.fix_missing_locations(new_node) return new_node
def test_empty_init(self): # Jython 2.5.0 did not allow empty constructors for many ast node types # but CPython ast nodes do allow this. For the moment, I don't see a # reason to allow construction of the super types (like ast.AST and # ast.stmt) as well as the op types that are implemented as enums in # Jython (like boolop), but I've left them in but commented out for # now. We may need them in the future since CPython allows this, but # it may fall under implementation detail. #ast.AST() ast.Add() ast.And() ast.Assert() ast.Assign() ast.Attribute() ast.AugAssign() ast.AugLoad() ast.AugStore() ast.BinOp() ast.BitAnd() ast.BitOr() ast.BitXor() ast.BoolOp() ast.Break() ast.Call() ast.ClassDef() ast.Compare() ast.Continue() ast.Del() ast.Delete() ast.Dict() ast.Div() ast.Ellipsis() ast.Eq() ast.Exec() ast.Expr() ast.Expression() ast.ExtSlice() ast.FloorDiv() ast.For() ast.FunctionDef() ast.GeneratorExp() ast.Global() ast.Gt() ast.GtE() ast.If() ast.IfExp() ast.Import() ast.ImportFrom() ast.In() ast.Index() ast.Interactive() ast.Invert() ast.Is() ast.IsNot() ast.LShift() ast.Lambda() ast.List() ast.ListComp() ast.Load() ast.Lt() ast.LtE() ast.Mod() ast.Module() ast.Mult() ast.Name() ast.Not() ast.NotEq() ast.NotIn() ast.Num() ast.Or() ast.Param() ast.Pass() ast.Pow() ast.Print() ast.RShift() ast.Raise() ast.Repr() ast.Return() ast.Slice() ast.Store() ast.Str() ast.Sub() ast.Subscript() ast.Suite() ast.TryExcept() ast.TryFinally() ast.Tuple() ast.UAdd() ast.USub() ast.UnaryOp() ast.While() ast.With() ast.Yield() ast.alias() ast.arguments() #ast.boolop() #ast.cmpop() ast.comprehension() #ast.excepthandler() #ast.expr() #ast.expr_context() ast.keyword()
def as_ast(dct): """See https://docs.python.org/2/library/ast.html""" if dct['ast_type'] == "Module": return ast.Module(dct["body"]) elif dct['ast_type'] == "Interactive": return ast.Interactive(dct["body"]) elif dct['ast_type'] == "Expression": return ast.Expression(dct["body"]) elif dct['ast_type'] == "Suite": return ast.Suite(dct["body"]) elif dct['ast_type'] == "FunctionDef": return ast.FunctionDef(dct["name"], dct["args"], dct["body"], dct["decorator_list"]) elif dct['ast_type'] == "ClassDef": return ast.ClassDef(dct["name"], dct["bases"], dct["body"], dct["decorator_list"]) elif dct['ast_type'] == "Return": return ast.Return(dct["value"]) elif dct['ast_type'] == "Delete": return ast.Delete(dct["targets"]) elif dct['ast_type'] == "Assign": return ast.Assign(dct["targets"], dct["value"]) elif dct['ast_type'] == "AugAssign": return ast.AugAssign(dct["target"], dct["op"], dct["value"]) elif dct['ast_type'] == "Print": return ast.Print(dct["dest"], dct["values"], dct["nl"]) elif dct['ast_type'] == "For": return ast.For(dct["target"], dct["iter"], dct["body"], dct["orelse"]) elif dct['ast_type'] == "While": return ast.While(dct["test"], dct["body"], dct["orelse"]) elif dct['ast_type'] == "If": return ast.If(dct["test"], dct["body"], dct["orelse"]) elif dct['ast_type'] == "With": return ast.With(dct["context_expr"], dct["optional_vars"], dct["body"]) elif dct['ast_type'] == "Raise": return ast.Raise(dct["type"], dct["inst"], dct["tback"]) elif dct['ast_type'] == "TryExcept": return ast.TryExcept(dct["body"], dct["handlers"], dct["orelse"]) elif dct['ast_type'] == "TryFinally": return ast.TryFinally(dct["body"], dct["finalbody"]) elif dct['ast_type'] == "Assert": return ast.Assert(dct["test"], dct["msg"]) elif dct['ast_type'] == "Import": return ast.Import(dct["names"]) elif dct['ast_type'] == "ImportFrom": return ast.ImportFrom(dct["module"], dct["names"], dct["level"]) elif dct['ast_type'] == "Exec": return ast.Exec(dct["body"], dct["globals"], dct["locals"]) elif dct['ast_type'] == "Global": return ast.Global(dct["names"]) elif dct['ast_type'] == "Expr": return ast.Expr(dct["value"]) elif dct['ast_type'] == "Pass": return ast.Pass() elif dct['ast_type'] == "Break": return ast.Break() elif dct['ast_type'] == "Continue": return ast.Continue() elif dct['ast_type'] == "BoolOp": return ast.BoolOp(dct["op"], dct["values"]) elif dct['ast_type'] == "BinOp": return ast.BinOp(dct["left"], dct["op"], dct["right"]) elif dct['ast_type'] == "UnaryOp": return ast.UnaryOp(dct["op"], dct["operand"]) elif dct['ast_type'] == "Lambda": return ast.Lambda(dct["args"], dct["body"]) elif dct['ast_type'] == "IfExp": return ast.IfExp(dct["test"], dct["body"], dct["orelse"]) elif dct['ast_type'] == "Dict": return ast.Dict(dct["keys"], dct["values"]) elif dct['ast_type'] == "Set": return ast.Set(dct["elts"]) elif dct['ast_type'] == "ListComp": return ast.ListComp(dct["elt"], dct["generators"]) elif dct['ast_type'] == "SetComp": return ast.SetComp(dct["elt"], dct["generators"]) elif dct['ast_type'] == "DictComp": return ast.DictComp(dct["key"], dct["value"], dct["generators"]) elif dct['ast_type'] == "GeneratorExp": return ast.GeneratorExp(dct["elt"], dct["generators"]) elif dct['ast_type'] == "Yield": return ast.Yield(dct["value"]) elif dct['ast_type'] == "Compare": return ast.Compare(dct["left"], dct["ops"], dct["comparators"]) elif dct['ast_type'] == "Call": return ast.Call(dct["func"], dct["args"], dct["keywords"], dct["starargs"], dct["kwargs"]) elif dct['ast_type'] == "Repr": return ast.Repr(dct["value"]) elif dct['ast_type'] == "Num": return ast.Num(dct["n"]) elif dct['ast_type'] == "Str": # Converting to ASCII return ast.Str(dct["s"].encode('ascii', 'ignore')) elif dct['ast_type'] == "Attribute": return ast.Attribute(dct["value"], dct["attr"], dct["ctx"]) elif dct['ast_type'] == "Subscript": return ast.Subscript(dct["value"], dct["slice"], dct["ctx"]) elif dct['ast_type'] == "Name": return ast.Name(dct["id"], dct["ctx"]) elif dct['ast_type'] == "List": return ast.List(dct["elts"], dct["ctx"]) elif dct['ast_type'] == "Tuple": return ast.Tuple(dct["elts"], dct["ctx"]) elif dct['ast_type'] == "Load": return ast.Load() elif dct['ast_type'] == "Store": return ast.Store() elif dct['ast_type'] == "Del": return ast.Del() elif dct['ast_type'] == "AugLoad": return ast.AugLoad() elif dct['ast_type'] == "AugStore": return ast.AugStore() elif dct['ast_type'] == "Param": return ast.Param() elif dct['ast_type'] == "Ellipsis": return ast.Ellipsis() elif dct['ast_type'] == "Slice": return ast.Slice(dct["lower"], dct["upper"], dct["step"]) elif dct['ast_type'] == "ExtSlice": return ast.ExtSlice(dct["dims"]) elif dct['ast_type'] == "Index": return ast.Index(dct["value"]) elif dct['ast_type'] == "And": return ast.And() elif dct['ast_type'] == "Or": return ast.Or() elif dct['ast_type'] == "Add": return ast.Add() elif dct['ast_type'] == "Sub": return ast.Sub() elif dct['ast_type'] == "Mult": return ast.Mult() elif dct['ast_type'] == "Div": return ast.Div() elif dct['ast_type'] == "Mod": return ast.Mod() elif dct['ast_type'] == "Pow": return ast.Pow() elif dct['ast_type'] == "LShift": return ast.LShift() elif dct['ast_type'] == "RShift": return ast.RShift() elif dct['ast_type'] == "BitOr": return ast.BitOr() elif dct['ast_type'] == "BitXor": return ast.BitXor() elif dct['ast_type'] == "BitAnd": return ast.BitAnd() elif dct['ast_type'] == "FloorDiv": return ast.FloorDiv() elif dct['ast_type'] == "Invert": return ast.Invert() elif dct['ast_type'] == "Not": return ast.Not() elif dct['ast_type'] == "UAdd": return ast.UAdd() elif dct['ast_type'] == "USub": return ast.USub() elif dct['ast_type'] == "Eq": return ast.Eq() elif dct['ast_type'] == "NotEq": return ast.NotEq() elif dct['ast_type'] == "Lt": return ast.Lt() elif dct['ast_type'] == "LtE": return ast.LtE() elif dct['ast_type'] == "Gt": return ast.Gt() elif dct['ast_type'] == "GtE": return ast.GtE() elif dct['ast_type'] == "Is": return ast.Is() elif dct['ast_type'] == "IsNot": return ast.IsNot() elif dct['ast_type'] == "In": return ast.In() elif dct['ast_type'] == "NotIn": return ast.NotIn() elif dct['ast_type'] == "comprehension": return ast.comprehension(dct["target"], dct["iter"], dct["ifs"]) elif dct['ast_type'] == "ExceptHandler": return ast.ExceptHandler(dct["type"], dct["name"], dct["body"]) elif dct['ast_type'] == "arguments": return ast.arguments(dct["args"], dct["vararg"], dct["kwarg"], dct["defaults"]) elif dct['ast_type'] == "keyword": return ast.keyword(dct["arg"], dct["value"]) elif dct['ast_type'] == "alias": return ast.alias(dct["name"], dct["asname"]) else: return dct
def mutate(cls, node): """ mutate binary mathematical operators: +, -, *, /, %, ** """ if node not in config.visited_nodes: if node.__class__ is ast.BinOp and node.op.__class__ in [ ast.Add, ast.Sub, ast.Mult, ast.Div, ast.FloorDiv, ast.Mod, ast.Pow ]: if node.op.__class__ is ast.Add: if node.left.__class__ in [ ast.Str, ast.List ] or node.right.__class__ in [ast.Str, ast.List]: return node if node.op.__class__ in config.arithmetic_operators: config.arithmetic_operators.remove(node.op.__class__) while len(config.arithmetic_operators) > 0: original_node = deepcopy(node) if node in config.parent_dict: parent = config.parent_dict[node] del config.parent_dict[node] op_node = None op_type = config.arithmetic_operators.pop() if op_type is ast.Add: op_node = ast.Add() elif op_type is ast.Sub: op_node = ast.Sub() elif op_type is ast.Mult: op_node = ast.Mult() elif op_type is ast.Div: op_node = ast.Div() elif op_type is ast.FloorDiv: op_node = ast.FloorDiv() elif op_type is ast.Mod: op_node = ast.Div() elif op_type is ast.Pow: op_node = ast.Mult() else: print "TypeError in AOR" if op_node: node.op = op_node config.parent_dict[node] = parent config.node_pairs[node] = original_node config.current_mutated_node = node config.mutated = True return node if len(config.arithmetic_operators) == 0: config.arithmetic_operators = [ ast.Add, ast.Sub, ast.Mult, ast.Div, ast.FloorDiv ] config.visited_nodes.add(node) elif node.__class__ is ast.UnaryOp: if node.op.__class__ is ast.UAdd: config.mutated = True original_node = deepcopy(node) parent = config.parent_dict[node] del config.parent_dict[node] node.op = ast.USub() config.parent_dict[node] = parent config.node_pairs[node] = original_node config.current_mutated_node = node elif node.op.__class__ is ast.USub: config.mutated = True original_node = deepcopy(node) parent = config.parent_dict[node] del config.parent_dict[node] node.op = ast.UAdd() config.parent_dict[node] = parent config.node_pairs[node] = original_node config.current_mutated_node = node # todo: try more unary operations return node
def mutate_USub(self, node): return ast.UAdd()
def test_UnaryAdd(self): py_ast = ast.UnaryOp(ast.UAdd(), ast.Name('i', ast.Load())) c_ast = Add(SymbolRef('i')) self._check(py_ast, c_ast)
def __pos__(self) -> UnaryOp[T]: # usually a no-op return UnaryOp(ast.UAdd(), self)
def factor(self, p): return ast.UnaryOp(op=ast.UAdd(), operand=p.factor)
def mutate(self, node): """Replace the unary-sub operator with unary-add. """ node.op = ast.UAdd() return node
def UnaryOp(draw, expression) -> ast.UnaryOp: op = draw(sampled_from([ast.USub(), ast.UAdd(), ast.Not(), ast.Invert()])) l = draw(expression) return ast.UnaryOp(op, l)