Add mypy annotations to cdsl.predicates, settings.
Wherein we learned that only BoolSettings can be used as predicates.
This commit is contained in:
@@ -8,11 +8,10 @@ from .registers import RegClass, Register
|
||||
try:
|
||||
from typing import Tuple, Union, Any, Iterable, Sequence, List, Set, TYPE_CHECKING # noqa
|
||||
from .instructions import MaybeBoundInst, InstructionGroup, InstructionFormat # noqa
|
||||
from .predicates import Predicate, FieldPredicate # noqa
|
||||
from .predicates import PredNode # noqa
|
||||
from .settings import SettingGroup # noqa
|
||||
from .types import ValueType # noqa
|
||||
from .registers import RegBank # noqa
|
||||
AnyPredicate = Union[Predicate, FieldPredicate]
|
||||
OperandConstraint = Union[RegClass, Register, int]
|
||||
ConstraintSeq = Union[OperandConstraint, Tuple[OperandConstraint, ...]]
|
||||
except ImportError:
|
||||
@@ -80,8 +79,8 @@ class TargetISA(object):
|
||||
Ensures that all ISA predicates have an assigned bit number in
|
||||
`self.settings`.
|
||||
"""
|
||||
self.all_instps = list() # type: List[AnyPredicate]
|
||||
instps = set() # type: Set[AnyPredicate]
|
||||
self.all_instps = list() # type: List[PredNode]
|
||||
instps = set() # type: Set[PredNode]
|
||||
for cpumode in self.cpumodes:
|
||||
for enc in cpumode.encodings:
|
||||
instp = enc.instp
|
||||
@@ -166,7 +165,7 @@ class EncRecipe(object):
|
||||
"""
|
||||
|
||||
def __init__(self, name, format, ins, outs, instp=None, isap=None):
|
||||
# type: (str, InstructionFormat, ConstraintSeq, ConstraintSeq, AnyPredicate, AnyPredicate) -> None # noqa
|
||||
# type: (str, InstructionFormat, ConstraintSeq, ConstraintSeq, PredNode, PredNode) -> None # noqa
|
||||
self.name = name
|
||||
self.format = format
|
||||
self.instp = instp
|
||||
@@ -219,7 +218,7 @@ class Encoding(object):
|
||||
"""
|
||||
|
||||
def __init__(self, cpumode, inst, recipe, encbits, instp=None, isap=None):
|
||||
# type: (CPUMode, MaybeBoundInst, EncRecipe, int, AnyPredicate, AnyPredicate) -> None # noqa
|
||||
# type: (CPUMode, MaybeBoundInst, EncRecipe, int, PredNode, PredNode) -> None # noqa
|
||||
assert isinstance(cpumode, CPUMode)
|
||||
assert isinstance(recipe, EncRecipe)
|
||||
self.inst, self.typevars = inst.fully_bound()
|
||||
|
||||
@@ -10,7 +10,7 @@ function determine the kind of predicate:
|
||||
|
||||
- An *Instruction predicate* is evaluated on an instruction instance, so it can
|
||||
inspect all the immediate fields and type variables of the instruction.
|
||||
Instruction predicates can be evaluatd before register allocation, so they
|
||||
Instruction predicates can be evaluated before register allocation, so they
|
||||
can not depend on specific register assignments to the value operands or
|
||||
outputs.
|
||||
|
||||
@@ -24,6 +24,17 @@ predicate, the context is the instruction format.
|
||||
from __future__ import absolute_import
|
||||
from functools import reduce
|
||||
|
||||
try:
|
||||
from typing import Sequence, Tuple, Set, Any, Union, TYPE_CHECKING # noqa
|
||||
if TYPE_CHECKING:
|
||||
from .formats import InstructionFormat, FormatField # noqa
|
||||
from .settings import BoolSetting, SettingGroup # noqa
|
||||
PredContext = Union[SettingGroup, InstructionFormat]
|
||||
PredLeaf = Union[BoolSetting, 'FieldPredicate']
|
||||
PredNode = Union[PredLeaf, 'Predicate']
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
def _is_parent(a, b):
|
||||
"""
|
||||
@@ -58,7 +69,9 @@ class Predicate(object):
|
||||
"""
|
||||
|
||||
def __init__(self, parts):
|
||||
self.name = None
|
||||
# type: (Sequence[PredNode]) -> None
|
||||
self.name = None # type: str
|
||||
self.number = None # type: int
|
||||
self.parts = parts
|
||||
self.context = reduce(
|
||||
_descendant,
|
||||
@@ -66,6 +79,7 @@ class Predicate(object):
|
||||
assert self.context, "Incompatible predicate parts"
|
||||
|
||||
def __str__(self):
|
||||
# type: () -> str
|
||||
if self.name:
|
||||
return '{}.{}'.format(self.context.name, self.name)
|
||||
else:
|
||||
@@ -74,15 +88,21 @@ class Predicate(object):
|
||||
', '.join(map(str, self.parts)))
|
||||
|
||||
def predicate_context(self):
|
||||
# type: () -> PredContext
|
||||
return self.context
|
||||
|
||||
def predicate_leafs(self, leafs):
|
||||
# type: (Set[PredLeaf]) -> None
|
||||
"""
|
||||
Collect all leaf predicates into the `leafs` set.
|
||||
"""
|
||||
for part in self.parts:
|
||||
part.predicate_leafs(leafs)
|
||||
|
||||
def rust_predicate(self, prec):
|
||||
# type: (int) -> str
|
||||
raise NotImplementedError("rust_predicate is an abstract method")
|
||||
|
||||
|
||||
class And(Predicate):
|
||||
"""
|
||||
@@ -92,9 +112,11 @@ class And(Predicate):
|
||||
precedence = 2
|
||||
|
||||
def __init__(self, *args):
|
||||
# type: (*PredNode) -> None
|
||||
super(And, self).__init__(args)
|
||||
|
||||
def rust_predicate(self, prec):
|
||||
# type: (int) -> str
|
||||
"""
|
||||
Return a Rust expression computing the value of this predicate.
|
||||
|
||||
@@ -112,6 +134,7 @@ class And(Predicate):
|
||||
|
||||
@staticmethod
|
||||
def combine(*args):
|
||||
# type: (*PredNode) -> PredNode
|
||||
"""
|
||||
Combine a sequence of predicates, allowing for `None` members.
|
||||
|
||||
@@ -135,9 +158,11 @@ class Or(Predicate):
|
||||
precedence = 1
|
||||
|
||||
def __init__(self, *args):
|
||||
# type: (*PredNode) -> None
|
||||
super(Or, self).__init__(args)
|
||||
|
||||
def rust_predicate(self, prec):
|
||||
# type: (int) -> str
|
||||
s = ' || '.join(p.rust_predicate(Or.precedence) for p in self.parts)
|
||||
if prec > Or.precedence:
|
||||
s = '({})'.format(s)
|
||||
@@ -152,9 +177,11 @@ class Not(Predicate):
|
||||
precedence = 3
|
||||
|
||||
def __init__(self, part):
|
||||
# type: (PredNode) -> None
|
||||
super(Not, self).__init__((part,))
|
||||
|
||||
def rust_predicate(self, prec):
|
||||
# type: (int) -> str
|
||||
return '!' + self.parts[0].rust_predicate(Not.precedence)
|
||||
|
||||
|
||||
@@ -168,15 +195,19 @@ class FieldPredicate(object):
|
||||
"""
|
||||
|
||||
def __init__(self, field, function, args):
|
||||
# type: (FormatField, str, Sequence[Any]) -> None
|
||||
self.number = None # type: int
|
||||
self.field = field
|
||||
self.function = function
|
||||
self.args = args
|
||||
|
||||
def __str__(self):
|
||||
# type: () -> str
|
||||
args = (self.field.name,) + tuple(map(str, self.args))
|
||||
return '{}({})'.format(self.function, ', '.join(args))
|
||||
|
||||
def predicate_context(self):
|
||||
# type: () -> PredContext
|
||||
"""
|
||||
This predicate can be evaluated in the context of an instruction
|
||||
format.
|
||||
@@ -184,9 +215,11 @@ class FieldPredicate(object):
|
||||
return self.field.format
|
||||
|
||||
def predicate_leafs(self, leafs):
|
||||
# type: (Set[PredLeaf]) -> None
|
||||
leafs.add(self)
|
||||
|
||||
def rust_predicate(self, prec):
|
||||
# type: (int) -> str
|
||||
"""
|
||||
Return a string of Rust code that evaluates this predicate.
|
||||
"""
|
||||
@@ -210,6 +243,7 @@ class IsSignedInt(FieldPredicate):
|
||||
"""
|
||||
|
||||
def __init__(self, field, width, scale=0):
|
||||
# type: (FormatField, int, int) -> None
|
||||
super(IsSignedInt, self).__init__(
|
||||
field, 'is_signed_int', (width, scale))
|
||||
self.width = width
|
||||
@@ -232,6 +266,7 @@ class IsUnsignedInt(FieldPredicate):
|
||||
"""
|
||||
|
||||
def __init__(self, field, width, scale=0):
|
||||
# type: (FormatField, int, int) -> None
|
||||
super(IsUnsignedInt, self).__init__(
|
||||
field, 'is_unsigned_int', (width, scale))
|
||||
self.width = width
|
||||
|
||||
@@ -3,6 +3,13 @@ from __future__ import absolute_import
|
||||
from collections import OrderedDict
|
||||
from .predicates import Predicate
|
||||
|
||||
try:
|
||||
from typing import Set, List, Dict, Any, TYPE_CHECKING # noqa
|
||||
if TYPE_CHECKING:
|
||||
from .predicates import PredLeaf, PredNode # noqa
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
class Setting(object):
|
||||
"""
|
||||
@@ -13,25 +20,26 @@ class Setting(object):
|
||||
"""
|
||||
|
||||
def __init__(self, doc):
|
||||
self.name = None # Assigned later by `extract_names()`.
|
||||
# type: (str) -> None
|
||||
self.name = None # type: str # Assigned later by `extract_names()`.
|
||||
self.number = None # type: int
|
||||
self.__doc__ = doc
|
||||
# Offset of byte in settings vector containing this setting.
|
||||
self.byte_offset = None
|
||||
self.byte_offset = None # type: int
|
||||
self.group = SettingGroup.append(self)
|
||||
|
||||
def __str__(self):
|
||||
# type: () -> str
|
||||
return '{}.{}'.format(self.group.name, self.name)
|
||||
|
||||
def predicate_context(self):
|
||||
# type: () -> SettingGroup
|
||||
"""
|
||||
Return the context where this setting can be evaluated as a (leaf)
|
||||
predicate.
|
||||
"""
|
||||
return self.group
|
||||
|
||||
def predicate_leafs(self, leafs):
|
||||
leafs.add(self)
|
||||
|
||||
|
||||
class BoolSetting(Setting):
|
||||
"""
|
||||
@@ -42,10 +50,13 @@ class BoolSetting(Setting):
|
||||
"""
|
||||
|
||||
def __init__(self, doc, default=False):
|
||||
# type: (str, bool) -> None
|
||||
super(BoolSetting, self).__init__(doc)
|
||||
self.default = default
|
||||
self.bit_offset = None # type: int
|
||||
|
||||
def default_byte(self):
|
||||
# type: () -> int
|
||||
"""
|
||||
Get the default value of this setting, as a byte that can be bitwise
|
||||
or'ed with the other booleans sharing the same byte.
|
||||
@@ -55,7 +66,12 @@ class BoolSetting(Setting):
|
||||
else:
|
||||
return 0
|
||||
|
||||
def predicate_leafs(self, leafs):
|
||||
# type: (Set[PredLeaf]) -> None
|
||||
leafs.add(self)
|
||||
|
||||
def rust_predicate(self, prec):
|
||||
# type: (int) -> str
|
||||
"""
|
||||
Return the Rust code to compute the value of this setting.
|
||||
|
||||
@@ -74,12 +90,14 @@ class NumSetting(Setting):
|
||||
"""
|
||||
|
||||
def __init__(self, doc, default=0):
|
||||
# type: (str, int) -> None
|
||||
super(NumSetting, self).__init__(doc)
|
||||
assert default == int(default)
|
||||
assert default >= 0 and default <= 255
|
||||
self.default = default
|
||||
|
||||
def default_byte(self):
|
||||
# type: () -> int
|
||||
return self.default
|
||||
|
||||
|
||||
@@ -94,12 +112,14 @@ class EnumSetting(Setting):
|
||||
"""
|
||||
|
||||
def __init__(self, doc, *args):
|
||||
# type: (str, *str) -> None
|
||||
super(EnumSetting, self).__init__(doc)
|
||||
assert len(args) > 0, "EnumSetting must have at least one value"
|
||||
self.values = tuple(str(x) for x in args)
|
||||
self.default = self.values[0]
|
||||
|
||||
def default_byte(self):
|
||||
# type: () -> int
|
||||
return 0
|
||||
|
||||
|
||||
@@ -119,23 +139,25 @@ class SettingGroup(object):
|
||||
_current = None # type: SettingGroup
|
||||
|
||||
def __init__(self, name, parent=None):
|
||||
# type: (str, SettingGroup) -> None
|
||||
self.name = name
|
||||
self.parent = parent
|
||||
self.settings = []
|
||||
self.settings = [] # type: List[Setting]
|
||||
# Named predicates computed from settings in this group or its
|
||||
# parents.
|
||||
self.named_predicates = []
|
||||
self.named_predicates = [] # type: List[Predicate]
|
||||
# All boolean predicates that can be accessed by number. This includes:
|
||||
# - All boolean settings in this group.
|
||||
# - All named predicates.
|
||||
# - Added anonymous predicates, see `number_predicate()`.
|
||||
# - Added parent predicates that are replicated in this group.
|
||||
# Maps predicate -> number.
|
||||
self.predicate_number = OrderedDict()
|
||||
self.predicate_number = OrderedDict() # type: OrderedDict[PredNode, int] # noqa
|
||||
|
||||
self.open()
|
||||
|
||||
def open(self):
|
||||
# type: () -> None
|
||||
"""
|
||||
Open this setting group such that future new settings are added to this
|
||||
group.
|
||||
@@ -146,6 +168,7 @@ class SettingGroup(object):
|
||||
SettingGroup._current = self
|
||||
|
||||
def close(self, globs=None):
|
||||
# type: (Dict[str, Any]) -> None
|
||||
"""
|
||||
Close this setting group. This function must be called before opening
|
||||
another setting group.
|
||||
@@ -170,12 +193,14 @@ class SettingGroup(object):
|
||||
|
||||
@staticmethod
|
||||
def append(setting):
|
||||
# type: (Setting) -> SettingGroup
|
||||
g = SettingGroup._current
|
||||
assert g, "Open a setting group before defining settings."
|
||||
g.settings.append(setting)
|
||||
return g
|
||||
|
||||
def number_predicate(self, pred):
|
||||
# type: (PredNode) -> int
|
||||
"""
|
||||
Make sure that `pred` has an assigned number, and will be included in
|
||||
this group's bit vector.
|
||||
@@ -200,6 +225,7 @@ class SettingGroup(object):
|
||||
return number
|
||||
|
||||
def layout(self):
|
||||
# type: () -> None
|
||||
"""
|
||||
Compute the layout of the byte vector used to represent this settings
|
||||
group.
|
||||
@@ -250,6 +276,7 @@ class SettingGroup(object):
|
||||
self.number_predicate(p)
|
||||
|
||||
def byte_size(self):
|
||||
# type: () -> int
|
||||
"""
|
||||
Compute the number of bytes required to hold all settings and
|
||||
precomputed predicates.
|
||||
|
||||
Reference in New Issue
Block a user