def visit_BinOp(self, node):
node = self.generic_visit(node)
left = node.left
right = node.right
if all(isinstance(value, ast.Num) for value in (left, right)):
if isinstance(node.op, tuple(self._operators.keys())):
val = self._operators[type(node.op)](left.n, right.n)
node = ast.copy_location(ast.Num(n = val), node)
return node
elif all(isinstance(value, ast.Str) for value in (left, right)):
if isinstance(node.op, ast.Add):
val = left.s + right.s
node = ast.copy_location(ast.Str(s = val), node)
return node
return self.fold(node)
#def visit_GeneratorExp(self, node):
# return self.comprehension(node)
python类Add()的实例源码
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
def test_increment_lineno(self):
src = ast.parse('1 + 1', mode='eval')
self.assertEqual(ast.increment_lineno(src, n=3), src)
self.assertEqual(ast.dump(src, include_attributes=True),
'Expression(body=BinOp(left=Num(n=1, lineno=4, col_offset=0), '
'op=Add(), right=Num(n=1, lineno=4, col_offset=4), lineno=4, '
'col_offset=0))'
)
# issue10869: do not increment lineno of root twice
src = ast.parse('1 + 1', mode='eval')
self.assertEqual(ast.increment_lineno(src.body, n=3), src.body)
self.assertEqual(ast.dump(src, include_attributes=True),
'Expression(body=BinOp(left=Num(n=1, lineno=4, col_offset=0), '
'op=Add(), right=Num(n=1, lineno=4, col_offset=4), lineno=4, '
'col_offset=0))'
)
def _generate_binop(self, node, ext_info):
left_type = self.get_type(node.left)
right_type = self.get_type(node.right)
extra_code = ext_info.get('extra_code', '')
if left_type.is_void or right_type.is_void:
raise CompileError('Void type is not able to operate.')
if left_type.is_number and right_type.is_number:
op = self.generate_numeric_op(node.op, ext_info)
if len(op) is 0:
raise SyntaxNotSupportError("%s operation is not support yet." % node.op.__class__.__name__)
left_name, extra_code = get_node_name_with_extra_code(self, node.left, extra_code)
right_name, extra_code = get_node_name_with_extra_code(self, node.right, extra_code)
return '$(( %s %s %s ))' % (left_name, op, right_name), extra_code
elif (left_type.is_string or right_type.is_string) and isinstance(node.op, ast.Add):
_ext_info = {'extra_code': extra_code}
left = self.dispatch(node.left, _ext_info)
right = self.dispatch(node.right, _ext_info)
return left + right, _ext_info['extra_code']
else:
raise SyntaxNotSupportError("%s operation is not support yet." % node.op.__class__.__name__)
def test_increment_lineno(self):
src = ast.parse('1 + 1', mode='eval')
self.assertEqual(ast.increment_lineno(src, n=3), src)
self.assertEqual(ast.dump(src, include_attributes=True),
'Expression(body=BinOp(left=Num(n=1, lineno=4, col_offset=0), '
'op=Add(), right=Num(n=1, lineno=4, col_offset=4), lineno=4, '
'col_offset=0))'
)
# issue10869: do not increment lineno of root twice
src = ast.parse('1 + 1', mode='eval')
self.assertEqual(ast.increment_lineno(src.body, n=3), src.body)
self.assertEqual(ast.dump(src, include_attributes=True),
'Expression(body=BinOp(left=Num(n=1, lineno=4, col_offset=0), '
'op=Add(), right=Num(n=1, lineno=4, col_offset=4), lineno=4, '
'col_offset=0))'
)
def test_increment_lineno(self):
src = ast.parse('1 + 1', mode='eval')
self.assertEqual(ast.increment_lineno(src, n=3), src)
self.assertEqual(ast.dump(src, include_attributes=True),
'Expression(body=BinOp(left=Num(n=1, lineno=4, col_offset=0), '
'op=Add(), right=Num(n=1, lineno=4, col_offset=4), lineno=4, '
'col_offset=0))'
)
# issue10869: do not increment lineno of root twice
src = ast.parse('1 + 1', mode='eval')
self.assertEqual(ast.increment_lineno(src.body, n=3), src.body)
self.assertEqual(ast.dump(src, include_attributes=True),
'Expression(body=BinOp(left=Num(n=1, lineno=4, col_offset=0), '
'op=Add(), right=Num(n=1, lineno=4, col_offset=4), lineno=4, '
'col_offset=0))'
)
def test_increment_lineno(self):
src = ast.parse('1 + 1', mode='eval')
self.assertEqual(ast.increment_lineno(src, n=3), src)
self.assertEqual(ast.dump(src, include_attributes=True),
'Expression(body=BinOp(left=Num(n=1, lineno=4, col_offset=0), '
'op=Add(), right=Num(n=1, lineno=4, col_offset=4), lineno=4, '
'col_offset=0))'
)
# issue10869: do not increment lineno of root twice
src = ast.parse('1 + 1', mode='eval')
self.assertEqual(ast.increment_lineno(src.body, n=3), src.body)
self.assertEqual(ast.dump(src, include_attributes=True),
'Expression(body=BinOp(left=Num(n=1, lineno=4, col_offset=0), '
'op=Add(), right=Num(n=1, lineno=4, col_offset=4), lineno=4, '
'col_offset=0))'
)
def add_line_info(root_node):
"""
Add lineno attribute for all nodes at and under root_node, recursively.
"""
class AddLineNumbers(BottomUpVisitor):
def __init__(self):
BottomUpVisitor.__init__(self, strict_line_order=True, make_unique=True)
def visit_one_node(self, node, lineno=None):
# print(node, lineno, getattr(node, 'lineno', None))
if not hasattr(node, 'lineno'):
node.lineno = lineno
else:
if node.lineno != lineno:
print(node, lineno, node.lineno)
print(astor.dump(root_node))
assert False
BottomUpVisitor.visit_one_node(self, node, lineno)
AddLineNumbers().visit(root_node)
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 test_increment_lineno(self):
src = ast.parse('1 + 1', mode='eval')
self.assertEqual(ast.increment_lineno(src, n=3), src)
self.assertEqual(ast.dump(src, include_attributes=True),
'Expression(body=BinOp(left=Num(n=1, lineno=4, col_offset=0), '
'op=Add(), right=Num(n=1, lineno=4, col_offset=4), lineno=4, '
'col_offset=0))'
)
# issue10869: do not increment lineno of root twice
src = ast.parse('1 + 1', mode='eval')
self.assertEqual(ast.increment_lineno(src.body, n=3), src.body)
self.assertEqual(ast.dump(src, include_attributes=True),
'Expression(body=BinOp(left=Num(n=1, lineno=4, col_offset=0), '
'op=Add(), right=Num(n=1, lineno=4, col_offset=4), lineno=4, '
'col_offset=0))'
)
def test_increment_lineno(self):
src = ast.parse('1 + 1', mode='eval')
self.assertEqual(ast.increment_lineno(src, n=3), src)
self.assertEqual(ast.dump(src, include_attributes=True),
'Expression(body=BinOp(left=Num(n=1, lineno=4, col_offset=0), '
'op=Add(), right=Num(n=1, lineno=4, col_offset=4), lineno=4, '
'col_offset=0))'
)
# issue10869: do not increment lineno of root twice
src = ast.parse('1 + 1', mode='eval')
self.assertEqual(ast.increment_lineno(src.body, n=3), src.body)
self.assertEqual(ast.dump(src, include_attributes=True),
'Expression(body=BinOp(left=Num(n=1, lineno=4, col_offset=0), '
'op=Add(), right=Num(n=1, lineno=4, col_offset=4), lineno=4, '
'col_offset=0))'
)
def test_increment_lineno(self):
src = ast.parse('1 + 1', mode='eval')
self.assertEqual(ast.increment_lineno(src, n=3), src)
self.assertEqual(ast.dump(src, include_attributes=True),
'Expression(body=BinOp(left=Num(n=1, lineno=4, col_offset=0), '
'op=Add(), right=Num(n=1, lineno=4, col_offset=4), lineno=4, '
'col_offset=0))'
)
# issue10869: do not increment lineno of root twice
src = ast.parse('1 + 1', mode='eval')
self.assertEqual(ast.increment_lineno(src.body, n=3), src.body)
self.assertEqual(ast.dump(src, include_attributes=True),
'Expression(body=BinOp(left=Num(n=1, lineno=4, col_offset=0), '
'op=Add(), right=Num(n=1, lineno=4, col_offset=4), lineno=4, '
'col_offset=0))'
)
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 visit_Assert(self, node):
"""Replace assertions with augmented assignments."""
self.max_score += 1
return ast.AugAssign(
op=ast.Add(),
target=ast.Name(
id=self.score_var_name,
ctx=ast.Store()
),
value=ast.Call(
args=[node.test],
func=ast.Name(
id='bool',
ctx=ast.Load()
),
keywords=[],
kwargs=None,
starargs=None
)
)
def test_increment_lineno(self):
src = ast.parse('1 + 1', mode='eval')
self.assertEqual(ast.increment_lineno(src, n=3), src)
self.assertEqual(ast.dump(src, include_attributes=True),
'Expression(body=BinOp(left=Num(n=1, lineno=4, col_offset=0), '
'op=Add(), right=Num(n=1, lineno=4, col_offset=4), lineno=4, '
'col_offset=0))'
)
# issue10869: do not increment lineno of root twice
src = ast.parse('1 + 1', mode='eval')
self.assertEqual(ast.increment_lineno(src.body, n=3), src.body)
self.assertEqual(ast.dump(src, include_attributes=True),
'Expression(body=BinOp(left=Num(n=1, lineno=4, col_offset=0), '
'op=Add(), right=Num(n=1, lineno=4, col_offset=4), lineno=4, '
'col_offset=0))'
)
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 add_error(self, node, message=None):
"""Add an error caused by a node to the list of errors for pep8."""
message = message or self.CHECK_DESC
error = (node.lineno, node.col_offset, message, self.__class__)
self._errors.append(error)
def visit_BinOp(self, node):
if isinstance(node.op, ast.Add):
if self._check_call_names(node.left, self.TRANS_FUNC):
self.add_error(node.left)
elif self._check_call_names(node.right, self.TRANS_FUNC):
self.add_error(node.right)
super(CheckForTransAdd, self).generic_visit(node)
def listNotEmpty(a):
"""Determines that the iterable is NOT empty, if we can know that"""
"""Used for For objects"""
if not isinstance(a, ast.AST):
return False
if type(a) == ast.Call:
if type(a.func) == ast.Name and a.func.id in ["range"]:
if len(a.args) == 1: # range(x)
return type(a.args[0]) == ast.Num and type(a.args[0].n) != complex and a.args[0].n > 0
elif len(a.args) == 2: # range(start, x)
if type(a.args[0]) == ast.Num and type(a.args[1]) == ast.Num and \
type(a.args[0].n) != complex and type(a.args[1].n) != complex and \
a.args[0].n < a.args[1].n:
return True
elif type(a.args[1]) == ast.BinOp and type(a.args[1].op) == ast.Add:
if type(a.args[1].right) == ast.Num and type(a.args[1].right) != complex and a.args[1].right.n > 0 and \
compareASTs(a.args[0], a.args[1].left, checkEquality=True) == 0:
return True
elif type(a.args[1].left) == ast.Num and type(a.args[1].left) != complex and a.args[1].left.n > 0 and \
compareASTs(a.args[0], a.args[1].right, checkEquality=True) == 0:
return True
elif type(a) in [ast.List, ast.Tuple]:
return len(a.elts) > 0
elif type(a) == ast.Str:
return len(a.s) > 0
return False
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_copy_location(self):
src = ast.parse('1 + 1', mode='eval')
src.body.right = ast.copy_location(ast.Num(2), src.body.right)
self.assertEqual(ast.dump(src, include_attributes=True),
'Expression(body=BinOp(left=Num(n=1, lineno=1, col_offset=0), '
'op=Add(), right=Num(n=2, lineno=1, col_offset=4), lineno=1, '
'col_offset=0))'
)
def generate_aug_assign(self, node, ext_info):
tmp_name = self.temp_variable.get_new_name()
tmp_assign_code = '%s=%s' % (
tmp_name,
self.dispatch(node.value)
)
self.code_buffer.append(tmp_assign_code)
target = self.dispatch(node.target)
target_type = self.get_type(node.target)
if target_type.is_number:
op = self.generate_numeric_op(node.op, ext_info)
return '%s=$(( $%s %s $%s ))'% (
target,
target,
op,
tmp_name
)
elif target_type.is_string:
if isinstance(node.op, ast.Add):
return '%s=%s$%s'% (
target,
target,
tmp_name
)
else:
raise SyntaxNotSupportError(
"%s operation is not support yet."
% node.op.__class__.__name__
)
def get_type(self, node):
if isinstance(node, ast.BinOp):
left_type = self.get_type(node.left)
right_type = self.get_type(node.right)
if isinstance(node.op, ast.Add):
if left_type.is_number and right_type.is_number:
return Type.NUMBER
else:
return Type.STRING
elif left_type.is_number and right_type.is_number:
return Type.NUMBER
else:
raise CompileError("Can not '%s' operator with string." % node.op.__class__.__name__)
elif isinstance(node, ast.UnaryOp):
if isinstance(operand, ast.Num):
return Type.NUMBER
else:
raise SyntaxNotSupportError("Not support unary operator except number.")
elif isinstance(node, ast.Num):
return Type.NUMBER
elif isinstance(node, ast.Str):
return Type.STRING
elif isinstance(node, ast.List):
return Type.LIST
elif isinstance(node, ast.Call):
args_type = [self.get_type(arg) for arg in node.args]
return self.get_function_return_type(node.func.id, args_type)
elif isinstance(node, ast.Name):
return self.variables[node.id].var_type
def test_copy_location(self):
src = ast.parse('1 + 1', mode='eval')
src.body.right = ast.copy_location(ast.Num(2), src.body.right)
self.assertEqual(ast.dump(src, include_attributes=True),
'Expression(body=BinOp(left=Num(n=1, lineno=1, col_offset=0), '
'op=Add(), right=Num(n=2, lineno=1, col_offset=4), lineno=1, '
'col_offset=0))'
)
def test_copy_location(self):
src = ast.parse('1 + 1', mode='eval')
src.body.right = ast.copy_location(ast.Num(2), src.body.right)
self.assertEqual(ast.dump(src, include_attributes=True),
'Expression(body=BinOp(left=Num(n=1, lineno=1, col_offset=0), '
'op=Add(), right=Num(n=2, lineno=1, col_offset=4), lineno=1, '
'col_offset=0))'
)
def test_copy_location(self):
src = ast.parse('1 + 1', mode='eval')
src.body.right = ast.copy_location(ast.Num(2), src.body.right)
self.assertEqual(ast.dump(src, include_attributes=True),
'Expression(body=BinOp(left=Num(n=1, lineno=1, col_offset=0), '
'op=Add(), right=Num(n=2, lineno=1, col_offset=4), lineno=1, '
'col_offset=0))'
)
def test_augassign(self):
aug = ast.AugAssign(ast.Name("x", ast.Load()), ast.Add(),
ast.Name("y", ast.Load()))
self.stmt(aug, "must have Store context")
aug = ast.AugAssign(ast.Name("x", ast.Store()), ast.Add(),
ast.Name("y", ast.Store()))
self.stmt(aug, "must have Load context")
def chosen_typespec_dumps(typeconfig):
"""
Add a comment about the chosen type specialization that was used for a given function.
"""
ans = chosen_typespec + repr(typeconfig) + '\n'
if typeconfig is not None and verbose:
print('chosen_typespec_dumps:', ans)
print('chosen_typespec_dumps, checking')
for value in typeconfig.values():
print('chosen_typespec_dumps, check', type(value), repr(value))
# value.check()
return ans