Skip to content

Commit 6058ad3

Browse files
wanda-phiwhitequark
authored andcommitted
hdl._ast: make Shape immutable and hashable.
Fixes #1127.
1 parent 24a3928 commit 6058ad3

File tree

3 files changed

+24
-2
lines changed

3 files changed

+24
-2
lines changed

amaranth/hdl/_ast.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,16 @@ def __init__(self, width=1, signed=False):
6161
f"not {width}")
6262
if signed and width <= 0:
6363
raise TypeError(f"Width of a signed value must be a positive integer, not {width}")
64-
self.width = width
65-
self.signed = bool(signed)
64+
self._width = width
65+
self._signed = bool(signed)
66+
67+
@property
68+
def width(self):
69+
return self._width
70+
71+
@property
72+
def signed(self):
73+
return self._signed
6674

6775
# The algorithm for inferring shape for standard Python enumerations is factored out so that
6876
# `Shape.cast()` and Amaranth's `EnumMeta.as_shape()` can both use it.
@@ -144,6 +152,9 @@ def __repr__(self):
144152
else:
145153
return f"unsigned({self.width})"
146154

155+
def __hash__(self):
156+
return hash((self._width, self._signed))
157+
147158
def __eq__(self, other):
148159
return (isinstance(other, Shape) and
149160
self.width == other.width and self.signed == other.signed)

docs/changes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ Language changes
6363
* Changed: ``Signal(range(0))`` is now valid without a warning.
6464
* Changed: ``Shape.cast(range(1))`` is now ``unsigned(0)``. (`RFC 46`_)
6565
* Changed: the ``reset=`` argument of :class:`Signal`, :meth:`Signal.like`, :class:`amaranth.lib.wiring.Member`, :class:`amaranth.lib.cdc.FFSynchronizer`, and ``m.FSM()`` has been renamed to ``init=``. (`RFC 43`_)
66+
* Changed: :class:`Shape` has been made immutable and hashable.
6667
* Deprecated: :func:`amaranth.utils.log2_int`. (`RFC 17`_)
6768
* Removed: (deprecated in 0.4) :meth:`Const.normalize`. (`RFC 5`_)
6869
* Removed: (deprecated in 0.4) :class:`Repl`. (`RFC 10`_)

tests/test_hdl_ast.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,16 @@ def test_cast_bad(self):
152152
r"^Object 'foo' cannot be converted to an Amaranth shape$"):
153153
Shape.cast("foo")
154154

155+
def test_hashable(self):
156+
d = {
157+
signed(2): "a",
158+
unsigned(3): "b",
159+
unsigned(2): "c",
160+
}
161+
self.assertEqual(d[signed(2)], "a")
162+
self.assertEqual(d[unsigned(3)], "b")
163+
self.assertEqual(d[unsigned(2)], "c")
164+
155165

156166
class MockShapeCastable(ShapeCastable):
157167
def __init__(self, dest):

0 commit comments

Comments
 (0)