我们从Python开源项目中,提取了以下43个代码示例,用于说明如何使用ast.Not()。
def visit_If(self, node): new_node = self._visit_if_while(node) if new_node is not None: return new_node if node.orelse and is_empty_body(node.orelse): self.log_node_removal("Remove dead code (empty else block of if)", node.orelse) new_node = copy_node(node) del new_node.orelse[:] node = new_node if is_empty_body(node.body) and not is_empty_body(node.orelse): self.log_node_removal("Remove dead code (empty if block)", node.body) new_node = copy_node(node) not_test = ast.UnaryOp(op=ast.Not(), operand=node.test) copy_lineno(node.test, not_test) new_node = ast.If(test=not_test, body=new_node.orelse, orelse=[]) copy_lineno(node, new_node) return new_node return node
def visit_UnaryOp(self, node): if not self.config.constant_folding: return eval_unaryop = EVAL_UNARYOP.get(node.op.__class__) if eval_unaryop is None: return if isinstance(node.op, ast.Invert): types = int else: types = COMPLEX_TYPES value = get_constant(node.operand, types=types) if value is not UNSET: result = eval_unaryop(value) return self.new_constant(node, result) if (isinstance(node.op, ast.Not) and isinstance(node.operand, ast.Compare)): new_node = self.not_compare(node) if new_node is not None: return new_node
def infer_unary_operation(node, context, solver): """Infer the type for unary operations Examples: -5, not 1, ~2 """ unary_type = infer(node.operand, context, solver) if isinstance(node.op, ast.Not): # (not expr) always gives bool type return solver.z3_types.bool if isinstance(node.op, ast.Invert): solver.add(axioms.unary_invert(unary_type, solver.z3_types), fail_message="Invert operation in line {}".format(node.lineno)) return solver.z3_types.int else: result_type = solver.new_z3_const("unary_result") solver.add(axioms.unary_other(unary_type, result_type, solver.z3_types), fail_message="Unary operation in line {}".format(node.lineno)) return result_type
def __init__(self): super().__init__() # add support for bitwise operators if ast.LShift not in self.MATH_OPERATORS: # '<<' self.MATH_OPERATORS[ast.LShift] = simpleeval.op.lshift if ast.RShift not in self.MATH_OPERATORS: # '>>' self.MATH_OPERATORS[ast.RShift] = simpleeval.op.rshift if ast.BitOr not in self.MATH_OPERATORS: # '|' self.MATH_OPERATORS[ast.BitOr] = simpleeval.op.or_ if ast.BitXor not in self.MATH_OPERATORS: # '^' self.MATH_OPERATORS[ast.BitXor] = simpleeval.op.xor if ast.BitAnd not in self.MATH_OPERATORS: # '&' self.MATH_OPERATORS[ast.BitAnd] = simpleeval.op.and_ # add support for extra operators #if ast.Not not in self.MATH_OPERATORS: # not ('not') # self.MATH_OPERATORS[ast.Not] = simpleeval.op.not_ if ast.FloorDiv not in self.MATH_OPERATORS: # floordiv ('//') self.MATH_OPERATORS[ast.FloorDiv] = simpleeval.op.floordiv
def check_identifier(self, name): assert isinstance(name, str), "An identifier must be a string: %r" % (name,) # Not a private, mangled name: # XXX also make sure there's no '.' inside (the compiler will add some sometimes) assert len(name) <= 2 or not name.startswith('__') or name.endswith('__'), \ "Mangled private names are not supported: %r" % (name,)
def unary_operations(self): operand = Expr.parse_value_expr(self.expr.operand, self.context) if isinstance(self.expr.op, ast.Not): # Note that in the case of bool, num, address, decimal, num256 AND bytes32, # a zero entry represents false, all others represent true return LLLnode.from_list(["iszero", operand], typ='bool', pos=getpos(self.expr)) elif isinstance(self.expr.op, ast.USub): if not is_numeric_type(operand.typ): raise TypeMismatchException("Unsupported type for negation: %r" % operand.typ, operand) return LLLnode.from_list(["sub", 0, operand], typ=operand.typ, pos=getpos(self.expr)) else: raise StructureException("Only the 'not' unary operator is supported") # Function calls
def visit_BoolOp(self, boolop): res_var = self.variable() expl_list = self.assign(ast.List([], ast.Load())) app = ast.Attribute(expl_list, "append", ast.Load()) is_or = int(isinstance(boolop.op, ast.Or)) body = save = self.statements fail_save = self.on_failure levels = len(boolop.values) - 1 self.push_format_context() # Process each operand, short-circuting if needed. for i, v in enumerate(boolop.values): if i: fail_inner = [] # cond is set in a prior loop iteration below self.on_failure.append(ast.If(cond, fail_inner, [])) # noqa self.on_failure = fail_inner self.push_format_context() res, expl = self.visit(v) body.append(ast.Assign([ast.Name(res_var, ast.Store())], res)) expl_format = self.pop_format_context(ast.Str(expl)) call = ast_Call(app, [expl_format], []) self.on_failure.append(ast.Expr(call)) if i < levels: cond = res if is_or: cond = ast.UnaryOp(ast.Not(), cond) inner = [] self.statements.append(ast.If(cond, inner, [])) self.statements = body = inner self.statements = save self.on_failure = fail_save expl_template = self.helper("format_boolop", expl_list, ast.Num(is_or)) expl = self.pop_format_context(expl_template) return ast.Name(res_var, ast.Load()), self.explanation_param(expl)
def visit_If(self, node): node = self.generic_visit(node) if (node.orelse and len(node.orelse) == 1 and isinstance(node.orelse[0], ast.Pass) ): node.orelse = [] if (len(node.body) == 1 and isinstance(node.body[0], ast.Pass) ): if node.orelse: node_test = ast.UnaryOp(op=ast.Not(), operand=node.test) if (len(node.orelse) == 1 and isinstance(node.orelse[0], ast.If) ): node_test = ast.BoolOp\ ( op = ast.And() , values = [node_test, node.orelse[0].test] ) node.test = ast.copy_location(node_test, node.orelse[0].test) node.body = node.orelse[0].body node.orelse = node.orelse[0].orelse else: node.test = ast.copy_location(node_test, node.test) node.body = node.orelse node.orelse = [] else: node = None return node
def diffLists(x, y, ignoreVariables=False): mapSet = matchLists(x, y) changeVectors = [] # First, get all the added and deleted lines deletedLines = mapSet[-1] if -1 in mapSet else [] for line in sorted(deletedLines): changeVectors.append(DeleteVector([line], x[line], None)) addedLines = list(filter(lambda tmp : mapSet[tmp] == -1, mapSet.keys())) addedOffset = 0 # Because added lines don't start in the list, we need # to offset their positions for each new one that's added for line in sorted(addedLines): changeVectors.append(AddVector([line - addedOffset], None, y[line])) addedOffset += 1 # Now, find all the required moves changeVectors += findMoveVectors(mapSet, x, y, addedLines, deletedLines) # Finally, for each pair of lines (which have already been moved appropriately, # find if they need a normal ChangeVector for j in mapSet: i = mapSet[j] # Not a delete or an add if j != -1 and i != -1: tempVectors = diffAsts(x[i], y[j], ignoreVariables=ignoreVariables) for change in tempVectors: change.path.append(i) changeVectors += tempVectors return changeVectors
def isNegation(a, b): """Is a the negation of b?""" return compareASTs(deMorganize(ast.UnaryOp(ast.Not(), deepcopy(a))), b, checkEquality=True) == 0
def doUnaryOp(op, val): """Perform the given AST unary operation on the value""" top = type(op) if top == ast.Invert: return ~ val elif top == ast.Not: return not val elif top == ast.UAdd: return val elif top == ast.USub: return -val
def _translate_unaryop(self, operand, op, location): value = operand if isinstance(op, ast.USub): value_node = self._translate_node(value) if value_node['pseudo_type'] != 'Int' and value_node['pseudo_type'] != 'Float': raise type_check_error('- expects Int or Float', location, self.lines[location[0]], wrong_type=value_node['pseudo_type']) if value_node['type'] == 'int': return { 'type': 'int', 'value': -value_node['value'], 'pseudo_type': 'Int' } else: return { 'type': 'unary_op', 'op': '-', 'value': value_node, 'pseudo_type': value_node['pseudo_type'] } elif isinstance(op, ast.Not): value_node = self._testable(self._translate_node(value)) if value_node['type'] == 'standard_method_call' and value_node['message'] == 'present?': value_node['message'] = 'empty?' return value_node else: return { 'type': 'unary_op', 'op': 'not', 'value': value_node, 'pseudo_type': 'Boolean' } else: raise translation_error('no support for %s as an unary op' % type(op).__name__, location, self.lines[location[0]], suggestions='not and - are supported')
def generate_unaryop(self, node, ext_info): if isinstance(node.op, ast.Not): return '! ' + self.dispatch(node.operand, ext_info) else: SyntaxNotSupportError("%s is not support yet" % node.op.__class__.__name__)
def _safe_eval(node, default): """ Safely evaluate the Boolean expression under the given AST node. Substitute `default` for all sub-expressions that cannot be evaluated (because variables or functions are undefined). We could use eval() to evaluate more sub-expressions. However, this function is not safe for arbitrary Python code. Even after overwriting the "__builtins__" dictionary, the original dictionary can be restored (https://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html). """ if isinstance(node, ast.BoolOp): results = [_safe_eval(value, default) for value in node.values] if isinstance(node.op, ast.And): return all(results) else: return any(results) elif isinstance(node, ast.UnaryOp) and isinstance(node.op, ast.Not): return not _safe_eval(node.operand, not default) else: try: return ast.literal_eval(node) except ValueError: return default
def visit_UnaryOp(self, node, **kwargs): if isinstance(node.op, (ast.Not, ast.Invert)): return UnaryOp('~', self.visit(node.operand)) elif isinstance(node.op, ast.USub): return self.const_type(-self.visit(node.operand).value, self.env) elif isinstance(node.op, ast.UAdd): raise NotImplementedError('Unary addition not supported')
def rewrite_expr_z3(r, is_py_ast=True): # Rewrites py_ast expression to a str expression that could be used in z3 # Return (z3_expr_str, z3_varnames) z3_expr_str = (py_ast.dump_ast(r) if is_py_ast else r).strip() z3_expr_str = z3_expr_str.replace('.', '_').replace('[', '_').replace(']', '_') rp = py_ast.get_ast(z3_expr_str).body[0].value for node in py_ast.find_all(rp, ast.UnaryOp): if isinstance(node.op, ast.Not): if rp == node: rp = py_ast.get_ast('z3.Not(' + py_ast.dump_ast(node.operand) + ')').body[0].value else: py_ast.replace_node(rp, node, py_ast.get_ast('z3.Not(' + py_ast.dump_ast(node.operand) + ')').body[0].value) for node in py_ast.find_all(rp, ast.BoolOp): if isinstance(node.op, ast.And): if rp == node: rp = py_ast.get_ast('z3.And(' + py_ast.dump_ast(node.values[0]) + ',' + py_ast.dump_ast(node.values[1]) + ')') else: py_ast.replace_node(rp, node, py_ast.get_ast('z3.And(' + py_ast.dump_ast(node.values[0]) + ',' + py_ast.dump_ast(node.values[1]) + ')')) elif isinstance(node.op, ast.Or): if rp == node: rp = py_ast.get_ast('z3.Or(' + py_ast.dump_ast(node.values[0]) + ',' + py_ast.dump_ast(node.values[1]) + ')') else: py_ast.replace_node(rp, node, py_ast.get_ast('z3.Or(' + py_ast.dump_ast(node.values[0]) + ',' + py_ast.dump_ast(node.values[1]) + ')')) z3_expr_str = py_ast.dump_ast(rp) z3_vars = set() for node in py_ast.find_all(rp, ast.Name): z3_vars.add(node.id) return (z3_expr_str, z3_vars)
def unop_str(op: ast.AST) -> str: if isinstance(op, ast.UAdd): return '+' if isinstance(op, ast.USub): return '-' if isinstance(op, ast.Not): return '!' if isinstance(op, ast.Invert): return '~' error(loc(op), "Invalid unary operator encountered: {0}:{1}. Check supported intrinsics.".format(op.lineno, op.col_offset)) return 'INVALID_UNOP'
def visit_UnaryOp(self, node): term = self.visit(node.operand) if self.__is_bool(term): if isinstance(node.op, ast.Not): return Not(term) elif isinstance(node.op, ast.Invert): return Not(term) else: raise Exception("Unsupported bool unary operation %s" % unparse(node)) if DATA_TYPE == "int": if isinstance(node.op, ast.USub): return -term elif isinstance(node.op, ast.Not): if is_is_int(term): term = term == IntVal(1) return Not(term) else: raise Exception("Unsupported integer unary operation %s" % unparse(node)) elif DATA_TYPE.startswith("bit_"): if isinstance(node.op, ast.Not): return ~term elif isinstance(node.op, ast.Invert): return ~term else: raise Exception("Unsupported bitvector unary operation %s" % unparse(node)) else: raise Exception("Unsupported unary operation %s" % unparse(node))
def visit_Compare(self, node): left_term = self.visit(node.left) if len(node.comparators) > 1: raise Exception("Cannot handle 'foo > bar > baz' comparison in %s" % unparse(node)) right_term = self.visit(node.comparators[0]) op = node.ops[0] if isinstance(op, ast.Eq): if self.__is_bool(left_term) and self.__is_bool(right_term): if left_term == True: return right_term elif right_term == True: return left_term elif left_term == False: return Not(right_term) elif right_term == False: return Not(left_term) return left_term == right_term elif isinstance(op, ast.Lt): return left_term < right_term elif isinstance(op, ast.LtE): return left_term <= right_term elif isinstance(op, ast.Gt): return left_term > right_term elif isinstance(op, ast.GtE): return left_term >= right_term else: raise Exception("Unhandled operators '%s' in %s" % (unparse(op), unparse(node)))
def visit_If(self, if_node): exprVisitor = ToZ3ExprVisitor(env=self.__env) test_term = exprVisitor.visit(if_node.test) then_constraints = list(itertools.chain.from_iterable([ self.visit(stmt) for stmt in if_node.body])) else_constraints = list(itertools.chain.from_iterable([ self.visit(stmt) for stmt in if_node.orelse])) then_constraint = then_constraints[0] if len(then_constraints) == 1 else And(then_constraints) else_constraint = else_constraints[0] if len(else_constraints) == 1 else And(else_constraints) if len(else_constraints) == 0: return [Implies(test_term, then_constraint)] else: return [Implies(test_term, then_constraint), Implies(Not(test_term), else_constraint)]
def Not(self): c = criteria_class.instance(Const.Not, self._pop()) self._push(c) return self
def __init__(self, one): if not isinstance(one, Criteria): raise TypeError("%s is not supported" % type(one)) super(Not, self).__init__(stack=False) self._one = one
def visit_UnaryOp(self, node): if type(node.op) not in (ast.Not,): raise SyntaxError("%s is not supported" % type(node.op)) self.visit(node.operand) obj = self.data.pop() criteria = obj if isinstance(obj, Criteria) else criteria_class.instance(Const.Bool, obj) cls = criteria_class.lookup(ast_op_to_criteria.lookup(type(node.op))) criteria = cls(criteria) self.data.append(criteria)
def negate_test(self, node): not_node = ast.UnaryOp(op=ast.Not(), operand=node.test) node.test = not_node return node
def syn_UnaryOp(self, ctx, e): if isinstance(e.op, ast.Not): return self else: raise _errors.TyError( """Type bool does not support this unary operator.""", e)
def translate_pat_Name_constructor(self, ctx, pat, scrutinee): id = pat.id if id == "True": return (scrutinee, typy.odict()) elif id == "False": return (ast.UnaryOp(op=ast.Not(), operand=scrutinee), typy.odict())
def syn_UnaryOp(self, ctx, e): if not isinstance(e.op, ast.Not): return self else: raise _errors.TyError( "Invalid unary operator 'not' for operand of type num.", e)
def syn_UnaryOp(self, ctx, e): if isinstance(e.op, (ast.Not, ast.Invert)): raise _errors.TyError("Invalid unary operator for operand of type ieee.", e) else: return self
def syn_UnaryOp(self, ctx, e): if not isinstance(e.op, (ast.Not, ast.Invert)): return self else: raise _errors.TyError("Invalid unary operator for operand of type cplx.", e)
def visit_Assert(self, assert_): """Return the AST statements to replace the ast.Assert instance. This re-writes the test of an assertion to provide intermediate values and replace it with an if statement which raises an assertion error with a detailed explanation in case the expression is false. """ if isinstance(assert_.test, ast.Tuple) and self.config is not None: fslocation = (self.module_path, assert_.lineno) self.config.warn('R1', 'assertion is always true, perhaps ' 'remove parentheses?', fslocation=fslocation) self.statements = [] self.variables = [] self.variable_counter = itertools.count() self.stack = [] self.on_failure = [] self.push_format_context() # Rewrite assert into a bunch of statements. top_condition, explanation = self.visit(assert_.test) # Create failure message. body = self.on_failure negation = ast.UnaryOp(ast.Not(), top_condition) self.statements.append(ast.If(negation, body, [])) if assert_.msg: assertmsg = self.helper('format_assertmsg', assert_.msg) explanation = "\n>assert " + explanation else: assertmsg = ast.Str("") explanation = "assert " + explanation template = ast.BinOp(assertmsg, ast.Add(), ast.Str(explanation)) msg = self.pop_format_context(template) fmt = self.helper("format_explanation", msg) err_name = ast.Name("AssertionError", ast.Load()) exc = ast_Call(err_name, [fmt], []) if sys.version_info[0] >= 3: raise_ = ast.Raise(exc, None) else: raise_ = ast.Raise(exc, None, None) body.append(raise_) # Clear temporary variables by setting them to None. if self.variables: variables = [ast.Name(name, ast.Store()) for name in self.variables] clear = ast.Assign(variables, _NameConstant(None)) self.statements.append(clear) # Fix line numbers. for stmt in self.statements: set_location(stmt, assert_.lineno, assert_.col_offset) return self.statements
def specialFunctions(cv, old, new): if type(old) == type(new) == list: log("individualize\tspecialFunctions\tWhy are we comparing lists?: " + str(cv) + ";" + printFunction(old) + ";" + printFunction(new), "bug") return cv rev = neg = False if (hasattr(old, "reversed") and old.reversed and (not hasattr(old, "multCompFixed"))): rev = True if (hasattr(old, "negated") and old.negated): neg = True if rev and neg: (old, new) = (negate(undoReverse(old)), negate(undoReverse(new))) elif rev: (old, new) = (undoReverse(old), undoReverse(new)) elif neg: (old, new) = (negate(old), negate(new)) if type(old) == ast.UnaryOp and type(old.op) == ast.Not and \ type(new) == ast.UnaryOp and type(new.op) == ast.Not: # Just get rid of them old = old.operand new = new.operand if hasattr(old, "num_negated") and old.num_negated: origNew = deepcopy(new) (old, new) = (num_negate(old), num_negate(new)) if new == None: # couldn't reverse the new operator # To get here, we must have a binary operator. Go up a level and negate the right side cvCopy = cv.deepcopy() parentSpot = deepcopy(cvCopy.traverseTree(cvCopy.start)) if type(parentSpot) == ast.BinOp: cvCopy.path = cvCopy.path[1:] cvCopy.oldSubtree = parentSpot cvCopy.newSubtree = deepcopy(parentSpot) cvCopy.newSubtree.op = origNew cvCopy.newSubtree.right = num_negate(cvCopy.newSubtree.right) cvCopy = orderedBinOpSpecialFunction(cvCopy) # just in case return cvCopy else: log("individualize\tspecialFunctions\tWhere are we? " + str(type(parentSpot)), "bug") #if (hasattr(old, "inverted") and old.inverted): # (old, new) = (invert(old), invert(new)) cv.oldSubtree = old cv.newSubtree = new return cv
def areDisjoint(a, b): """Are the sets of values that satisfy these two boolean constraints disjoint?""" # The easiest way to be disjoint is to have comparisons that cover different areas if type(a) == type(b) == ast.Compare: aop = a.ops[0] bop = b.ops[0] aLeft = a.left aRight = a.comparators[0] bLeft = b.left bRight = b.comparators[0] alblComp = compareASTs(aLeft, bLeft, checkEquality=True) albrComp = compareASTs(aLeft, bRight, checkEquality=True) arblComp = compareASTs(aRight, bLeft, checkEquality=True) arbrComp = compareASTs(aRight, bRight, checkEquality=True) altype = type(aLeft) in [ast.Num, ast.Str] artype = type(aRight) in [ast.Num, ast.Str] bltype = type(bLeft) in [ast.Num, ast.Str] brtype = type(bRight) in [ast.Num, ast.Str] if (type(aop) == ast.Eq and type(bop) == ast.NotEq) or \ (type(bop) == ast.Eq and type(aop) == ast.NotEq): # x == y, x != y if (alblComp == 0 and arbrComp == 0) or (albrComp == 0 and arblComp == 0): return True elif type(aop) == type(bop) == ast.Eq: if (alblComp == 0 and arbrComp == 0) or (albrComp == 0 and arblComp == 0): return False # x = num1, x = num2 elif alblComp == 0 and artype and brtype: return True elif albrComp == 0 and artype and bltype: return True elif arblComp == 0 and altype and brtype: return True elif arbrComp == 0 and altype and bltype: return True elif (type(aop) == ast.Lt and type(bop) == ast.GtE) or \ (type(aop) == ast.Gt and type(bop) == ast.LtE) or \ (type(aop) == ast.LtE and type(bop) == ast.Gt) or \ (type(aop) == ast.GtE and type(bop) == ast.Lt) or \ (type(aop) == ast.Is and type(bop) == ast.IsNot) or \ (type(aop) == ast.IsNot and type(bop) == ast.Is) or \ (type(aop) == ast.In and type(bop) == ast.NotIn) or \ (type(aop) == ast.NotIn and type(bop) == ast.In): if alblComp == 0 and arbrComp == 0: return True elif (type(aop) == ast.Lt and type(bop) == ast.LtE) or \ (type(aop) == ast.Gt and type(bop) == ast.GtE) or \ (type(aop) == ast.LtE and type(bop) == ast.Lt) or \ (type(aop) == ast.GtE and type(bop) == ast.Gt): if albrComp == 0 and arblComp == 0: return True elif type(a) == type(b) == ast.BoolOp: return False # for now- TODO: when is this not true? elif type(a) == ast.UnaryOp and type(a.op) == ast.Not: if compareASTs(a.operand, b, checkEquality=True) == 0: return True elif type(b) == ast.UnaryOp and type(b.op) == ast.Not: if compareASTs(b.operand, a, checkEquality=True) == 0: return True return False
def deMorganize(a): """Apply De Morgan's law throughout the code in order to canonicalize""" if not isinstance(a, ast.AST): return a # We only care about statements beginning with not if type(a) == ast.UnaryOp and type(a.op) == ast.Not: oper = a.operand top = type(oper) # not (blah and gah) == (not blah or not gah) if top == ast.BoolOp: oper.op = negate(oper.op) for i in range(len(oper.values)): oper.values[i] = deMorganize(negate(oper.values[i])) oper.negated = not oper.negated if hasattr(oper, "negated") else True transferMetaData(a, oper) return oper # not a < b == a >= b elif top == ast.Compare: oper.left = deMorganize(oper.left) oper.ops = [negate(oper.ops[0])] oper.comparators = [deMorganize(oper.comparators[0])] oper.negated = not oper.negated if hasattr(oper, "negated") else True transferMetaData(a, oper) return oper # not not blah == blah elif top == ast.UnaryOp and type(oper.op) == ast.Not: oper.operand = deMorganize(oper.operand) if eventualType(oper.operand) != bool: return a oper.operand.negated = not oper.operand.negated if hasattr(oper.operand, "negated") else True return oper.operand elif top == ast.NameConstant: if oper.value in [True, False]: oper = negate(oper) transferMetaData(a, oper) return oper elif oper.value == None: tmp = ast.NameConstant(True) transferMetaData(a, tmp) tmp.negated = True return tmp else: log("Unknown NameConstant: " + str(oper.value), "bug") return applyToChildren(a, deMorganize) ##### CLEANUP FUNCTIONS #####
def negate(op): """Return the negation of the provided operator""" if op == None: return None top = type(op) neg = not op.negated if hasattr(op, "negated") else True if top == ast.And: newOp = ast.Or() elif top == ast.Or: newOp = ast.And() elif top == ast.Eq: newOp = ast.NotEq() elif top == ast.NotEq: newOp = ast.Eq() elif top == ast.Lt: newOp = ast.GtE() elif top == ast.GtE: newOp = ast.Lt() elif top == ast.Gt: newOp = ast.LtE() elif top == ast.LtE: newOp = ast.Gt() elif top == ast.Is: newOp = ast.IsNot() elif top == ast.IsNot: newOp = ast.Is() elif top == ast.In: newOp = ast.NotIn() elif top == ast.NotIn: newOp = ast.In() elif top == ast.NameConstant and op.value in [True, False]: op.value = not op.value op.negated = neg return op elif top == ast.Compare: if len(op.ops) == 1: op.ops[0] = negate(op.ops[0]) op.negated = neg return op else: values = [] allOperands = [op.left] + op.comparators for i in range(len(op.ops)): values.append(ast.Compare(allOperands[i], [negate(op.ops[i])], [allOperands[i+1]], multiCompPart=True)) newOp = ast.BoolOp(ast.Or(multiCompOp=True), values, multiComp=True) elif top == ast.UnaryOp and type(op.op) == ast.Not and \ eventualType(op.operand) == bool: # this can mess things up type-wise return op.operand else: # this is a normal value, so put a not around it newOp = ast.UnaryOp(ast.Not(addedNot=True), op) transferMetaData(op, newOp) newOp.negated = neg return newOp
def rewrite_expr_z3_py_ast(r, is_py_ast=True): if verbose and False: print('rewrite_expr_z3_py_ast:', r) # Rewrites py_ast expression to a str expression that could be used in z3 # Return (z3_expr_str, z3_varnames) z3_expr_str = (py_ast.dump_ast(r) if is_py_ast else r).strip() z3_expr_str = z3_expr_str.replace('.', '_').replace('[', '_').replace(']', '_') rp = py_ast.get_ast(z3_expr_str).body[0].value nodes = py_ast.find_all(rp, ast.UnaryOp) while nodes != []: node = nodes[0] if isinstance(node.op, ast.Not): if rp == node: rp = py_ast.get_ast('z3.Not(' + py_ast.dump_ast(node.operand) + ')').body[0].value else: py_ast.replace_node(rp, node, py_ast.get_ast('z3.Not(' + py_ast.dump_ast(node.operand) + ')').body[0].value) nodes = py_ast.find_all(rp, ast.UnaryOp) else: nodes = nodes[1:] nodes = py_ast.find_all(rp, ast.BoolOp) while nodes != []: node = nodes[0] if isinstance(node.op, ast.And): rp_str = 'z3.And(' for value in node.values: rp_str += py_ast.dump_ast(value) + ', ' rp_str = rp_str.rstrip(', ') rp_str += ')' if rp == node: rp = py_ast.get_ast(rp_str).body[0].value else: py_ast.replace_node(rp, node, py_ast.get_ast(rp_str).body[0].value) elif isinstance(node.op, ast.Or): rp_str = 'z3.Or(' for value in node.values: rp_str += py_ast.dump_ast(value) + ', ' rp_str = rp_str.rstrip(', ') rp_str += ')' if rp == node: rp = py_ast.get_ast(rp_str).body[0].value else: py_ast.replace_node(rp, node, py_ast.get_ast(rp_str).body[0].value) nodes = py_ast.find_all(rp, ast.BoolOp) z3_expr_str = py_ast.dump_ast(rp) z3_vars = set() for node in py_ast.find_all(rp, ast.Name): z3_vars.add(node.id) if 'z3' in z3_vars: z3_vars.remove('z3') return (z3_expr_str, z3_vars)
def visit_Assert(self, assert_): """Return the AST statements to replace the ast.Assert instance. This re-writes the test of an assertion to provide intermediate values and replace it with an if statement which raises an assertion error with a detailed explanation in case the expression is false. """ self.statements = [] self.variables = [] self.variable_counter = itertools.count() self.stack = [] self.on_failure = [] self.push_format_context() # Rewrite assert into a bunch of statements. top_condition, explanation = self.visit(assert_.test) # Create failure message. body = self.on_failure negation = ast.UnaryOp(ast.Not(), top_condition) self.statements.append(ast.If(negation, body, [])) if assert_.msg: assertmsg = self.helper('format_assertmsg', assert_.msg) explanation = "\n>assert " + explanation else: assertmsg = ast.Str("") explanation = "assert " + explanation template = ast.BinOp(assertmsg, ast.Add(), ast.Str(explanation)) msg = self.pop_format_context(template) fmt = self.helper("format_explanation", msg) err_name = ast.Name("AssertionError", ast.Load()) exc = ast_Call(err_name, [fmt], []) if sys.version_info[0] >= 3: raise_ = ast.Raise(exc, None) else: raise_ = ast.Raise(exc, None, None) body.append(raise_) # Clear temporary variables by setting them to None. if self.variables: variables = [ast.Name(name, ast.Store()) for name in self.variables] clear = ast.Assign(variables, _NameConstant(None)) self.statements.append(clear) # Fix line numbers. for stmt in self.statements: set_location(stmt, assert_.lineno, assert_.col_offset) return self.statements