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类Sub()的实例源码
def eval_numeric_constexpr(node: ast.AST) -> int:
if isinstance(node, ast.Num):
return node.n
if isinstance(node, ast.UnaryOp):
if isinstance(node.op, ast.UAdd):
return +eval_numeric_constexpr(node.operand)
elif isinstance(node.op, ast.USub):
return -eval_numeric_constexpr(node.operand)
else:
return None
if isinstance(node, ast.BinOp):
if isinstance(node.op, ast.Add):
return eval_numeric_constexpr(node.left) + eval_numeric_constexpr(node.right)
if isinstance(node.op, ast.Sub):
return eval_numeric_constexpr(node.left) - eval_numeric_constexpr(node.right)
if isinstance(node.op, ast.Mult):
return eval_numeric_constexpr(node.left) * eval_numeric_constexpr(node.right)
if isinstance(node.op, ast.Div):
return eval_numeric_constexpr(node.left) / eval_numeric_constexpr(node.right)
return None
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 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 aug_assign(self):
target = self.get_target(self.stmt.target)
sub = Expr.parse_value_expr(self.stmt.value, self.context)
if not isinstance(self.stmt.op, (ast.Add, ast.Sub, ast.Mult, ast.Div, ast.Mod)):
raise Exception("Unsupported operator for augassign")
if not isinstance(target.typ, BaseType):
raise TypeMismatchException("Can only use aug-assign operators with simple types!", self.stmt.target)
if target.location == 'storage':
o = Expr.parse_value_expr(ast.BinOp(left=LLLnode.from_list(['sload', '_stloc'], typ=target.typ, pos=target.pos),
right=sub, op=self.stmt.op, lineno=self.stmt.lineno, col_offset=self.stmt.col_offset), self.context)
return LLLnode.from_list(['with', '_stloc', target, ['sstore', '_stloc', base_type_conversion(o, o.typ, target.typ)]], typ=None, pos=getpos(self.stmt))
elif target.location == 'memory':
o = Expr.parse_value_expr(ast.BinOp(left=LLLnode.from_list(['mload', '_mloc'], typ=target.typ, pos=target.pos),
right=sub, op=self.stmt.op, lineno=self.stmt.lineno, col_offset=self.stmt.col_offset), self.context)
return LLLnode.from_list(['with', '_mloc', target, ['mstore', '_mloc', base_type_conversion(o, o.typ, target.typ)]], typ=None, pos=getpos(self.stmt))
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 visit_BinOp(self, node):
if node.op.__class__ in self.operators:
sympy_class = self.operators[node.op.__class__]
right = self.visit(node.right)
if isinstance(node.op, ast.Sub):
right = ast.UnaryOp(op=ast.USub(), operand=right)
elif isinstance(node.op, ast.Div):
right = ast.Call(
func=ast.Name(id='Pow', ctx=ast.Load()),
args=[right, ast.UnaryOp(op=ast.USub(), operand=ast.Num(1))],
keywords=[ast.keyword(arg='evaluate', value=ast.Name(id='False', ctx=ast.Load()))],
starargs=None,
kwargs=None
)
new_node = ast.Call(
func=ast.Name(id=sympy_class, ctx=ast.Load()),
args=[self.visit(node.left), right],
keywords=[ast.keyword(arg='evaluate', value=ast.Name(id='False', ctx=ast.Load()))],
starargs=None,
kwargs=None
)
if sympy_class in ('Add', 'Mul'):
# Denest Add or Mul as appropriate
new_node.args = self.flatten(new_node.args, sympy_class)
return new_node
return node
def test_no_fields(self):
# this used to fail because Sub._fields was None
x = ast.Sub()
self.assertEqual(x._fields, ())
def visit_Add(self, node):
node = ast.Sub()
return node
def visit_Add(self, node):
node = ast.Sub()
return node
def test_no_fields(self):
# this used to fail because Sub._fields was None
x = ast.Sub()
self.assertEqual(x._fields, ())
def test_no_fields(self):
# this used to fail because Sub._fields was None
x = ast.Sub()
self.assertEqual(x._fields, ())
def test_no_fields(self):
# this used to fail because Sub._fields was None
x = ast.Sub()
self.assertEqual(x._fields, ())
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 get_op_string(op_class):
return {
ast.Add: '+',
ast.Sub: '-',
ast.Div: '/',
ast.Mult: '*'
}[op_class.__class__]
# For expr code
def Sub():
return operator.sub
def test_no_fields(self):
# this used to fail because Sub._fields was None
x = ast.Sub()
self.assertEqual(x._fields, ())
def test_no_fields(self):
# this used to fail because Sub._fields was None
x = ast.Sub()
self.assertEqual(x._fields, ())
def test_no_fields(self):
# this used to fail because Sub._fields was None
x = ast.Sub()
self.assertEqual(x._fields, ())
def mutate_Add(self, node):
if self.should_mutate(node):
return ast.Sub()
raise MutationResign()
def aor_mutation_on_subtraction():
return operators.Mutation(operator=operators.ArithmeticOperatorReplacement, node=ast.Sub(children=[]))
def test_generate_if_same_node(self):
node = ast.Sub()
mutations = [
self.aor_mutation(node=node),
self.aor_mutation(node=node),
]
changes_to_apply = self.apply_strategy_to_mutations_with_order_2(controller.FirstToLastHOMStrategy, mutations)
self.assert_num_changesets(changes_to_apply, 2)
self.assert_num_changeset_entries(changes_to_apply, 0, 1)
self.assert_mutation_in_changeset_at_position_equals(changes_to_apply, 0, 0, mutations[0])
self.assert_num_changeset_entries(changes_to_apply, 1, 1)
self.assert_mutation_in_changeset_at_position_equals(changes_to_apply, 1, 0, mutations[1])
def test_generate_if_node_child(self):
node = ast.Sub(children=[])
mutations = [
self.aor_mutation(node=ast.UnaryOp(children=[node])),
self.aor_mutation(node=node),
]
changes_to_apply = self.apply_strategy_to_mutations_with_order_2(controller.FirstToLastHOMStrategy, mutations)
self.assert_num_changesets(changes_to_apply, 2)
self.assert_num_changeset_entries(changes_to_apply, 0, 1)
self.assert_mutation_in_changeset_at_position_equals(changes_to_apply, 0, 0, mutations[0])
self.assert_num_changeset_entries(changes_to_apply, 1, 1)
self.assert_mutation_in_changeset_at_position_equals(changes_to_apply, 1, 0, mutations[1])
def test_generate_if_two_operators(self):
mutations = self.TWO_AOR_MUTATIONS_ON_SUBTRACTION + [self.asr_mutation(node=ast.Sub(children=[]))]
changes_to_apply = self.apply_strategy_to_mutations_with_order_2(controller.BetweenOperatorsHOMStrategy,
mutations)
self.assert_num_changesets(changes_to_apply, 2)
self.assert_num_changeset_entries(changes_to_apply, 0, 2)
self.assert_mutation_in_changeset_at_position_equals(changes_to_apply, 0, 0, mutations[0])
self.assert_mutation_in_changeset_at_position_equals(changes_to_apply, 0, 1, mutations[2])
self.assert_num_changeset_entries(changes_to_apply, 1, 2)
self.assert_mutation_in_changeset_at_position_equals(changes_to_apply, 1, 0, mutations[1])
self.assert_mutation_in_changeset_at_position_equals(changes_to_apply, 1, 1, mutations[2])
def test_no_fields(self):
# this used to fail because Sub._fields was None
x = ast.Sub()
self.assertEqual(x._fields, ())
def pythonast(self, args, tonative=False):
return ast.BinOp(args[0], ast.Sub(), args[1])
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 safe_eval(node_or_string, env):
"""
Safely evaluate an expression node or a string containing a Python
expression. The string or node provided may only consist of the following
Python literal structures: strings, numbers, tuples, lists, dicts, booleans,
and None.
"""
_safe_names = {'None': None, 'True': True, 'False': False}
_safe_names.update(env)
if isinstance(node_or_string, basestring):
node_or_string = ast.parse(node_or_string, mode='eval')
if isinstance(node_or_string, ast.Expression):
node_or_string = node_or_string.body
def _convert(node):
if isinstance(node, ast.Str):
return node.s
elif isinstance(node, ast.Num):
return node.n
elif isinstance(node, ast.Tuple):
return tuple(map(_convert, node.elts))
elif isinstance(node, ast.List):
return list(map(_convert, node.elts))
elif isinstance(node, ast.Dict):
return dict((_convert(k), _convert(v)) for k, v
in zip(node.keys, node.values))
elif isinstance(node, ast.Name):
if node.id in _safe_names:
return _safe_names[node.id]
elif isinstance(node, ast.BinOp) and \
isinstance(node.op, (ast.Add, ast.Sub)) and \
isinstance(node.right, ast.Num) and \
isinstance(node.right.n, complex) and \
isinstance(node.left, ast.Num) and \
isinstance(node.left.n, (int, long, float)):
left = node.left.n
right = node.right.n
if isinstance(node.op, ast.Add):
return left + right
else:
return left - right
raise ValueError('malformed string')
return _convert(node_or_string)
def parse_call_args(defnode, array_var, call_args, prev_dimensions):
"""
try split call_args into multiple dimensions
"""
if isinstance(py_ast.get_ast(call_args).body[0].value, (ast.List, ast.Tuple)):
call_args = call_args[1 : -1]
dimensions = call_args.split(',')
for i in range(len(dimensions)):
dimension = dimensions[i]
try:
d_node = py_ast.get_ast(dimension.strip()).body[0].value
if isinstance(d_node, ast.BinOp):
if isinstance(d_node.op, (ast.Add, ast.Sub)):
if isinstance(d_node.left, ast.Num) and not isinstance(d_node.right, ast.Num):
dimensions[i] = py_ast.dump_ast(d_node.right)
elif isinstance(d_node.right, ast.Num) and not isinstance(d_node.left, ast.Num):
dimensions[i] = py_ast.dump_ast(d_node.left)
else:
dimensions[i] = py_ast.dump_ast(d_node)
else:
dimensions[i] = py_ast.dump_ast(d_node)
else:
dimensions[i] = py_ast.dump_ast(d_node)
except:
pass
prev_dimensions.append(dimensions)
else:
arg_node = py_ast.get_ast(call_args).body[0].value
if isinstance(arg_node, ast.Attribute):
if arg_node.attr == 'shape':
arg_shape_var = py_ast.dump_ast(arg_node.value)
try:
(shape_assignnode, shape_call_args, shape_assign_funcname) = preallocate_find_assignnode_py_ast(defnode, defnode.name, arg_shape_var)
prev_dimensions.append([call_args])
prev_dimensions = parse_call_args(defnode, arg_shape_var, shape_call_args, prev_dimensions)
except PreallocateNotFound:
dimensions = [call_args]
prev_dimensions.append(dimensions)
else:
dimensions = [call_args]
prev_dimensions.append(dimensions)
return prev_dimensions