hdl.rec: proxy operators correctly.

Commit abbebf8e used __getattr__ to proxy Value methods called on 
Record. However, that did not proxy operators like __add__ because
Python looks up the special operator methods directly on the class
and does not run __getattr__ if they are missing.

Instead of using __getattr__, explicitly enumerate and wrap every
Value method that should be proxied. This also ensures backwards
compatibility if more methods are added to Value later.

Fixes #533.
This commit is contained in:
awygle 2020-11-09 12:20:25 -08:00 committed by GitHub
parent ebbdac9798
commit ea94c9cc45
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 138 additions and 11 deletions

View file

@ -143,17 +143,7 @@ class Record(ValueCastable):
src_loc_at=1 + src_loc_at)
def __getattr__(self, name):
# must check `getattr` before `self` - we need to hit Value methods before fields
try:
value_attr = getattr(Value, name)
if callable(value_attr):
@wraps(value_attr)
def _wrapper(*args, **kwargs):
return value_attr(self, *args, **kwargs)
return _wrapper
return value_attr
except AttributeError:
return self[name]
return self[name]
def __getitem__(self, item):
if isinstance(item, str):
@ -257,3 +247,29 @@ class Record(ValueCastable):
stmts += [item.eq(reduce(lambda a, b: a | b, subord_items))]
return stmts
def _valueproxy(name):
value_func = getattr(Value, name)
@wraps(value_func)
def _wrapper(self, *args, **kwargs):
return value_func(Value.cast(self), *args, **kwargs)
return _wrapper
for name in [
"__bool__",
"__invert__", "__neg__",
"__add__", "__radd__", "__sub__", "__rsub__",
"__mul__", "__rmul__",
"__mod__", "__rmod__", "__floordiv__", "__rfloordiv__",
"__lshift__", "__rlshift__", "__rshift__", "__rrshift__",
"__and__", "__rand__", "__xor__", "__rxor__", "__or__", "__ror__",
"__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__",
"__abs__", "__len__",
"as_unsigned", "as_signed", "bool", "any", "all", "xor", "implies",
"bit_select", "word_select", "matches",
"shift_left", "shift_right", "rotate_left", "rotate_right", "eq"
]:
setattr(Record, name, _valueproxy(name))
del _valueproxy
del name