Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: amaranth-lang/amaranth
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 3ac13eb8f9a8
Choose a base ref
...
head repository: amaranth-lang/amaranth
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 9964fc6b5768
Choose a head ref
  • 1 commit
  • 2 files changed
  • 1 contributor

Commits on Jan 31, 2020

  1. 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.
    whitequark committed Jan 31, 2020
    Copy the full SHA
    9964fc6 View commit details
Showing with 43 additions and 4 deletions.
  1. +26 −4 nmigen/hdl/dsl.py
  2. +17 −0 nmigen/test/test_hdl_dsl.py
30 changes: 26 additions & 4 deletions nmigen/hdl/dsl.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from collections import OrderedDict, namedtuple
from collections.abc import Iterable
from contextlib import contextmanager
from contextlib import contextmanager, _GeneratorContextManager
from functools import wraps
from enum import Enum
import warnings

@@ -113,6 +114,27 @@ def __setattr__(self, name, 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:
def __init__(self, state, encoding, decoding):
self.state = state
@@ -183,7 +205,7 @@ def _check_signed_cond(self, cond):
SyntaxWarning, stacklevel=4)
return cond

@contextmanager
@_guardedcontextmanager("If")
def If(self, cond):
self._check_context("If", context=None)
cond = self._check_signed_cond(cond)
@@ -206,7 +228,7 @@ def If(self, cond):
self.domain._depth -= 1
self._statements = _outer_case

@contextmanager
@_guardedcontextmanager("Elif")
def Elif(self, cond):
self._check_context("Elif", context=None)
cond = self._check_signed_cond(cond)
@@ -226,7 +248,7 @@ def Elif(self, cond):
self.domain._depth -= 1
self._statements = _outer_case

@contextmanager
@_guardedcontextmanager("Else")
def Else(self):
self._check_context("Else", context=None)
src_loc = tracer.get_src_loc(src_loc_at=1)
17 changes: 17 additions & 0 deletions nmigen/test/test_hdl_dsl.py
Original file line number Diff line number Diff line change
@@ -300,6 +300,23 @@ def test_Elif_signed_suspicious(self):
with m.Elif(~True):
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):
m = Module()
with m.Switch(self.w1):