Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
Combiner for Floor divide operation.
>>> import gast as ast
>>> combine(Range(-1, 5), Range(3, 8), ast.FloorDiv())
Range(low=-1, high=1)
>>> combine(Range(-1, 5), Range(-5, -4), ast.FloorDiv())
Range(low=-2, high=0)
>>> combine(Range(-1, 5), Range(-5, 3), ast.FloorDiv())
Range(low=-inf, high=inf)
"""
if range2.low <= 0 and range2.high >= 0:
return UNKNOWN_RANGE
if 0 in range2:
return UNKNOWN_RANGE
res = [v1 // v2 for v1, v2 in itertools.product(range1, range2)]
return Range(numpy.min(res), numpy.max(res))
TODO : We could exclude some operand with this range information...
>>> import ast
>>> from pythran import passmanager, backend
>>> node = ast.parse('''
... def foo():
... a = 2
... c = 3
... d = a or c''')
>>> pm = passmanager.PassManager("test")
>>> res = pm.gather(RangeValues, node)
>>> res['d']
Range(low=2, high=3)
"""
res = zip(*[self.visit(v) for v in node.values])
return Range(min(res[0]), max(res[1]))
>>> res['d']
Range(low=-3, high=-3)
>>> res['e']
Range(low=0, high=1)
"""
res = self.visit(node.operand)
if isinstance(node.op, ast.Not):
return Range(0, 1)
elif(isinstance(node.op, ast.Invert) and
isinstance(res.high, int) and
isinstance(res.low, int)):
return Range(~res.high, ~res.low)
elif isinstance(node.op, ast.UAdd):
return res
elif isinstance(node.op, ast.USub):
return Range(-res.high, -res.low)
else:
return UNKNOWN_RANGE
def cmp_values(_):
""" Return the range of a comparison value, i.e. [-1, 1]. """
return Range(-1, 1)
def ord_values(_):
""" Return possible range for ord function. """
return Range(0, 255)
def positive_values(_):
""" Return a positive range without upper bound. """
return Range(0, float("inf"))
def range_values(args):
""" Function used to compute returned range value of [x]range function. """
if len(args) == 1:
return Range(0, args[0].high)
elif len(args) == 2:
return Range(args[0].low, args[1].high)
elif len(args) == 3:
is_neg = args[2].low < 0
is_pos = args[2].high > 0
if is_neg and is_pos:
return UNKNOWN_RANGE
elif is_neg:
return Range(args[1].low, args[0].high)
else:
return Range(args[0].low, args[1].high)
def max_values(args):
""" Return possible range for max function. """
return Range(max(x.low for x in args), max(x.high for x in args))
self.high = max(self.high, new_range.high)
def __iter__(self):
""" Iterate over a range bound."""
yield self.low
yield self.high
def widen(self, range_):
""" Widen current range. """
if self.low < range_.low:
self.low = -float("inf")
if self.high > range_.high:
self.high = float("inf")
UNKNOWN_RANGE = Range(-float("inf"), float("inf"))
def range_values(args):
""" Function used to compute returned range value of [x]range function. """
if len(args) == 1:
return Range(0, args[0].high)
elif len(args) == 2:
return Range(args[0].low, args[1].high)
elif len(args) == 3:
is_neg = args[2].low < 0
is_pos = args[2].high > 0
if is_neg and is_pos:
return UNKNOWN_RANGE
elif is_neg:
return Range(args[1].low, args[0].high)
else:
def combine_add(range1, range2):
"""
Combiner for Addition operation.
>>> import gast as ast
>>> combine(Range(-12, 5), Range(-5, -3), ast.Add())
Range(low=-17, high=2)
"""
return Range(range1.low + range2.low, range1.high + range2.high)