Skip to content

Commit 2994b27

Browse files
authored
Minor fixes and improvements (#45)
* "Normative points" renamed to "requirements" * `__copy__ ` and `__deepcopy__` operators implemented * Type hinting fixes
1 parent 7afa5b5 commit 2994b27

17 files changed

Lines changed: 301 additions & 66 deletions

packtype/grammar/declarations.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from ..types.base import Base
1717
from ..types.constant import Constant
1818
from ..types.enum import Enum, EnumMode
19-
from ..types.normative import NormativePoint, Priority
19+
from ..types.requirement import Priority, RequirementTag
2020
from ..types.scalar import Scalar
2121
from ..types.struct import Struct
2222
from ..types.union import Union
@@ -407,8 +407,8 @@ def to_class(
407407

408408

409409
@dataclass
410-
class DeclNormative:
411-
"""Represents a normative point declaration."""
410+
class DeclRequirement:
411+
"""Represents a requirement tag declaration."""
412412

413413
position: Position
414414
name: str
@@ -423,9 +423,10 @@ def to_class(
423423
],
424424
int | type[Base],
425425
],
426-
) -> type[NormativePoint]:
427-
entity = build_from_fields(NormativePoint, self.name, {}, {"priority": self.priority})
426+
) -> type[RequirementTag]:
427+
entity = build_from_fields(RequirementTag, self.name, {}, {"priority": self.priority})
428428
entity.__doc__ = str(self.description) if self.description else None
429+
entity.priority = self.priority
429430
return entity
430431

431432

packtype/grammar/grammar.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121
DeclEnum,
2222
DeclImport,
2323
DeclInstance,
24-
DeclNormative,
2524
DeclPackage,
25+
DeclRequirement,
2626
DeclScalar,
2727
DeclStruct,
2828
DeclUnion,
@@ -227,7 +227,7 @@ def _resolve(ref: str | ForeignRef) -> int:
227227
package._pt_attach(obj := decl.to_class(source, _resolve))
228228
# Remember this type
229229
known_entities[decl.name] = (obj, decl.position)
230-
case DeclNormative():
230+
case DeclRequirement():
231231
# Check for name collisions
232232
_check_collision(decl.name)
233233
obj = decl.to_class(_resolve)

packtype/grammar/packtype.lark

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ modifier: "@" name "=" (name | ESCAPED_STRING | NUMERIC)
7373
| decl_enum
7474
| decl_struct
7575
| decl_union
76-
| decl_normative
76+
| decl_requirement
7777

7878
// =============================================================================
7979
// Package
@@ -213,16 +213,16 @@ decl_union: "union"i name "{" descr? modifier* field* "}"
213213

214214

215215
// =============================================================================
216-
// Normative Points
216+
// Requirement Tags
217217
//
218-
// vnorm my_feature : P1 "This feature is high priority"
218+
// requirement my_feature : P1 "This feature is high priority"
219219
//
220220
// =============================================================================
221221

222222
// Priority keywords
223223
PRIORITY: /P[0-9]+/
224224

225-
decl_normative: "vnorm"i name ":" PRIORITY descr?
225+
decl_requirement: "requirement"i name ":" PRIORITY descr?
226226

227227
// =============================================================================
228228
// Expressions
@@ -241,7 +241,10 @@ expr: expr_term (OPERATOR expr_term)*
241241
expr_funcs: name "(" (expr ","?)* ")"
242242

243243
NUMERIC: HEX | BINARY | DECIMAL
244-
HEX: (/\b0x[0-9a-f]+\b/i)
244+
245+
// Allowing the following format 0x0000_0000_...
246+
HEX: (/\b0x[0-9a-f]+(?:_[0-9a-f]+)*\b/i)
247+
245248
BINARY: (/\b0b[0-1]+\b/)
246249
DECIMAL: SIGN? /\b[0-9]+\b/
247250
OPERATOR: SIGN

packtype/grammar/transformer.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from ..common.expression import Expression, ExpressionFunction
1313
from ..types.assembly import Packing
1414
from ..types.enum import EnumMode
15-
from ..types.normative import Priority
15+
from ..types.requirement import Priority
1616
from .declarations import (
1717
DeclAlias,
1818
DeclConstant,
@@ -21,8 +21,8 @@
2121
DeclField,
2222
DeclImport,
2323
DeclInstance,
24-
DeclNormative,
2524
DeclPackage,
25+
DeclRequirement,
2626
DeclScalar,
2727
DeclStruct,
2828
DeclUnion,
@@ -307,8 +307,8 @@ def decl_union(self, meta, body):
307307
return DeclUnion(Position(meta.line, meta.column), name, description, mods, remainder)
308308

309309
@v_args(meta=True)
310-
def decl_normative(self, meta, body):
311-
"""Transform a normative point declaration."""
310+
def decl_requirement(self, meta, body):
311+
"""Transform a requirement tag declaration."""
312312
name, priority_token, *remainder = body
313313
if remainder and isinstance(remainder[0], Description):
314314
descr, *remainder = remainder
@@ -317,7 +317,7 @@ def decl_normative(self, meta, body):
317317

318318
priority = Priority[priority_token.value.upper()]
319319

320-
return DeclNormative(Position(meta.line, meta.column), name, priority, descr)
320+
return DeclRequirement(Position(meta.line, meta.column), name, priority, descr)
321321

322322
def variant_default(self, body):
323323
return VariantCondition(conditions=None)

packtype/types/array.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,12 @@
55
import functools
66
import math
77
from collections.abc import Callable, Iterable
8-
from typing import Any, Self
8+
from typing import Any
9+
10+
try:
11+
from typing import Self
12+
except ImportError:
13+
from typing_extensions import Self # noqa: UP035
914

1015
from .bitvector import BitVector, BitVectorWindow
1116
from .numeric import Numeric
@@ -190,6 +195,20 @@ def __str__(self) -> str:
190195
lines.append(f"- Entry[{i}]: {self._pt_entries[i]!s}")
191196
return "\n".join(lines)
192197

198+
def __copy__(self) -> "PackedArray":
199+
"""
200+
Copy this object by unpacking and then packing it again.
201+
:return: A copy of this object
202+
"""
203+
return self._pt_spec._pt_unpack(self._pt_pack())
204+
205+
def __deepcopy__(self, _memo: dict) -> "PackedArray":
206+
"""
207+
Reuse __copy__,
208+
which should already be a deep copy for objects that pack and unpack cleanly.
209+
"""
210+
return self.__copy__()
211+
193212

194213
class UnpackedArray:
195214
def __init__(

packtype/types/assembly.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@
88
from textwrap import indent
99
from typing import Any
1010

11+
try:
12+
from typing import Self
13+
except ImportError:
14+
from typing_extensions import Self # noqa: UP035
15+
1116
from ..svg.render import ElementStyle, SvgConfig, SvgField, SvgRender
1217
from .array import ArraySpec, PackedArray
1318
from .base import Base
@@ -123,7 +128,8 @@ def __getattribute__(self, fname: str):
123128
return finst
124129
# Is this the padding field?
125130
elif fname == "_padding" and self._PT_PADDING > 0:
126-
padding = Scalar[self._PT_PADDING](_pt_bv=self._pt_bv)
131+
lsb, msb = self._PT_RANGES["_padding"]
132+
padding = Scalar[self._PT_PADDING](_pt_bv=self._pt_bv.create_window(msb, lsb))
127133
self._pt_force_set("_padding", padding)
128134
return padding
129135
# If not resolved, forward the attribute error
@@ -382,7 +388,7 @@ def _pt_pack(self) -> int:
382388
return int(self._pt_bv)
383389

384390
@classmethod
385-
def _pt_unpack(cls, packed: int) -> "PackedAssembly":
391+
def _pt_unpack(cls, packed: int) -> Self:
386392
inst = cls()
387393
inst._pt_set(packed)
388394
return inst

packtype/types/base.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -117,13 +117,3 @@ def _list_objs():
117117
print(f"{cnt:10d}: {obj}") # noqa: T201
118118

119119
atexit.register(_list_objs)
120-
121-
def __copy__(self) -> Self:
122-
raise NotImplementedError(
123-
"Please use packtype.utils.basic.copy() to copy a Packtype definition"
124-
)
125-
126-
def __deepcopy__(self, _memo: dict[int, Any]) -> Self:
127-
raise NotImplementedError(
128-
"Please use packtype.utils.basic.copy() to copy a Packtype definition"
129-
)

packtype/types/enum.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@
66
import math
77
from typing import Any
88

9+
try:
10+
from typing import Self
11+
except ImportError:
12+
from typing_extensions import Self # noqa: UP035
13+
914
from .base import Base
1015
from .bitvector import BitVector, BitVectorWindow
1116
from .constant import Constant
@@ -154,8 +159,12 @@ def _pt_as_dict(cls) -> dict[str, int]:
154159
return {n: int(v) for v, n in cls._PT_LKP_INST.items()}
155160

156161
@classmethod
157-
def _pt_cast(cls, value: int) -> None:
162+
def _pt_cast(cls, value: int) -> Self:
158163
if value in cls._PT_LKP_VALUE:
159164
return cls._PT_LKP_VALUE[value]
160165
else:
161166
return cls(value)
167+
168+
@classmethod
169+
def _pt_unpack(cls, packed: int) -> Self:
170+
return cls._pt_cast(packed)

packtype/types/numeric.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
#
44

55

6+
try:
7+
from typing import Self
8+
except ImportError:
9+
from typing_extensions import Self # noqa: UP035
10+
11+
612
class Numeric:
713
def __int__(self) -> int:
814
raise NotImplementedError("Subclass must implement __int__")
@@ -248,3 +254,26 @@ def __ge__(self, other) -> bool:
248254

249255
def __hash__(self) -> int:
250256
return id(self)
257+
258+
@classmethod
259+
def _pt_unpack(cls, _packed: int) -> Self:
260+
"""
261+
Unpack the object from an integer
262+
:param packed: The value to unpack
263+
:return: The unpacked object
264+
"""
265+
raise NotImplementedError
266+
267+
def __copy__(self) -> Self:
268+
"""
269+
Copy this object by unpacking and then packing it again
270+
:return: A copy of this object
271+
"""
272+
return self._pt_unpack(int(self))
273+
274+
def __deepcopy__(self, _memo: dict) -> Self:
275+
"""
276+
Reuse __copy__,
277+
which should already be a deep copy for objects that pack and unpack cleanly.
278+
"""
279+
return self.__copy__()

packtype/types/package.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
from .base import Base
1414
from .constant import Constant
1515
from .enum import Enum
16-
from .normative import NormativePoint
1716
from .primitive import NumericType
17+
from .requirement import RequirementTag
1818
from .scalar import ScalarType
1919
from .struct import Struct
2020
from .union import Union
@@ -24,13 +24,13 @@
2424
class Package(Base):
2525
_PT_ALLOW_DEFAULTS: list[type[Base]] = [Constant]
2626
_PT_FIELDS: dict
27-
_PT_NORMS: dict
27+
_PT_REQUIREMENTS: dict
2828

2929
@classmethod
3030
def _pt_construct(cls, parent: Base) -> None:
3131
super()._pt_construct(parent)
3232
cls._PT_FIELDS = {}
33-
cls._PT_NORMS = {}
33+
cls._PT_REQUIREMENTS = {}
3434
for fname, ftype, fval in cls._pt_definitions():
3535
if inspect.isclass(ftype) and issubclass(ftype, Constant):
3636
cls._pt_attach_constant(fname, ftype(default=fval))
@@ -45,9 +45,9 @@ def _pt_attach_constant(cls, fname: str, finst: Constant) -> Constant:
4545
return finst
4646

4747
@classmethod
48-
def _pt_attach_norm(cls, fname: str, finst: NormativePoint) -> NormativePoint:
48+
def _pt_attach_norm(cls, fname: str, finst: RequirementTag) -> RequirementTag:
4949
finst._PT_ATTACHED_TO = cls
50-
cls._PT_NORMS[fname] = finst
50+
cls._PT_REQUIREMENTS[fname] = finst
5151
cls._PT_FIELDS[finst] = finst
5252
setattr(cls, fname, finst)
5353
return finst
@@ -170,8 +170,11 @@ def _pt_unions(self) -> Iterable[tuple[str, Union]]:
170170
return self._pt_filter_for_class(Union)
171171

172172
@property
173-
def _pt_norms(self) -> Iterable[tuple[str, NormativePoint]]:
174-
return ((vnorm_name, vnorm_inst) for vnorm_name, vnorm_inst in self._PT_NORMS.items())
173+
def _pt_reqs(self) -> Iterable[tuple[str, RequirementTag]]:
174+
return (
175+
(requirement_name, requirement_inst)
176+
for requirement_name, requirement_inst in self._PT_REQUIREMENTS.items()
177+
)
175178

176179
@property
177180
def _pt_structs_and_unions(self) -> Iterable[tuple[str, Struct | Union]]:

0 commit comments

Comments
 (0)