def num_negate(op):
top = type(op)
neg = not op.num_negated if hasattr(op, "num_negated") else True
if top == ast.Add:
newOp = ast.Sub()
elif top == ast.Sub:
newOp = ast.Add()
elif top in [ast.Mult, ast.Div, ast.Mod, ast.Pow, ast.LShift,
ast.RShift, ast.BitOr, ast.BitXor, ast.BitAnd, ast.FloorDiv]:
return None # can't negate this
elif top in [ast.Num, ast.Name]:
# this is a normal value, so put a - in front of it
newOp = ast.UnaryOp(ast.USub(addedNeg=True), op)
else:
log("astTools\tnum_negate\tUnusual type: " + str(top), "bug")
transferMetaData(op, newOp)
newOp.num_negated = neg
return newOp
python类RShift()的实例源码
def binop_str(op: ast.AST) -> str:
if isinstance(op, ast.Add):
return '+'
if isinstance(op, ast.Sub):
return '-'
if isinstance(op, ast.Mult):
return '*'
if isinstance(op, ast.Div):
return '/ '
if isinstance(op, ast.Mod):
return '%'
if isinstance(op, ast.LShift):
return '<<'
if isinstance(op, ast.RShift):
return '>>'
if isinstance(op, ast.BitOr):
return '|'
if isinstance(op, ast.BitXor):
return '^'
if isinstance(op, ast.BitAnd):
return '&'
if isinstance(op, ast.MatMult):
return '@'
error(loc(op), "Invalid binary operator encountered: {0}:{1}. Check supported intrinsics.".format(op.lineno, op.col_offset))
return 'INVALID_BINOP'
def _infer_arithmetic(left_type, right_type, op, lineno, solver):
"""Infer the type of an arithmetic operation, and add the corresponding axioms"""
result_type = solver.new_z3_const("arithmetic_result")
magic_method = ""
if isinstance(op, ast.Sub):
magic_method = "__sub__"
elif isinstance(op, ast.FloorDiv):
magic_method = "__floordiv__"
elif isinstance(op, ast.Mod):
magic_method = "__mod__"
elif isinstance(op, ast.LShift):
magic_method = "__lshift__"
elif isinstance(op, ast.RShift):
magic_method = "__rshift__"
solver.add(axioms.arithmetic(left_type, right_type, result_type, magic_method,
isinstance(op, ast.Mod), solver.z3_types),
fail_message="Arithmetic operation in line {}".format(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 _process_function_signature(stmt, arg_names, static_env):
return_type = Ellipsis
if isinstance(stmt, ast.Expr):
value = stmt.value
if isinstance(value, ast.BinOp):
left, op, right = value.left, value.op, value.right
if isinstance(op, ast.RShift):
arg_types = fn._process_argument_signature(left, arg_names,
static_env)
return_type = static_env.eval_expr_ast(right)
else:
return None
elif isinstance(value, ast.Dict) or isinstance(value, ast.Set):
arg_types = fn._process_argument_signature(value, arg_names,
static_env)
else:
return None
else:
return None
if arg_types is None:
return None
return (arg_types, return_type)
def doBinaryOp(op, l, r):
"""Perform the given AST binary operation on the values"""
top = type(op)
if top == ast.Add:
return l + r
elif top == ast.Sub:
return l - r
elif top == ast.Mult:
return l * r
elif top == ast.Div:
# Don't bother if this will be a really long float- it won't work properly!
# Also, in Python 3 this is floating division, so perform it accordingly.
val = 1.0 * l / r
if (val * 1e10 % 1.0) != 0:
raise Exception("Repeating Float")
return val
elif top == ast.Mod:
return l % r
elif top == ast.Pow:
return l ** r
elif top == ast.LShift:
return l << r
elif top == ast.RShift:
return l >> r
elif top == ast.BitOr:
return l | r
elif top == ast.BitXor:
return l ^ r
elif top == ast.BitAnd:
return l & r
elif top == ast.FloorDiv:
return l // r
def test_shift_error(self):
self.check_dont_optimize_func("1 << -3",
ast.BinOp(left=ast.Num(n=1), op=ast.LShift(), right=ast.Num(-3)))
self.check_dont_optimize_func("1 >> -3",
ast.BinOp(left=ast.Num(n=1), op=ast.RShift(), right=ast.Num(-3)))
def get_binary_op_str(bin_op_node):
"""Returns the string representation of the binary operator node (e.g. +, -,
etc.). For some reason astor doesn't implement this???
"""
if isinstance(bin_op_node, ast.Add):
return "+"
elif isinstance(bin_op_node, ast.Sub):
return "-"
elif isinstance(bin_op_node, ast.Mult):
return "*"
elif isinstance(bin_op_node, ast.Div):
return "/"
elif isinstance(bin_op_node, ast.Mod):
return "%"
elif isinstance(bin_op_node, ast.Pow):
return "**"
elif isinstance(bin_op_node, ast.LShift):
return "<<"
elif isinstance(bin_op_node, ast.RShift):
return ">>"
else:
raise ValueError("No string defined for binary operator node %s" % \
bin_op_node.__class__.__name__)
def mutate_LShift(self, node):
return ast.RShift()
def syn_BinOp(self, ctx, e):
if isinstance(e.op, (ast.LShift, ast.RShift, ast.BitOr, ast.BitXor, ast.BitAnd)):
raise _errors.TyError("Cannot use bitwise operators on ieee values.", e)
ctx.ana(e.right, self)
return self
def syn_BinOp(self, ctx, e):
if isinstance(e.op, (ast.LShift, ast.RShift, ast.BitOr, ast.BitXor, ast.BitAnd)):
raise _errors.TyError("Cannot use bitwise operators on cplx values.", e)
if isinstance(e.op, ast.Mod):
raise _errors.TyError("Cannot take the modulus of a complex number.", e)
right = e.right
ctx.ana(right, self)
return self
def check_binop(self, op, left, right):
if isinstance(left, COMPLEX_TYPES) and isinstance(right, COMPLEX_TYPES):
if isinstance(op, DIVIDE_BINOPS) and not right:
# x/0: ZeroDivisionError
return False
if isinstance(op, ast.Pow):
if isinstance(left, complex) or isinstance(right, complex):
return False
return check_pow(self.config, left, right)
if isinstance(op, (ast.LShift, ast.RShift)) and right < 0:
# 1 << -3 and 1 >> -3 raise a ValueError
return False
if isinstance(left, int) and isinstance(right, int):
return True
if isinstance(left, FLOAT_TYPES) and isinstance(right, FLOAT_TYPES):
return isinstance(op, FLOAT_BINOPS)
if isinstance(left, COMPLEX_TYPES) and isinstance(right, COMPLEX_TYPES):
return isinstance(op, COMPLEX_BINOPS)
if isinstance(op, ast.Mult):
if isinstance(right, int):
# bytes * int
if isinstance(left, bytes):
return (len(left) * right <= self.config.max_bytes_len)
# str * int
if isinstance(left, str):
return (len(left) * right <= self.config.max_str_len)
# tuple * int
if isinstance(left, tuple):
size = get_constant_size(left)
return (size * right <= self.config.max_seq_len)
if isinstance(left, int):
# int * bytes
if isinstance(right, bytes):
return (left * len(right) <= self.config.max_bytes_len)
# int * str
if isinstance(right, str):
return (left * len(right) <= self.config.max_str_len)
# int * tuple
if isinstance(right, tuple):
size = get_constant_size(right)
return (left * size <= self.config.max_seq_len)
if isinstance(op, ast.Add):
if isinstance(left, str) and isinstance(right, str):
return ((len(left) + len(right)) <= self.config.max_str_len)
if isinstance(left, bytes) and isinstance(right, bytes):
return ((len(left) + len(right)) <= self.config.max_bytes_len)
if isinstance(left, tuple) and isinstance(right, tuple):
return ((len(left) + len(right)) <= self.config.max_seq_len)
return False