Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def visit_Slice(self, node):
"""
Set slicing type using continuous information if provided.
Also visit subnodes as they may contains relevant typing information.
"""
self.generic_visit(node)
if node.step is None or (isnum(node.step) and node.step.value == 1):
self.result[node] = self.builder.NamedType(
'pythonic::types::contiguous_slice')
else:
self.result[node] = self.builder.NamedType(
'pythonic::types::slice')
def visit_If(self, node):
test = self.visit(node.test)
body = [self.visit(n) for n in node.body]
orelse = [self.visit(n) for n in node.orelse]
# compound statement required for some OpenMP Directives
if isnum(node.test) and node.test.value == 1:
stmt = Block(body)
else:
stmt = If(test, Block(body), Block(orelse) if orelse else None)
return self.process_locals(node,
self.process_omp_attachements(node, stmt))
>>> node = ast.parse("def foo(a): a[-4:][5]")
>>> _, node = pm.apply(PartialConstantFolding, node)
>>> _, node = pm.apply(ConstantFolding, node)
>>> print(pm.dump(backend.Python, node))
def foo(a):
a[1]
"""
self.generic_visit(node)
if not isinstance(node.value, ast.Subscript):
return node
if not isinstance(node.value.slice, ast.Slice):
return node
if not isinstance(node.slice, ast.Index):
return node
if not isnum(node.slice.value):
return node
slice_ = node.value.slice
index = node.slice
node = node.value
node.slice = index
lower = slice_.lower or ast.Constant(0, None)
step = slice_.step or ast.Constant(1, None)
node.slice.value = ast.BinOp(lower,
ast.Add(),
ast.BinOp(index.value,
ast.Mult(),
step))
self.update = True
return node
def visit_Subscript(self, node):
self.visit(node.value)
# type of a[1:2, 3, 4:1] is the type of: declval(a)(slice, long, slice)
if isinstance(node.slice, ast.ExtSlice):
self.visit(node.slice)
def f(t):
def et(a, *b):
return "{0}({1})".format(a, ", ".join(b))
dim_types = tuple(self.result[d] for d in node.slice.dims)
return self.builder.ExpressionType(et, (t,) + dim_types)
elif (isinstance(node.slice, ast.Index) and
isnum(node.slice.value) and node.slice.value.value >= 0):
# type of a[2] is the type of an elements of a
# this special case is to make type inference easier
# for the back end compiler
def f(t):
return self.builder.ElementType(node.slice.value.value, t)
else:
# type of a[i] is the return type of the matching function
self.visit(node.slice)
def f(x):
return self.builder.ExpressionType(
"{0}[{1}]".format,
(x, self.result[node.slice]))
f and self.combine(node, node.value, unary_op=f)
def isrange(self, elts):
if not elts:
return None
if not all(isnum(x) and isinstance(x.value, int)
for x in elts):
return None
unboxed_ints = [x.value for x in elts]
start = unboxed_ints[0]
if len(unboxed_ints) == 1:
return start, start + 1, 1
else:
step = unboxed_ints[1] - start
stop = unboxed_ints[-1] + step
if unboxed_ints == list(range(start, stop, step)):
return start, stop, step
else:
return None
pattern_range = ast.Call(func=ast.Attribute(
value=ast.Name('__builtin__', ast.Load(), None, None),
attr=range_name, ctx=ast.Load()),
args=AST_any(), keywords=[])
is_assigned = set()
for stmt in node.body:
is_assigned.update(self.gather(IsAssigned, stmt))
nodes = ASTMatcher(pattern_range).search(node.iter)
if node.iter not in nodes or node.target.id in is_assigned:
return False
args = node.iter.args
if len(args) < 3:
return True
if isnum(args[2]):
return True
return False
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 isnum(t.operand):
self.write("(")
self.dispatch(t.operand)
self.write(")")
else:
self.dispatch(t.operand)
self.write(")")
def handle_real_loop_comparison(self, args, target, upper_bound):
"""
Handle comparison for real loops.
Add the correct comparison operator if possible.
"""
# order is 1 for increasing loop, -1 for decreasing loop and 0 if it is
# not known at compile time
if len(args) <= 2:
order = 1
elif isnum(args[2]):
order = -1 + 2 * (int(args[2].value) > 0)
elif isnum(args[1]) and isnum(args[0]):
order = -1 + 2 * (int(args[1].value) > int(args[0].value))
else:
order = 0
comparison = "{} < {}" if order == 1 else "{} > {}"
comparison = comparison.format(target, upper_bound)
return comparison
def _Attribute(self, t):
self.dispatch(t.value)
# Special case: 3.__abs__() is a syntax error, so if t.value
# is an integer literal then we need to either parenthesize
# it or add an extra space to get 3 .__abs__().
if isnum(t.value) and isinstance(t.value.value, int):
self.write(" ")
self.write(".")
self.write(t.attr)
def fold_mult_right(self, node):
if not isinstance(node.right, (ast.List, ast.Tuple)):
return False
if not isnum(node.left):
return False
return isinstance(node.op, ast.Mult)