def _is_numeric_pow(self, node: ast.BinOp) -> bool:
if isinstance(node.op, ast.Pow):
left, right = node.left, node.right
if isinstance(left, (ast.Name, ast.Num)):
if isinstance(right, ast.Num):
degree = right.n
elif isinstance(right, ast.UnaryOp)\
and isinstance(right.op, (ast.USub, ast.UAdd))\
and isinstance(right.operand, ast.Num):
degree = right.operand.n
else:
return False
if isinstance(degree, float):
degree = int(degree) if degree.is_integer() else degree
return isinstance(degree, int)
return False
python类USub()的实例源码
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 _UnaryOp(self, t):
self.write("(")
self.write(self.unop[t.op.__class__.__name__])
self.write(" ")
# If we're applying unary minus to a number, parenthesize the number.
# This is necessary: -2147483648 is different from -(2147483648) on
# a 32-bit machine (the first is an int, the second a long), and
# -7j is different from -(7j). (The first has real part 0.0, the second
# has real part -0.0.)
if isinstance(t.op, ast.USub) and isinstance(t.operand, ast.Num):
self.write("(")
self.dispatch(t.operand)
self.write(")")
else:
self.dispatch(t.operand)
self.write(")")
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 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_Num(self, t):
# -0.0 is distinct from +0.0, but my compiler would mistakenly
# coalesce the two, if both appear among the constants. Likewise
# for -0.0 as a component of a complex number. As a hack, instead
# of handling this case correctly in the compiler, we just forbid
# it. It's especially unlikely to crop up because the parser even
# parses -0.0 as UnaryOp(op=USub(), operand=Num(0.0)) -- you'd
# have to build the AST some other way, to get Num(-0.0).
assert not has_negzero(t.n), "Negative-zero literals not supported: %r" % (t,)
def resolve_negative_literals(_ast):
class RewriteUnaryOp(ast.NodeTransformer):
def visit_UnaryOp(self, node):
if isinstance(node.op, ast.USub) and isinstance(node.operand, ast.Num):
node.operand.n = 0 - node.operand.n
return node.operand
else:
return node
return RewriteUnaryOp().visit(_ast)
# Make a getter for a variable. This function gives an output that
# contains lists of 4-tuples:
# (i) the tail of the function name for the getter
# (ii) the code for the arguments that the function takes
# (iii) the code for the return
# (iv) the output type
#
# Here is an example:
#
# Input: my_variable: {foo: num, bar: decimal[5]}
#
# Output:
#
# [('__foo', '', '.foo', 'num'),
# ('__bar', 'arg0: num, ', '.bar[arg0]', 'decimal')]
#
# The getters will have code:
# def get_my_variable__foo() -> num: return self.foo
# def get_my_variable__bar(arg0: nun) -> decimal: return self.bar[arg0]
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_BinOp(self, node: ast.BinOp):
node = self.generic_visit(node)
if self._is_numeric_pow(node):
left, right = node.left, node.right
degree = ( right.n if isinstance(right, ast.Num)
else -right.operand.n if isinstance(right.op, ast.USub)
else right.operand.n )
degree = int(degree)
if abs(degree) == 0:
node = ast.copy_location(ast.Num(n = 1), node)
elif abs(degree) == 1:
node = node.left
elif 2 <= abs(degree) <= self.MAX_DEGREE:
for _ in range(1, abs(degree)):
new_node = ast.BinOp\
( left = left
, op = ast.Mult()
, right = copy(node.left)
)
left = new_node = ast.copy_location(new_node, node)
node = new_node
else:
return node
if degree < 0:
new_node = ast.BinOp\
( left = ast.Num(n = 1)
, op = ast.Div()
, right = node
)
node = ast.copy_location(new_node, node)
return node
def turnPositive(a):
"""Take a negative number and make it positive"""
if type(a) == ast.UnaryOp and type(a.op) == ast.USub:
return a.operand
elif type(a) == ast.Num and type(a.n) != complex and a.n < 0:
a.n = a.n * -1
return a
else:
log("transformations\tturnPositive\tFailure: " + str(a), "bug")
return a
def isNegative(a):
"""Is the give number negative?"""
if type(a) == ast.UnaryOp and type(a.op) == ast.USub:
return True
elif type(a) == ast.Num and type(a.n) != complex and a.n < 0:
return True
else:
return False
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 visitUnaryOp(self, node):
import ast
if isinstance(node.op, ast.UAdd):
return +self.visit(node.operand)
elif isinstance(node.op, ast.USub):
return -self.visit(node.operand)
else:
raise SyntaxError("Unknown unary op: %r" % node.op)
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 visitUnaryOp(self, node):
import ast
if isinstance(node.op, ast.UAdd):
return +self.visit(node.operand)
elif isinstance(node.op, ast.USub):
return -self.visit(node.operand)
else:
raise SyntaxError("Unknown unary op: %r" % node.op)
def _get_constant(node, *, types=None):
if isinstance(node, ast.Constant):
return node.value
if isinstance(node, ast.UnaryOp) and isinstance(node.op, ast.USub):
# FIXME: rely on constant folding for that!
value = get_constant(node.operand, types=types)
if value is UNSET:
return UNSET
return (-value)
return UNSET
pytables.py 文件源码
项目:PyDataLondon29-EmbarrassinglyParallelDAWithAWSLambda
作者: SignalMedia
项目源码
文件源码
阅读 24
收藏 0
点赞 0
评论 0
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 is_int_constant_py_ast(s):
"""
py_ast version on is_int_constant in redbaron_util.py
"""
s = s.strip()
rootnode = get_ast(s).body
if len(rootnode) == 1 and isinstance(rootnode[0], ast.Expr):
node = rootnode[0].value
if isinstance(node, ast.UnaryOp):
if isinstance(node.op, (ast.USub, ast.UAdd)):
return isinstance(node.operand, ast.Num)
else:
return isinstance(node, ast.Num)
return False
def TO_INT(node: ast) -> (bool, int):
if isinstance(node, ast.Num):
return (True, node.n)
if isinstance(node, ast.UnaryOp) and isinstance(node.operand, ast.Num):
if isinstance(node.op, ast.UAdd):
return (True, +node.operand.n)
if isinstance(node.op, ast.USub):
return (True, -node.operand.n)
error(loc(node), "Expected +/- Num")
return (False, 0)
error(loc(node), "Expected signed integer")
return (False, 0)
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 visitUnaryOp(self, node):
import ast
if isinstance(node.op, ast.UAdd):
return +self.visit(node.operand)
elif isinstance(node.op, ast.USub):
return -self.visit(node.operand)
else:
raise SyntaxError("Unknown unary op: %r" % node.op)
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 visitUnaryOp(self, node):
import ast
if isinstance(node.op, ast.UAdd):
return +self.visit(node.operand)
elif isinstance(node.op, ast.USub):
return -self.visit(node.operand)
else:
raise SyntaxError("Unknown unary op: %r" % node.op)
def visitUnaryOp(self, node):
import ast
if isinstance(node.op, ast.UAdd):
return +self.visit(node.operand)
elif isinstance(node.op, ast.USub):
return -self.visit(node.operand)
else:
raise SyntaxError("Unknown unary op: %r" % node.op)
def mutate_UAdd(self, node):
return ast.USub()
def Subscript_default(t, x):
assert isinstance(x.slice, ast.Index)
v = x.slice.value
if isinstance(v, ast.UnaryOp) and isinstance(v.op, ast.USub):
return JSSubscript(
JSCall(JSAttribute(x.value, 'slice'), [v]),
JSNum(0))
return JSSubscript(x.value, v)
def USub(t, x):
"Handles tokens like '-1'"
return JSOpUSub()
def ana_Unary_Name_constructor(self, ctx, e):
id = e.operand.id
if id != "Inf":
raise _errors.TyError("Invalid ieee literal.", e)
if not isinstance(e.op, (ast.UAdd, ast.USub)):
raise _errors.TyError("Invalid unary operator on ieee literal.", e)
def syn_idx_Unary_Name_constructor(cls, ctx, e, inc_idx):
id = e.operand.id
if id != "Inf":
raise _errors.TyError("Invalid ieee literal.", e)
if not isinstance(e.op, (ast.UAdd, ast.USub)):
raise _errors.TyError("Invalid unary operator on ieee literal.", e)
return ()