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类BitXor()的实例源码
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 eval_expr(expr):
import ast
import operator as op
op = {
ast.Add: op.add,
ast.Sub: op.sub,
ast.Mult: op.mul,
ast.Div: op.truediv,
ast.Pow: op.pow,
ast.BitXor: op.xor,
ast.USub: op.neg,
}
def eval_(node):
if isinstance(node, ast.Num):
return fractions.Fraction(node.n)
elif isinstance(node, ast.BinOp):
return op[type(node.op)](eval_(node.left), eval_(node.right))
elif isinstance(node, ast.UnaryOp):
return op[type(node.op)](eval_(node.operand))
raise TypeError(node)
return eval_(ast.parse(str(expr), mode='eval').body)
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 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 __init__(self, range_op=ast.BitXor):
assert range_op in [ast.BitXor, ast.BitAnd, ast.BitOr, ast.MatMult]
self.range_op = range_op
def BitXor():
return operator.xor
def _infer_bitwise(left_type, right_type, op, lineno, solver):
"""Infer the type of a bitwise operation, and add the corresponding axioms"""
result_type = solver.new_z3_const("bitwise_result")
magic_method = ""
if isinstance(op, ast.BitOr):
magic_method = "__or__"
elif isinstance(op, ast.BitXor):
magic_method = "__xor__"
elif isinstance(op, ast.BitAnd):
magic_method = "__and__"
solver.add(axioms.bitwise(left_type, right_type, result_type, magic_method, solver.z3_types),
fail_message="Bitwise operation in line {}".format(lineno))
return result_type
def binary_operation_type(left_type, op, right_type, lineno, solver):
"""Infer the type of a binary operation result"""
if isinstance(op, ast.Add):
inference_func = _infer_add
elif isinstance(op, ast.Mult):
inference_func = _infer_mult
elif isinstance(op, ast.Div):
inference_func = _infer_div
elif isinstance(op, (ast.BitOr, ast.BitXor, ast.BitAnd)):
return _infer_bitwise(left_type, right_type, op, lineno, solver)
else:
return _infer_arithmetic(left_type, right_type, op, lineno, solver)
return inference_func(left_type, right_type, lineno, solver)
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 _update(self):
"""update tkk
"""
# we don't need to update the base TKK value when it is still valid
now = math.floor(int(time.time() * 1000) / 3600000.0)
if self.tkk and int(self.tkk.split('.')[0]) == now:
return
r = self.session.get(self.host)
# this will be the same as python code after stripping out a reserved word 'var'
code = unicode(self.RE_TKK.search(r.text).group(1)).replace('var ', '')
# unescape special ascii characters such like a \x3d(=)
if PY3: # pragma: no cover
code = code.encode().decode('unicode-escape')
else: # pragma: no cover
code = code.decode('string_escape')
if code:
tree = ast.parse(code)
visit_return = False
operator = '+'
n, keys = 0, dict(a=0, b=0)
for node in ast.walk(tree):
if isinstance(node, ast.Assign):
name = node.targets[0].id
if name in keys:
if isinstance(node.value, ast.Num):
keys[name] = node.value.n
# the value can sometimes be negative
elif isinstance(node.value, ast.UnaryOp) and \
isinstance(node.value.op, ast.USub): # pragma: nocover
keys[name] = -node.value.operand.n
elif isinstance(node, ast.Return):
# parameters should be set after this point
visit_return = True
elif visit_return and isinstance(node, ast.Num):
n = node.n
elif visit_return and n > 0:
# the default operator is '+' but implement some more for
# all possible scenarios
if isinstance(node, ast.Add): # pragma: nocover
pass
elif isinstance(node, ast.Sub): # pragma: nocover
operator = '-'
elif isinstance(node, ast.Mult): # pragma: nocover
operator = '*'
elif isinstance(node, ast.Pow): # pragma: nocover
operator = '**'
elif isinstance(node, ast.BitXor): # pragma: nocover
operator = '^'
# a safety way to avoid Exceptions
clause = compile('{1}{0}{2}'.format(
operator, keys['a'], keys['b']), '', 'eval')
value = eval(clause, dict(__builtin__={}))
result = '{}.{}'.format(n, value)
self.tkk = result
def visit_BinOp(self, node):
left_term = self.visit(node.left)
right_term = self.visit(node.right)
if self.__is_bool(left_term) and self.__is_bool(right_term):
if isinstance(node.op, ast.BitAnd):
return And(left_term, right_term)
elif isinstance(node.op, ast.BitOr):
return Or(left_term, right_term)
elif isinstance(node.op, ast.BitXor):
return Xor(left_term, right_term)
else:
raise Exception("Unsupported bool binary operation %s" % unparse(node))
if DATA_TYPE == "int":
if isinstance(node.op, ast.Mod):
return left_term % right_term
elif isinstance(node.op, ast.Add):
return left_term + right_term
elif isinstance(node.op, ast.Sub):
return left_term - right_term
elif isinstance(node.op, ast.Mult):
return left_term * right_term
elif isinstance(node.op, ast.BitXor):
# Special-case for bool circuit-examples:
if is_is_int(left_term):
left_term = left_term == IntVal(1)
if is_is_int(right_term):
right_term = right_term == IntVal(1)
return left_term != right_term
else:
raise Exception("Unsupported integer binary operation %s" % unparse(node))
elif DATA_TYPE.startswith("bit_"):
if isinstance(node.op, ast.BitAnd):
return left_term & right_term
elif isinstance(node.op, ast.BitOr):
return left_term | right_term
elif isinstance(node.op, ast.BitXor):
return left_term ^ right_term
else:
raise Exception("Unsupported bitvector operation %s" % unparse(node))
else:
raise Exception("Unsupported data type %s" % DATA_TYPE)
def _update(self):
"""update tkk
"""
# we don't need to update the base TKK value when it is still valid
now = math.floor(int(time.time() * 1000) / 3600000.0)
if self.tkk and int(self.tkk.split('.')[0]) == now:
return
r = self.session.get(self.host)
# this will be the same as python code after stripping out a reserved word 'var'
code = str(self.RE_TKK.search(r.text).group(1)).replace('var ', '')
# unescape special ascii characters such like a \x3d(=)
code = code.encode().decode('unicode-escape')
if code:
tree = ast.parse(code)
visit_return = False
operator = '+'
n, keys = 0, dict(a=0, b=0)
for node in ast.walk(tree):
if isinstance(node, ast.Assign):
name = node.targets[0].id
if name in keys:
if isinstance(node.value, ast.Num):
keys[name] = node.value.n
# the value can sometimes be negative
elif isinstance(node.value, ast.UnaryOp) and \
isinstance(node.value.op, ast.USub): # pragma: nocover
keys[name] = -node.value.operand.n
elif isinstance(node, ast.Return):
# parameters should be set after this point
visit_return = True
elif visit_return and isinstance(node, ast.Num):
n = node.n
elif visit_return and n > 0:
# the default operator is '+' but implement some more for
# all possible scenarios
if isinstance(node, ast.Add): # pragma: nocover
pass
elif isinstance(node, ast.Sub): # pragma: nocover
operator = '-'
elif isinstance(node, ast.Mult): # pragma: nocover
operator = '*'
elif isinstance(node, ast.Pow): # pragma: nocover
operator = '**'
elif isinstance(node, ast.BitXor): # pragma: nocover
operator = '^'
# a safety way to avoid Exceptions
clause = compile('{1}{0}{2}'.format(
operator, keys['a'], keys['b']), '', 'eval')
value = eval(clause, dict(__builtin__={}))
result = '{}.{}'.format(n, value)
self.tkk = result
def seteval(str_, get=None, stemmer=None, target=None):
"""Evaluate a set operation string, where each Name is fetched
Parameters
----------
str_ : str
The query to evaluate
get : function, optional
A getting method, defaults to instatiating one from _requests
stemmer : function, optional
A method to stem a query Name. If None, defaults to passthrough.
target : str, optional
A subcontext to query against. If None, defaults to text-search.
"""
if get is None:
import redbiom
config = redbiom.get_config()
get = redbiom._requests.make_get(config)
if stemmer is None:
stemmer = passthrough
if target is None:
target = 'text-search'
# Load is subject to indirection to simplify testing
globals()['Load'] = make_Load(get)
# this seems right now to be the easiest way to inject parameters
# into Name
globals()['stemmer'] = stemmer
globals()['target'] = target
formed = ast.parse(str_, mode='eval')
node_types = (ast.BitAnd, ast.BitOr, ast.BitXor, ast.Name, ast.Sub,
ast.Expression, ast.BinOp, ast.Load)
for node in ast.walk(formed):
if not isinstance(node, node_types):
raise TypeError("Unsupported node type: %s" % ast.dump(node))
result = eval(ast.dump(formed))
# clean up
global Load
del Load
del stemmer
del target
return result