_unused: extract must-use logic from hdl.ir.

This commit is contained in:
whitequark 2020-02-01 01:35:05 +00:00
parent 687d3a3df7
commit 9fb4a4f09e
3 changed files with 51 additions and 34 deletions

45
nmigen/_unused.py Normal file
View file

@ -0,0 +1,45 @@
import sys
import warnings
from ._utils import get_linter_option
__all__ = ["UnusedMustUse", "MustUse"]
class UnusedMustUse(Warning):
pass
class MustUse:
_MustUse__silence = False
_MustUse__warning = UnusedMustUse
def __new__(cls, *args, src_loc_at=0, **kwargs):
frame = sys._getframe(1 + src_loc_at)
self = super().__new__(cls)
self._MustUse__used = False
self._MustUse__context = dict(
filename=frame.f_code.co_filename,
lineno=frame.f_lineno,
source=self)
return self
def __del__(self):
if self._MustUse__silence:
return
if hasattr(self, "_MustUse__used") and not self._MustUse__used:
if get_linter_option(self._MustUse__context["filename"],
self._MustUse__warning.__name__, bool, True):
warnings.warn_explicit(
"{!r} created but never used".format(self), self._MustUse__warning,
**self._MustUse__context)
_old_excepthook = sys.excepthook
def _silence_elaboratable(type, value, traceback):
# Don't show anything if the interpreter crashed; that'd just obscure the exception
# traceback instead of helping.
MustUse._MustUse__silence = True
_old_excepthook(type, value, traceback)
sys.excepthook = _silence_elaboratable

View file

@ -95,7 +95,7 @@ class _CompatModuleClockDomains(_CompatModuleProxy):
class CompatModule(ir.Elaboratable):
_Elaboratable__silence = True
_MustUse__silence = True
# Actually returns another nMigen Elaboratable (nmigen.dsl.Module), not a Fragment.
def get_fragment(self):

View file

@ -6,6 +6,7 @@ import traceback
import sys
from .._utils import *
from .._unused import *
from .ast import *
from .cd import *
@ -13,41 +14,12 @@ from .cd import *
__all__ = ["UnusedElaboratable", "Elaboratable", "DriverConflict", "Fragment", "Instance"]
class UnusedElaboratable(Warning):
class UnusedElaboratable(UnusedMustUse):
pass
class Elaboratable(metaclass=ABCMeta):
_Elaboratable__silence = False
def __new__(cls, *args, src_loc_at=0, **kwargs):
frame = sys._getframe(1 + src_loc_at)
self = super().__new__(cls)
self._Elaboratable__used = False
self._Elaboratable__context = dict(
filename=frame.f_code.co_filename,
lineno=frame.f_lineno,
source=self)
return self
def __del__(self):
if self._Elaboratable__silence:
return
if hasattr(self, "_Elaboratable__used") and not self._Elaboratable__used:
if get_linter_option(self._Elaboratable__context["filename"],
"UnusedElaboratable", bool, True):
warnings.warn_explicit(
"{!r} created but never used".format(self), UnusedElaboratable,
**self._Elaboratable__context)
_old_excepthook = sys.excepthook
def _silence_elaboratable(type, value, traceback):
# Don't show anything if the interpreter crashed; that'd just obscure the exception
# traceback instead of helping.
Elaboratable._Elaboratable__silence = True
_old_excepthook(type, value, traceback)
sys.excepthook = _silence_elaboratable
class Elaboratable(MustUse, metaclass=ABCMeta):
_MustUse__warning = UnusedElaboratable
class DriverConflict(UserWarning):
@ -63,7 +35,7 @@ class Fragment:
return obj
elif isinstance(obj, Elaboratable):
code = obj.elaborate.__code__
obj._Elaboratable__used = True
obj._MustUse__used = True
obj = obj.elaborate(platform)
elif hasattr(obj, "elaborate"):
warnings.warn(