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类Pow()的实例源码
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 visit_AugAssign(self, node):
"""
AugAssign(expr target, operator op, expr value)
"""
# TODO: Make sure that all the logic in Assign also works in AugAssign
target = self.visit(node.target)
value = self.visit(node.value)
if isinstance(node.op, ast.Pow):
self.write("%s = %s ** %s" % (target, target, value))
#elif isinstance(node.op, ast.FloorDiv):
# #self.write("%s = Math.floor((%s)/(%s));" % (target, target, value))
# self.write("%s = (%s/%s)" % (target, target, value))
elif isinstance(node.op, ast.Div):
if re.search(r"Numo::", target) or re.search(r"Numo::", value):
self.write("%s = (%s)/(%s)" % (target, target, value))
else:
self.write("%s = (%s)/(%s).to_f" % (target, target, value))
else:
self.write("%s %s= %s" % (target, self.get_binary_op(node), value))
def visit_BinOp(self, node):
if isinstance(node.op, ast.Mod) and isinstance(node.left, ast.Str):
left = self.visit(node.left)
# 'b=%(b)0d and c=%(c)d and d=%(d)d' => 'b=%<b>0d and c=%<c>d and d=%<d>d'
left = re.sub(r"(.+?%)\((.+?)\)(.+?)", r"\1<\2>\3", left)
self._dict_format = True
right = self.visit(node.right)
self._dict_format = False
return "%s %% %s" % (left, right)
left = self.visit(node.left)
right = self.visit(node.right)
if isinstance(node.op, ast.Pow):
return "%s ** %s" % (left, right)
if isinstance(node.op, ast.Div):
if re.search(r"Numo::", left) or re.search(r"Numo::", right):
return "(%s)/(%s)" % (left, right)
else:
return "(%s)/(%s).to_f" % (left, right)
return "(%s)%s(%s)" % (left, self.get_binary_op(node), right)
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 parse_unit(item):
if isinstance(item, ast.Name):
if item.id not in valid_units:
raise InvalidTypeException("Invalid base unit", item)
return {item.id: 1}
elif isinstance(item, ast.Num) and item.n == 1:
return {}
elif not isinstance(item, ast.BinOp):
raise InvalidTypeException("Invalid unit expression", item)
elif isinstance(item.op, ast.Mult):
left, right = parse_unit(item.left), parse_unit(item.right)
return combine_units(left, right)
elif isinstance(item.op, ast.Div):
left, right = parse_unit(item.left), parse_unit(item.right)
return combine_units(left, right, div=True)
elif isinstance(item.op, ast.Pow):
if not isinstance(item.left, ast.Name):
raise InvalidTypeException("Can only raise a base type to an exponent", item)
if not isinstance(item.right, ast.Num) or not isinstance(item.right.n, int) or item.right.n <= 0:
raise InvalidTypeException("Exponent must be positive integer", item)
return {item.left.id: item.right.n}
else:
raise InvalidTypeException("Invalid unit expression", item)
# Parses an expression representing a type. Annotation refers to whether
# the type is to be located in memory or storage
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_AugAssign(self, node):
if node.op.__class__ != ast.Pow:
return node
dummy_math = ast.Name(id="math", ctx=ast.Load())
dummy_func = ast.Attribute(value=dummy_math, attr="pow", ctx=ast.Load())
dummy_call = ast.Call(func=dummy_func, args=[node.target, node.value], keywords=[], starargs=None, kwargs=None)
return ast.Assign(targets=[node.target], value=dummy_call)
def visit_BinOp(self, node):
if node.op.__class__ != ast.Pow:
return node
# math.pow
dummy_math = ast.Name(id="math", ctx=ast.Load())
dummy_func = ast.Attribute(value=dummy_math, attr="pow", ctx=ast.Load())
return ast.Call(func=dummy_func, args=[node.left, node.right], keywords=[], starargs=None, kwargs=None)
def visit_AugAssign(self, node):
assert node.op.__class__ not in [ast.Pow, ast.FloorDiv]
target = self.visit(node.target)
op = OPERATOR_MAP[node.op.__class__]
value = self.visit(node.value)
return cpp.AugAssign(target, op, value)
def visit_BinOp(self, node):
assert node.op.__class__ not in [ast.Pow, ast.FloorDiv]
left = self.visit(node.left)
op = OPERATOR_MAP[node.op.__class__]
right = self.visit(node.right)
return cpp.BinOp(left=left, op=op, right=right)
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_pow(self):
self.check_optimize_func("2 ** 3", "8")
self.check_optimize_func("2.0 ** 3.0", "8.0")
# complex
self.check_dont_optimize_func("2.0j ** 3.0")
self.check_dont_optimize_func("2.0 ** 3.0j")
# 0 ** -1
self.check_dont_optimize_func("0 ** -1",
ast.BinOp(left=ast.Num(n=0), op=ast.Pow(), right=ast.Num(-1)))
self.check_dont_optimize_func("0.0 ** -1",
ast.BinOp(left=ast.Num(n=0.0), op=ast.Pow(), right=ast.Num(-1)))
def preprocess_input_python(s):
rootnode = py_ast.get_ast(s)
rootnode = add_str_node(rootnode)
for node in py_ast.find_all(rootnode, ast.BinOp):
if isinstance(node.op, ast.Pow):
if not py_ast.is_int_constant_py_ast(py_ast.dump_ast(node.right)):
new_str = 'pow(' + py_ast.dump_ast(node.left) + ', ' + py_ast.dump_ast(node.right) + ')'
new_node = py_ast.get_ast(new_str).body[0].value
py_ast.replace_node(rootnode, node, new_node)
for node in py_ast.find_all(rootnode, ast.Call):
if isinstance(node.func, ast.Attribute):
if isinstance(node.func.value, ast.Name) and node.func.attr in ['floow', 'ceil']:
if node.func.value.id == 'math':
py_ast.replace_node(node, node.func.value, py_ast.get_ast('numpy').body[0].value)
ans = py_ast.dump_ast(rootnode)
ans = 'import numpy\n' + ans
lines = ans.split('\n')
i = 0
while i < len(lines):
line = lines[i]
if line.startswith('#'):
j = i + 1
while j < len(lines) and lines[j].strip() == '':
del lines[j]
i += 1
ans = '\n'.join(lines)
return ans
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_Mult_to_Pow(self, node):
if self.should_mutate(node):
return ast.Pow()
raise MutationResign()
def pythonast(self, args, tonative=False):
return ast.BinOp(args[0], ast.Pow(), args[1])
def BinOp_pow(t, x):
if isinstance(x.op, ast.Pow):
return JSCall(
JSAttribute(
JSName('Math'),
'pow'),
[x.left, x.right])
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 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
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 visit_BinOp(self, node):
if node.op.__class__ in self.operators:
sympy_class = self.operators[node.op.__class__]
right = self.visit(node.right)
left = self.visit(node.left)
if isinstance(node.left, ast.UnaryOp) and (isinstance(node.right, ast.UnaryOp) == 0) and sympy_class in ('Mul',):
left, right = right, left
if isinstance(node.op, ast.Sub):
right = ast.UnaryOp(op=ast.USub(), operand=right)
if isinstance(node.op, ast.Div):
if isinstance(node.left, ast.UnaryOp):
if isinstance(node.right,ast.UnaryOp):
left, right = right, left
left = ast.Call(
func=ast.Name(id='Pow', ctx=ast.Load()),
args=[left, 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
)
else:
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=[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 _aslimit(value, lc):
if isinstance(value, string_types):
module = ast.parse(value)
if isinstance(module, ast.Module) and len(module.body) == 1 and isinstance(module.body[0], ast.Expr):
def restrictedeval(expr):
if isinstance(expr, ast.Num):
return expr.n
elif isinstance(expr, ast.Name) and expr.id == "inf":
return femtocode.typesystem.inf
elif isinstance(expr, ast.Name) and expr.id == "pi":
return math.pi
elif isinstance(expr, ast.UnaryOp) and isinstance(expr.op, ast.USub):
return -restrictedeval(expr.operand)
elif isinstance(expr, ast.BinOp) and isinstance(expr.op, ast.Add):
return restrictedeval(expr.left) + restrictedeval(expr.right)
elif isinstance(expr, ast.BinOp) and isinstance(expr.op, ast.Sub):
return restrictedeval(expr.left) - restrictedeval(expr.right)
elif isinstance(expr, ast.BinOp) and isinstance(expr.op, ast.Mult):
return restrictedeval(expr.left) * restrictedeval(expr.right)
elif isinstance(expr, ast.BinOp) and isinstance(expr.op, ast.Div):
return restrictedeval(expr.left) / restrictedeval(expr.right)
elif isinstance(expr, ast.BinOp) and isinstance(expr.op, ast.Pow):
return restrictedeval(expr.left) ** restrictedeval(expr.right)
elif isinstance(expr, ast.Call) and isinstance(expr.func, ast.Name) and expr.func.id == "almost" and len(expr.args) == 1 and len(expr.keywords) == 0 and expr.kwargs is None and expr.starargs is None:
return femtocode.typesystem.almost(restrictedeval(expr.args[0]))
else:
raise DatasetDeclaration.Error(lc, "couldn't parse as a min/max/least/most limit: {0}".format(value))
return restrictedeval(module.body[0].value)
elif isinstance(value, (int, long, float)):
return value
elif isinstance(value, femtocode.typesystem.almost) and isinstance(value.real, (int, long, float)):
return value
else:
raise DatasetDeclaration.Error(lc, "unrecognized type for min/max/least/most limit: {0}".format(value))