From ae12c94d04307c0c5f8cebd7d684295374ffb525 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Thu, 30 Mar 2017 14:11:19 -0700 Subject: [PATCH] Add mypy annotations to cdsl.predicates, settings. Wherein we learned that only BoolSettings can be used as predicates. --- lib/cretonne/meta/cdsl/isa.py | 11 ++++--- lib/cretonne/meta/cdsl/predicates.py | 39 +++++++++++++++++++++++-- lib/cretonne/meta/cdsl/settings.py | 43 ++++++++++++++++++++++------ 3 files changed, 77 insertions(+), 16 deletions(-) diff --git a/lib/cretonne/meta/cdsl/isa.py b/lib/cretonne/meta/cdsl/isa.py index ef667015ce..0109c1f12f 100644 --- a/lib/cretonne/meta/cdsl/isa.py +++ b/lib/cretonne/meta/cdsl/isa.py @@ -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() diff --git a/lib/cretonne/meta/cdsl/predicates.py b/lib/cretonne/meta/cdsl/predicates.py index 8a1b18807a..82a54c6cf7 100644 --- a/lib/cretonne/meta/cdsl/predicates.py +++ b/lib/cretonne/meta/cdsl/predicates.py @@ -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 diff --git a/lib/cretonne/meta/cdsl/settings.py b/lib/cretonne/meta/cdsl/settings.py index 1c1e31643c..ea50afa44b 100644 --- a/lib/cretonne/meta/cdsl/settings.py +++ b/lib/cretonne/meta/cdsl/settings.py @@ -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.