parent
cee43f0de1
commit
659b0e8189
|
@ -32,7 +32,7 @@ class DUID:
|
||||||
DUID.__next_uid += 1
|
DUID.__next_uid += 1
|
||||||
|
|
||||||
|
|
||||||
class Shape(typing.NamedTuple):
|
class Shape:
|
||||||
"""Bit width and signedness of a value.
|
"""Bit width and signedness of a value.
|
||||||
|
|
||||||
A ``Shape`` can be constructed using:
|
A ``Shape`` can be constructed using:
|
||||||
|
@ -55,8 +55,15 @@ class Shape(typing.NamedTuple):
|
||||||
signed : bool
|
signed : bool
|
||||||
If ``False``, the value is unsigned. If ``True``, the value is signed two's complement.
|
If ``False``, the value is unsigned. If ``True``, the value is signed two's complement.
|
||||||
"""
|
"""
|
||||||
width: int = 1
|
def __init__(self, width=1, signed=False):
|
||||||
signed: bool = False
|
if not isinstance(width, int) or width < 0:
|
||||||
|
raise TypeError("Width must be a non-negative integer, not {!r}"
|
||||||
|
.format(width))
|
||||||
|
self.width = width
|
||||||
|
self.signed = signed
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return iter((self.width, self.signed))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def cast(obj, *, src_loc_at=0):
|
def cast(obj, *, src_loc_at=0):
|
||||||
|
@ -95,13 +102,20 @@ class Shape(typing.NamedTuple):
|
||||||
else:
|
else:
|
||||||
return "unsigned({})".format(self.width)
|
return "unsigned({})".format(self.width)
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
# TODO: use dataclasses instead of this hack
|
if isinstance(other, tuple) and len(other) == 2:
|
||||||
def _Shape___init__(self, width=1, signed=False):
|
width, signed = other
|
||||||
if not isinstance(width, int) or width < 0:
|
if isinstance(width, int) and isinstance(signed, bool):
|
||||||
raise TypeError("Width must be a non-negative integer, not {!r}"
|
return self.width == width and self.signed == signed
|
||||||
.format(width))
|
else:
|
||||||
Shape.__init__ = _Shape___init__
|
raise TypeError("Shapes may be compared with other Shapes and (int, bool) tuples, "
|
||||||
|
"not {!r}"
|
||||||
|
.format(other))
|
||||||
|
if not isinstance(other, Shape):
|
||||||
|
raise TypeError("Shapes may be compared with other Shapes and (int, bool) tuples, "
|
||||||
|
"not {!r}"
|
||||||
|
.format(other))
|
||||||
|
return self.width == other.width and self.signed == other.signed
|
||||||
|
|
||||||
|
|
||||||
def unsigned(width):
|
def unsigned(width):
|
||||||
|
|
|
@ -39,6 +39,16 @@ class ShapeTestCase(FHDLTestCase):
|
||||||
msg="Width must be a non-negative integer, not -1"):
|
msg="Width must be a non-negative integer, not -1"):
|
||||||
Shape(-1)
|
Shape(-1)
|
||||||
|
|
||||||
|
def test_compare_wrong(self):
|
||||||
|
with self.assertRaises(TypeError,
|
||||||
|
msg="Shapes may be compared with other Shapes and (int, bool) tuples, not 'hi'"):
|
||||||
|
Shape(1, True) == 'hi'
|
||||||
|
|
||||||
|
def test_compare_tuple_wrong(self):
|
||||||
|
with self.assertRaises(TypeError,
|
||||||
|
msg="Shapes may be compared with other Shapes and (int, bool) tuples, not (2, 3)"):
|
||||||
|
Shape(1, True) == (2, 3)
|
||||||
|
|
||||||
def test_repr(self):
|
def test_repr(self):
|
||||||
self.assertEqual(repr(Shape()), "unsigned(1)")
|
self.assertEqual(repr(Shape()), "unsigned(1)")
|
||||||
self.assertEqual(repr(Shape(2, True)), "signed(2)")
|
self.assertEqual(repr(Shape(2, True)), "signed(2)")
|
||||||
|
|
Loading…
Reference in a new issue