Skip to content

lib.enum: privatize internal attributes in EnumView/FlagView #1424

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 27, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 29 additions & 23 deletions amaranth/lib/enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,16 +234,16 @@ def __init__(self, enum, target):
.format(target)) from e
if cast_target.shape() != enum.as_shape():
raise TypeError("EnumView target must have the same shape as the enum")
self.enum = enum
self.target = cast_target
self.__enum = enum
self.__target = cast_target

def shape(self):
"""Returns the underlying enum type."""
return self.enum
return self.__enum

def as_value(self):
"""Returns the underlying value."""
return self.target
return self.__target

def eq(self, other):
"""Assign to the underlying value.
Expand Down Expand Up @@ -296,21 +296,25 @@ def __eq__(self, other):
:class:`Value`
The result of the equality comparison, as a single-bit value.
"""
if isinstance(other, self.enum):
other = self.enum(Value.cast(other))
if not isinstance(other, EnumView) or other.enum is not self.enum:
raise TypeError("an EnumView can only be compared to value or other EnumView of the same enum type")
return self.target == other.target
enum_cls = self.shape()
if isinstance(other, enum_cls):
other = enum_cls(Value.cast(other))
if not isinstance(other, EnumView) or other.shape() is not enum_cls:
raise TypeError("an EnumView can only be compared to value or other EnumView of "
"the same enum type")
return self.as_value() == other.as_value()

def __ne__(self, other):
if isinstance(other, self.enum):
other = self.enum(Value.cast(other))
if not isinstance(other, EnumView) or other.enum is not self.enum:
raise TypeError("an EnumView can only be compared to value or other EnumView of the same enum type")
return self.target != other.target
enum_cls = self.shape()
if isinstance(other, enum_cls):
other = enum_cls(Value.cast(other))
if not isinstance(other, EnumView) or other.shape() is not enum_cls:
raise TypeError("an EnumView can only be compared to value or other EnumView of "
"the same enum type")
return self.as_value() != other.as_value()

def __repr__(self):
return f"{type(self).__qualname__}({self.enum.__qualname__}, {self.target!r})"
return f"{type(self).__qualname__}({self.__enum.__qualname__}, {self.__target!r})"


class FlagView(EnumView):
Expand All @@ -330,21 +334,23 @@ def __invert__(self):
-------
:class:`FlagView`
"""
if hasattr(self.enum, "_boundary_") and self.enum._boundary_ in (EJECT, KEEP):
return self.enum._amaranth_view_class_(self.enum, ~self.target)
enum_cls = self.shape()
if hasattr(enum_cls, "_boundary_") and enum_cls._boundary_ in (EJECT, KEEP):
return enum_cls._amaranth_view_class_(enum_cls, ~self.as_value())
else:
singles_mask = 0
for flag in self.enum:
for flag in enum_cls:
if (flag.value & (flag.value - 1)) == 0:
singles_mask |= flag.value
return self.enum._amaranth_view_class_(self.enum, ~self.target & singles_mask)
return enum_cls._amaranth_view_class_(enum_cls, ~self.as_value() & singles_mask)

def __bitop(self, other, op):
if isinstance(other, self.enum):
other = self.enum(Value.cast(other))
if not isinstance(other, FlagView) or other.enum is not self.enum:
enum_cls = self.shape()
if isinstance(other, enum_cls):
other = enum_cls(Value.cast(other))
if not isinstance(other, FlagView) or other.shape() is not enum_cls:
raise TypeError("a FlagView can only perform bitwise operation with a value or other FlagView of the same enum type")
return self.enum._amaranth_view_class_(self.enum, op(self.target, other.target))
return enum_cls._amaranth_view_class_(enum_cls, op(self.as_value(), other.as_value()))

def __and__(self, other):
"""Performs a bitwise AND and returns another :class:`FlagView`.
Expand Down
Loading