Run unittests with Python 3 if it is available.

The check.sh script always runs the Python unittests with 'python', but
if 'python3' is in the path, run it with that too.

Fix a Python 3 compat issue and avoid passing None to max() and min().
Use an explicit intersect() function instead to intersect intervals.
This commit is contained in:
Jakob Stoklund Olesen
2016-11-01 11:55:07 -07:00
parent c2dc400572
commit b7634ae5c3
3 changed files with 52 additions and 18 deletions

View File

@@ -18,5 +18,14 @@ runif() {
# #
# Install pylint with 'pip install pylint'. # Install pylint with 'pip install pylint'.
runif pylint --py3k --reports=no -- *.py cretonne isa runif pylint --py3k --reports=no -- *.py cretonne isa
# Then run the unit tests again with Python 3.
# We get deprecation warnings about assertRaisesRegexp which was renamed in
# Python 3, but there doesn't seem to be an easy workaround.
runif python3 -Wignore:Deprecation -m unittest discover
# Style linting.
runif flake8 . runif flake8 .
# Type checking.
runif mypy --py2 build.py runif mypy --py2 build.py

View File

@@ -392,9 +392,9 @@ srem = Instruction(
.. todo:: Integer remainder vs modulus. .. todo:: Integer remainder vs modulus.
Clarify whether the result has the sign of the divisor or the dividend. Clarify whether the result has the sign of the divisor or the
Should we add a ``smod`` instruction for the case where the result has dividend. Should we add a ``smod`` instruction for the case where
the same sign as the divisor? the result has the same sign as the divisor?
""", """,
ins=(x, y), outs=a) ins=(x, y), outs=a)

View File

@@ -8,19 +8,45 @@ from __future__ import absolute_import
import math import math
from . import value from . import value
try:
from typing import Tuple # noqa
Interval = Tuple[int, int]
except ImportError:
pass
MAX_LANES = 256 MAX_LANES = 256
MAX_BITS = 64 MAX_BITS = 64
def is_power_of_two(x): def is_power_of_two(x):
# type: (int) -> bool
return x > 0 and x & (x-1) == 0 return x > 0 and x & (x-1) == 0
def int_log2(x): def int_log2(x):
# type: (int) -> int
return int(math.log(x, 2)) return int(math.log(x, 2))
def intersect(a, b):
# type: (Interval, Interval) -> Interval
"""
Given two `(min, max)` inclusive intervals, compute their intersection.
Use `(None, None)` to represent the empty interval on input and output.
"""
if a[0] is None or b[0] is None:
return (None, None)
lo = max(a[0], b[0])
assert lo is not None
hi = min(a[1], b[1])
assert hi is not None
if lo <= hi:
return (lo, hi)
else:
return (None, None)
class TypeSet(object): class TypeSet(object):
""" """
A set of types. A set of types.
@@ -69,6 +95,7 @@ class TypeSet(object):
""" """
def __init__(self, lanes=None, ints=None, floats=None, bools=None): def __init__(self, lanes=None, ints=None, floats=None, bools=None):
# type: (Interval, Interval, Interval, Interval) -> None
if lanes: if lanes:
if lanes is True: if lanes is True:
lanes = (1, MAX_LANES) lanes = (1, MAX_LANES)
@@ -119,6 +146,7 @@ class TypeSet(object):
self.max_bool = None self.max_bool = None
def typeset_key(self): def typeset_key(self):
# type: () -> Tuple[int, int, int, int, int, int, int, int]
"""Key tuple used for hashing and equality.""" """Key tuple used for hashing and equality."""
return (self.min_lanes, self.max_lanes, return (self.min_lanes, self.max_lanes,
self.min_int, self.max_int, self.min_int, self.max_int,
@@ -126,6 +154,7 @@ class TypeSet(object):
self.min_bool, self.max_bool) self.min_bool, self.max_bool)
def __hash__(self): def __hash__(self):
# type: () -> int
h = hash(self.typeset_key()) h = hash(self.typeset_key())
assert h == getattr(self, 'prev_hash', h), "TypeSet changed!" assert h == getattr(self, 'prev_hash', h), "TypeSet changed!"
self.prev_hash = h self.prev_hash = h
@@ -135,6 +164,7 @@ class TypeSet(object):
return self.typeset_key() == other.typeset_key() return self.typeset_key() == other.typeset_key()
def __repr__(self): def __repr__(self):
# type: () -> str
s = 'TypeSet(lanes=({}, {})'.format(self.min_lanes, self.max_lanes) s = 'TypeSet(lanes=({}, {})'.format(self.min_lanes, self.max_lanes)
if self.min_int is not None: if self.min_int is not None:
s += ', ints=({}, {})'.format(self.min_int, self.max_int) s += ', ints=({}, {})'.format(self.min_int, self.max_int)
@@ -161,6 +191,7 @@ class TypeSet(object):
field, int_log2(max_val) + 1)) field, int_log2(max_val) + 1))
def __iand__(self, other): def __iand__(self, other):
# type: (TypeSet) -> TypeSet
""" """
Intersect self with other type set. Intersect self with other type set.
@@ -181,23 +212,17 @@ class TypeSet(object):
self.min_lanes = max(self.min_lanes, other.min_lanes) self.min_lanes = max(self.min_lanes, other.min_lanes)
self.max_lanes = min(self.max_lanes, other.max_lanes) self.max_lanes = min(self.max_lanes, other.max_lanes)
self.min_int = max(self.min_int, other.min_int) self.min_int, self.max_int = intersect(
self.max_int = min(self.max_int, other.max_int) (self.min_int, self.max_int),
if self.min_int > self.max_int: (other.min_int, other.max_int))
self.min_int = None
self.max_int = None
self.min_float = max(self.min_float, other.min_float) self.min_float, self.max_float = intersect(
self.max_float = min(self.max_float, other.max_float) (self.min_float, self.max_float),
if self.min_float > self.max_float: (other.min_float, other.max_float))
self.min_float = None
self.max_float = None
self.min_bool = max(self.min_bool, other.min_bool) self.min_bool, self.max_bool = intersect(
self.max_bool = min(self.max_bool, other.max_bool) (self.min_bool, self.max_bool),
if self.min_bool > self.max_bool: (other.min_bool, other.max_bool))
self.min_bool = None
self.max_bool = None
return self return self