self._ctrl_stack.append((name, data))
return data
+ def _check_signed_cond(self, cond):
+ cond = Value.wrap(cond)
+ bits, sign = cond.shape()
+ if sign:
+ warnings.warn("Signed values in If/Elif conditions usually result from inverting "
+ "Python booleans with ~, which leads to unexpected results: ~True is "
+ "-2, which is truthful. "
+ "(Silence this warning with `m.If(x)` → `m.If(x.bool())`.)",
+ SyntaxWarning, stacklevel=4)
+ return cond
+
@contextmanager
def If(self, cond):
self._check_context("If", context=None)
+ cond = self._check_signed_cond(cond)
src_loc = tracer.get_src_loc(src_loc_at=1)
if_data = self._set_ctrl("If", {
"tests": [],
@contextmanager
def Elif(self, cond):
self._check_context("Elif", context=None)
+ cond = self._check_signed_cond(cond)
src_loc = tracer.get_src_loc(src_loc_at=1)
if_data = self._get_ctrl("If")
if if_data is None:
)
""")
+ def test_If_signed_suspicious(self):
+ m = Module()
+ with self.assertWarns(SyntaxWarning,
+ msg="Signed values in If/Elif conditions usually result from inverting Python "
+ "booleans with ~, which leads to unexpected results: ~True is -2, which is "
+ "truthful. (Silence this warning with `m.If(x)` → `m.If(x.bool())`.)"):
+ with m.If(~True):
+ pass
+
+ def test_Elif_signed_suspicious(self):
+ m = Module()
+ with m.If(0):
+ pass
+ with self.assertWarns(SyntaxWarning,
+ msg="Signed values in If/Elif conditions usually result from inverting Python "
+ "booleans with ~, which leads to unexpected results: ~True is -2, which is "
+ "truthful. (Silence this warning with `m.If(x)` → `m.If(x.bool())`.)"):
+ with m.Elif(~True):
+ pass
+
def test_Switch(self):
m = Module()
with m.Switch(self.w1):