Project

General

Profile

Feature #458 » 0003-generate_packets.py-allow-compatible-fields-with-sam.patch

main - Alina Lenk, 04/16/2024 01:06 AM

View differences:

common/generate_packets.py
dataio stream."""
raise NotImplementedError
def _compat_keys(self, location: Location):
"""Internal helper function. Yield keys to compare for
type compatibility. See is_type_compatible()"""
yield self.get_code_declaration(location)
yield self.get_code_handle_param(location)
yield self.get_code_handle_arg(location)
yield self.get_code_fill(location)
yield self.complex
if self.complex:
yield self.get_code_init(location)
yield self.get_code_free(location)
def is_type_compatible(self, other: "FieldType") -> bool:
"""Determine whether two field types can be used interchangeably as
part of the packet struct, i.e. differ in dataio transmission only"""
if other is self:
return True
loc = Location("compat_test_field_name")
return all(
a == b
for a, b in zip_longest(
self._compat_keys(loc),
other._compat_keys(loc),
)
)
class BasicType(FieldType):
"""Type information for a field without any specialized treatment"""
......
see FieldType.complex"""
return self.type_info.complex
def is_compatible(self, other: "Field") -> bool:
"""Whether two field objects are variants of the same field, i.e.
type-compatible in the packet struct and mutually exclusive based
on their required capabilities.
Note that this function does not test field name."""
return bool(
(
(self.flags.add_caps & other.flags.remove_caps)
or
(self.flags.remove_caps & other.flags.add_caps)
)
and
self.type_info.is_type_compatible(other.type_info)
)
def present_with_caps(self, caps: typing.Container[str]) -> bool:
"""Determine whether this field should be part of a variant with the
given capabilities"""
......
self.negcaps = set(negcaps)
self.fields = [
field
for field in packet.fields
for field in packet.all_fields
if field.present_with_caps(self.poscaps)
]
self.key_fields = [field for field in self.fields if field.is_key]
......
dirs: Directions
"""Which directions this packet can be sent in"""
fields: "list[Field]"
"""List of all fields of this packet"""
all_fields: "list[Field]"
"""List of all fields of this packet, including name duplicates for
different capability variants that are compatible.
key_fields: "list[Field]"
"""List of only the key fields of this packet"""
Only relevant for creating Variants; self.fields should be used when
not dealing with capabilities or Variants."""
other_fields: "list[Field]"
"""List of only the non-key fields of this packet"""
fields: "list[Field]"
"""List of all fields of this packet, with only one field of each name"""
variants: "list[Variant]"
"""List of all variants of this packet"""
......
raise ValueError(f"no directions defined for {self.name}")
self.dirs = Directions(dirs)
self.fields = [
raw_fields = [
field
for line in lines
for field in Field.parse(self.cfg, line, resolve_type)
]
self.key_fields = [field for field in self.fields if field.is_key]
self.other_fields = [field for field in self.fields if not field.is_key]
# put key fields before all others
key_fields = [field for field in raw_fields if field.is_key]
other_fields = [field for field in raw_fields if not field.is_key]
self.all_fields = key_fields + other_fields
self.fields = []
# check for duplicate field names
for next_field in self.all_fields:
duplicates = [field for field in self.fields if field.name == next_field.name]
if not duplicates:
self.fields.append(next_field)
continue
if not all(field.is_compatible(next_field) for field in duplicates):
raise ValueError(f"incompatible fields with duplicate name: {packet_type}({packet_number}).{next_field.name}")
# valid, since self.fields is already set
if self.no_packet:
......
raise ValueError(f"requested dsend for {self.name} without fields isn't useful")
# create cap variants
all_caps = self.all_caps # valid, since self.fields is already set
all_caps = self.all_caps # valid, since self.all_fields is already set
self.variants = [
Variant(caps, all_caps.difference(caps), self, i + 100)
for i, caps in enumerate(powerset(sorted(all_caps)))
......
@property
def all_caps(self) -> "set[str]":
"""Set of all capabilities affecting this packet"""
return {cap for field in self.fields for cap in field.all_caps}
return {cap for field in self.all_fields for cap in field.all_caps}
@property
def complex(self) -> bool:
......
body = "".join(
prefix(" ", field.get_declar())
for field in chain(self.key_fields, self.other_fields)
for field in self.fields
) or """\
char __dummy; /* to avoid malloc(0); */
"""
(1-1/2)