diff --git a/amaranth/hdl/_ast.py b/amaranth/hdl/_ast.py index c7eba34..c2fe98f 100644 --- a/amaranth/hdl/_ast.py +++ b/amaranth/hdl/_ast.py @@ -839,8 +839,15 @@ class Value(metaclass=ABCMeta): raise NotImplementedError # :nocov: +class _ConstMeta(ABCMeta): + def __call__(cls, value, shape=None, src_loc_at=0, **kwargs): + if isinstance(shape, ShapeCastable): + return shape.const(value) + return super().__call__(value, shape, **kwargs, src_loc_at=src_loc_at + 1) + + @final -class Const(Value): +class Const(Value, metaclass=_ConstMeta): """A constant, literal integer value. Parameters @@ -898,7 +905,7 @@ class Const(Value): "shape {!r}; this is likely an off-by-one error" .format(self.value, shape), category=SyntaxWarning, - stacklevel=2) + stacklevel=3) shape = Shape.cast(shape, src_loc_at=1 + src_loc_at) self.width = shape.width self.signed = shape.signed diff --git a/tests/test_hdl_ast.py b/tests/test_hdl_ast.py index 5c79788..8829aa7 100644 --- a/tests/test_hdl_ast.py +++ b/tests/test_hdl_ast.py @@ -470,6 +470,25 @@ class ConstTestCase(FHDLTestCase): with self.assertRaises(TypeError): hash(Const(0)) + def test_shape_castable(self): + class MockConstValue: + def __init__(self, value): + self.value = value + + class MockConstShape(ShapeCastable): + def as_shape(self): + return unsigned(8) + + def __call__(self, value): + return value + + def const(self, init): + return MockConstValue(init) + + s = Const(10, MockConstShape()) + self.assertIsInstance(s, MockConstValue) + self.assertEqual(s.value, 10) + class OperatorTestCase(FHDLTestCase): def test_bool(self):