hdl.dsl: make if m.{If,Elif,Else}(...)
a syntax error.
A common typo, and hard to notice when it's silently ignored. Fixes #284.
This commit is contained in:
parent
3ac13eb8f9
commit
9964fc6b57
|
@ -1,6 +1,7 @@
|
||||||
from collections import OrderedDict, namedtuple
|
from collections import OrderedDict, namedtuple
|
||||||
from collections.abc import Iterable
|
from collections.abc import Iterable
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager, _GeneratorContextManager
|
||||||
|
from functools import wraps
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
|
@ -113,6 +114,27 @@ class _ModuleBuilderDomainSet:
|
||||||
self._builder._add_domain(domain)
|
self._builder._add_domain(domain)
|
||||||
|
|
||||||
|
|
||||||
|
# It's not particularly clean to depend on an internal interface, but, unfortunately, __bool__
|
||||||
|
# must be defined on a class to be called during implicit conversion.
|
||||||
|
class _GuardedContextManager(_GeneratorContextManager):
|
||||||
|
def __init__(self, keyword, func, args, kwds):
|
||||||
|
self.keyword = keyword
|
||||||
|
return super().__init__(func, args, kwds)
|
||||||
|
|
||||||
|
def __bool__(self):
|
||||||
|
raise SyntaxError("`if m.{kw}(...):` does not work; use `with m.{kw}(...)`"
|
||||||
|
.format(kw=self.keyword))
|
||||||
|
|
||||||
|
|
||||||
|
def _guardedcontextmanager(keyword):
|
||||||
|
def decorator(func):
|
||||||
|
@wraps(func)
|
||||||
|
def helper(*args, **kwds):
|
||||||
|
return _GuardedContextManager(keyword, func, args, kwds)
|
||||||
|
return helper
|
||||||
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
class FSM:
|
class FSM:
|
||||||
def __init__(self, state, encoding, decoding):
|
def __init__(self, state, encoding, decoding):
|
||||||
self.state = state
|
self.state = state
|
||||||
|
@ -183,7 +205,7 @@ class Module(_ModuleBuilderRoot, Elaboratable):
|
||||||
SyntaxWarning, stacklevel=4)
|
SyntaxWarning, stacklevel=4)
|
||||||
return cond
|
return cond
|
||||||
|
|
||||||
@contextmanager
|
@_guardedcontextmanager("If")
|
||||||
def If(self, cond):
|
def If(self, cond):
|
||||||
self._check_context("If", context=None)
|
self._check_context("If", context=None)
|
||||||
cond = self._check_signed_cond(cond)
|
cond = self._check_signed_cond(cond)
|
||||||
|
@ -206,7 +228,7 @@ class Module(_ModuleBuilderRoot, Elaboratable):
|
||||||
self.domain._depth -= 1
|
self.domain._depth -= 1
|
||||||
self._statements = _outer_case
|
self._statements = _outer_case
|
||||||
|
|
||||||
@contextmanager
|
@_guardedcontextmanager("Elif")
|
||||||
def Elif(self, cond):
|
def Elif(self, cond):
|
||||||
self._check_context("Elif", context=None)
|
self._check_context("Elif", context=None)
|
||||||
cond = self._check_signed_cond(cond)
|
cond = self._check_signed_cond(cond)
|
||||||
|
@ -226,7 +248,7 @@ class Module(_ModuleBuilderRoot, Elaboratable):
|
||||||
self.domain._depth -= 1
|
self.domain._depth -= 1
|
||||||
self._statements = _outer_case
|
self._statements = _outer_case
|
||||||
|
|
||||||
@contextmanager
|
@_guardedcontextmanager("Else")
|
||||||
def Else(self):
|
def Else(self):
|
||||||
self._check_context("Else", context=None)
|
self._check_context("Else", context=None)
|
||||||
src_loc = tracer.get_src_loc(src_loc_at=1)
|
src_loc = tracer.get_src_loc(src_loc_at=1)
|
||||||
|
|
|
@ -300,6 +300,23 @@ class DSLTestCase(FHDLTestCase):
|
||||||
with m.Elif(~True):
|
with m.Elif(~True):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def test_if_If_Elif_Else(self):
|
||||||
|
m = Module()
|
||||||
|
with self.assertRaises(SyntaxError,
|
||||||
|
msg="`if m.If(...):` does not work; use `with m.If(...)`"):
|
||||||
|
if m.If(0):
|
||||||
|
pass
|
||||||
|
with m.If(0):
|
||||||
|
pass
|
||||||
|
with self.assertRaises(SyntaxError,
|
||||||
|
msg="`if m.Elif(...):` does not work; use `with m.Elif(...)`"):
|
||||||
|
if m.Elif(0):
|
||||||
|
pass
|
||||||
|
with self.assertRaises(SyntaxError,
|
||||||
|
msg="`if m.Else(...):` does not work; use `with m.Else(...)`"):
|
||||||
|
if m.Else():
|
||||||
|
pass
|
||||||
|
|
||||||
def test_Switch(self):
|
def test_Switch(self):
|
||||||
m = Module()
|
m = Module()
|
||||||
with m.Switch(self.w1):
|
with m.Switch(self.w1):
|
||||||
|
|
Loading…
Reference in a new issue