Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions packtype/grammar/declarations.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from ..types.base import Base
from ..types.constant import Constant
from ..types.enum import Enum, EnumMode
from ..types.normative import NormativePoint, Priority
from ..types.requirement import Priority, RequirementTag
from ..types.scalar import Scalar
from ..types.struct import Struct
from ..types.union import Union
Expand Down Expand Up @@ -407,8 +407,8 @@ def to_class(


@dataclass
class DeclNormative:
"""Represents a normative point declaration."""
class DeclRequirement:
"""Represents a requirement tag declaration."""

position: Position
name: str
Expand All @@ -423,9 +423,10 @@ def to_class(
],
int | type[Base],
],
) -> type[NormativePoint]:
entity = build_from_fields(NormativePoint, self.name, {}, {"priority": self.priority})
) -> type[RequirementTag]:
entity = build_from_fields(RequirementTag, self.name, {}, {"priority": self.priority})
entity.__doc__ = str(self.description) if self.description else None
entity.priority = self.priority
return entity


Expand Down
4 changes: 2 additions & 2 deletions packtype/grammar/grammar.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
DeclEnum,
DeclImport,
DeclInstance,
DeclNormative,
DeclPackage,
DeclRequirement,
DeclScalar,
DeclStruct,
DeclUnion,
Expand Down Expand Up @@ -227,7 +227,7 @@ def _resolve(ref: str | ForeignRef) -> int:
package._pt_attach(obj := decl.to_class(source, _resolve))
# Remember this type
known_entities[decl.name] = (obj, decl.position)
case DeclNormative():
case DeclRequirement():
# Check for name collisions
_check_collision(decl.name)
obj = decl.to_class(_resolve)
Expand Down
13 changes: 8 additions & 5 deletions packtype/grammar/packtype.lark
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ modifier: "@" name "=" (name | ESCAPED_STRING | NUMERIC)
| decl_enum
| decl_struct
| decl_union
| decl_normative
| decl_requirement

// =============================================================================
// Package
Expand Down Expand Up @@ -213,16 +213,16 @@ decl_union: "union"i name "{" descr? modifier* field* "}"


// =============================================================================
// Normative Points
// Requirement Tags
//
// vnorm my_feature : P1 "This feature is high priority"
// requirement my_feature : P1 "This feature is high priority"
//
// =============================================================================

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

decl_normative: "vnorm"i name ":" PRIORITY descr?
decl_requirement: "requirement"i name ":" PRIORITY descr?

// =============================================================================
// Expressions
Expand All @@ -241,7 +241,10 @@ expr: expr_term (OPERATOR expr_term)*
expr_funcs: name "(" (expr ","?)* ")"

NUMERIC: HEX | BINARY | DECIMAL
HEX: (/\b0x[0-9a-f]+\b/i)

// Allowing the following format 0x0000_0000_...
HEX: (/\b0x[0-9a-f]+(?:_[0-9a-f]+)*\b/i)

BINARY: (/\b0b[0-1]+\b/)
DECIMAL: SIGN? /\b[0-9]+\b/
OPERATOR: SIGN
Expand Down
10 changes: 5 additions & 5 deletions packtype/grammar/transformer.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from ..common.expression import Expression, ExpressionFunction
from ..types.assembly import Packing
from ..types.enum import EnumMode
from ..types.normative import Priority
from ..types.requirement import Priority
from .declarations import (
DeclAlias,
DeclConstant,
Expand All @@ -21,8 +21,8 @@
DeclField,
DeclImport,
DeclInstance,
DeclNormative,
DeclPackage,
DeclRequirement,
DeclScalar,
DeclStruct,
DeclUnion,
Expand Down Expand Up @@ -307,8 +307,8 @@ def decl_union(self, meta, body):
return DeclUnion(Position(meta.line, meta.column), name, description, mods, remainder)

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

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

return DeclNormative(Position(meta.line, meta.column), name, priority, descr)
return DeclRequirement(Position(meta.line, meta.column), name, priority, descr)

def variant_default(self, body):
return VariantCondition(conditions=None)
Expand Down
21 changes: 20 additions & 1 deletion packtype/types/array.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@
import functools
import math
from collections.abc import Callable, Iterable
from typing import Any, Self
from typing import Any

try:
from typing import Self
except ImportError:
from typing_extensions import Self # noqa: UP035

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

def __copy__(self) -> "PackedArray":
"""
Copy this object by unpacking and then packing it again.
:return: A copy of this object
"""
return self._pt_spec._pt_unpack(self._pt_pack())

def __deepcopy__(self, _memo: dict) -> "PackedArray":
"""
Reuse __copy__,
which should already be a deep copy for objects that pack and unpack cleanly.
"""
return self.__copy__()


class UnpackedArray:
def __init__(
Expand Down
10 changes: 8 additions & 2 deletions packtype/types/assembly.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@
from textwrap import indent
from typing import Any

try:
from typing import Self
except ImportError:
from typing_extensions import Self # noqa: UP035

from ..svg.render import ElementStyle, SvgConfig, SvgField, SvgRender
from .array import ArraySpec, PackedArray
from .base import Base
Expand Down Expand Up @@ -123,7 +128,8 @@ def __getattribute__(self, fname: str):
return finst
# Is this the padding field?
elif fname == "_padding" and self._PT_PADDING > 0:
padding = Scalar[self._PT_PADDING](_pt_bv=self._pt_bv)
lsb, msb = self._PT_RANGES["_padding"]
padding = Scalar[self._PT_PADDING](_pt_bv=self._pt_bv.create_window(msb, lsb))
self._pt_force_set("_padding", padding)
return padding
# If not resolved, forward the attribute error
Expand Down Expand Up @@ -382,7 +388,7 @@ def _pt_pack(self) -> int:
return int(self._pt_bv)

@classmethod
def _pt_unpack(cls, packed: int) -> "PackedAssembly":
def _pt_unpack(cls, packed: int) -> Self:
inst = cls()
inst._pt_set(packed)
return inst
Expand Down
10 changes: 0 additions & 10 deletions packtype/types/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,13 +117,3 @@ def _list_objs():
print(f"{cnt:10d}: {obj}") # noqa: T201

atexit.register(_list_objs)

def __copy__(self) -> Self:
raise NotImplementedError(
"Please use packtype.utils.basic.copy() to copy a Packtype definition"
)

def __deepcopy__(self, _memo: dict[int, Any]) -> Self:
raise NotImplementedError(
"Please use packtype.utils.basic.copy() to copy a Packtype definition"
)
11 changes: 10 additions & 1 deletion packtype/types/enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
import math
from typing import Any

try:
from typing import Self
except ImportError:
from typing_extensions import Self # noqa: UP035

from .base import Base
from .bitvector import BitVector, BitVectorWindow
from .constant import Constant
Expand Down Expand Up @@ -154,8 +159,12 @@ def _pt_as_dict(cls) -> dict[str, int]:
return {n: int(v) for v, n in cls._PT_LKP_INST.items()}

@classmethod
def _pt_cast(cls, value: int) -> None:
def _pt_cast(cls, value: int) -> Self:
if value in cls._PT_LKP_VALUE:
return cls._PT_LKP_VALUE[value]
else:
return cls(value)

@classmethod
def _pt_unpack(cls, packed: int) -> Self:
return cls._pt_cast(packed)
29 changes: 29 additions & 0 deletions packtype/types/numeric.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
#


try:
from typing import Self
except ImportError:
from typing_extensions import Self # noqa: UP035


class Numeric:
def __int__(self) -> int:
raise NotImplementedError("Subclass must implement __int__")
Expand Down Expand Up @@ -248,3 +254,26 @@ def __ge__(self, other) -> bool:

def __hash__(self) -> int:
return id(self)

@classmethod
def _pt_unpack(cls, _packed: int) -> Self:
"""
Unpack the object from an integer
:param packed: The value to unpack
:return: The unpacked object
"""
raise NotImplementedError

def __copy__(self) -> Self:
"""
Copy this object by unpacking and then packing it again
:return: A copy of this object
"""
return self._pt_unpack(int(self))

def __deepcopy__(self, _memo: dict) -> Self:
"""
Reuse __copy__,
which should already be a deep copy for objects that pack and unpack cleanly.
"""
return self.__copy__()
17 changes: 10 additions & 7 deletions packtype/types/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
from .base import Base
from .constant import Constant
from .enum import Enum
from .normative import NormativePoint
from .primitive import NumericType
from .requirement import RequirementTag
from .scalar import ScalarType
from .struct import Struct
from .union import Union
Expand All @@ -24,13 +24,13 @@
class Package(Base):
_PT_ALLOW_DEFAULTS: list[type[Base]] = [Constant]
_PT_FIELDS: dict
_PT_NORMS: dict
_PT_REQUIREMENTS: dict

@classmethod
def _pt_construct(cls, parent: Base) -> None:
super()._pt_construct(parent)
cls._PT_FIELDS = {}
cls._PT_NORMS = {}
cls._PT_REQUIREMENTS = {}
for fname, ftype, fval in cls._pt_definitions():
if inspect.isclass(ftype) and issubclass(ftype, Constant):
cls._pt_attach_constant(fname, ftype(default=fval))
Expand All @@ -45,9 +45,9 @@ def _pt_attach_constant(cls, fname: str, finst: Constant) -> Constant:
return finst

@classmethod
def _pt_attach_norm(cls, fname: str, finst: NormativePoint) -> NormativePoint:
def _pt_attach_norm(cls, fname: str, finst: RequirementTag) -> RequirementTag:
finst._PT_ATTACHED_TO = cls
cls._PT_NORMS[fname] = finst
cls._PT_REQUIREMENTS[fname] = finst
cls._PT_FIELDS[finst] = finst
setattr(cls, fname, finst)
return finst
Expand Down Expand Up @@ -170,8 +170,11 @@ def _pt_unions(self) -> Iterable[tuple[str, Union]]:
return self._pt_filter_for_class(Union)

@property
def _pt_norms(self) -> Iterable[tuple[str, NormativePoint]]:
return ((vnorm_name, vnorm_inst) for vnorm_name, vnorm_inst in self._PT_NORMS.items())
def _pt_reqs(self) -> Iterable[tuple[str, RequirementTag]]:
return (
(requirement_name, requirement_inst)
for requirement_name, requirement_inst in self._PT_REQUIREMENTS.items()
)

@property
def _pt_structs_and_unions(self) -> Iterable[tuple[str, Struct | Union]]:
Expand Down
8 changes: 6 additions & 2 deletions packtype/types/primitive.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,10 @@ def value(self) -> int:
return int(self._pt_bv)

@value.setter
def value(self, value: int) -> int:
def value(self, value: int) -> None:
self._pt_set(value)

def _pt_set(self, value: int) -> int:
def _pt_set(self, value: int) -> None:
value = int(value)
if value < 0 or (self._pt_width > 0 and value > self._pt_mask):
raise PrimitiveValueError(
Expand All @@ -98,6 +98,10 @@ def __int__(self) -> int:
def __float__(self) -> float:
return float(int(self))

@classmethod
def _pt_unpack(cls, packed: int) -> Self:
return cls(packed)


class NumericPrimitive(NumericType, metaclass=MetaPrimitive):
@classmethod
Expand Down
14 changes: 7 additions & 7 deletions packtype/types/normative.py → packtype/types/requirement.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@


class Priority(Enum):
"""Priority levels for normative points."""
"""Priority levels for requirement tags."""

P0 = "P0"
P1 = "P1"
Expand All @@ -17,12 +17,12 @@ def __str__(self):
return self.value


class NormativePoint(Base):
class RequirementTag(Base):
"""
Represents a normative point declaration inside a Packtype package.
Represents a RequirementTag declaration inside a Packtype package.

A NormativePoint marks an element with a defined priority level
(P0-P3) and optional description. Created when parsing `vnorm`
A RequirementTag marks an element with a defined priority level
(P0-P3) and optional description. Created when parsing `requirement`
declarations.
"""

Expand All @@ -39,8 +39,8 @@ def __init__(self, name: str, priority: Priority, description: str | None = None
def __repr__(self) -> str:
"""Compact debug-friendly representation."""
if self.description:
return f"<NormativePoint {self.name}: {self.priority.value} — {self.description}>"
return f"<NormativePoint {self.name}: {self.priority.value}>"
return f"<RequirementTag {self.name}: {self.priority.value} — {self.description}>"
return f"<RequirementTag {self.name}: {self.priority.value}>"

def __str__(self) -> str:
"""Human-readable string representation."""
Expand Down
Loading