Skip to content

Commit

Permalink
Change representation of null messages
Browse files Browse the repository at this point in the history
Ref. #643
  • Loading branch information
treiher committed Sep 22, 2022
1 parent 6d50056 commit 34df54c
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 26 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,14 @@ CLI:

### Changed

Specification:

- Syntax for defining initial and final states of session (#700)

Model:

- Change representation of null messages (#643)

### Removed

Specification:
Expand Down
15 changes: 4 additions & 11 deletions rflx/graph.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import logging
import re
from copy import copy
from pathlib import Path
from typing import Sequence

from pydotplus import Dot, Edge, Node

from rflx.expression import TRUE, UNDEFINED
from rflx.identifier import ID
from rflx.model import FINAL, FINAL_STATE, INITIAL, AbstractSession, Link, Message
from rflx.model import FINAL_STATE, AbstractSession, Link, Message

log = logging.getLogger(__name__)

Expand Down Expand Up @@ -54,19 +53,13 @@ def _edge_label(link: Link) -> str:
first=str(link.first) if link.first != UNDEFINED else "⋆",
)

msg = copy(message)
if not msg.structure:
# https://github.com/Componolit/RecordFlux/issues/643
# pylint: disable-next = protected-access
msg._structure = [Link(INITIAL, FINAL)]

result = _graph_with_defaults(msg.full_name)
result = _graph_with_defaults(message.full_name)
result.add_node(
Node(name="Initial", fillcolor="#ffffff", shape="circle", width="0.5", label="")
)
for f in msg.fields:
for f in message.fields:
result.add_node(Node(name=f.name))
for i, l in enumerate(msg.structure):
for i, l in enumerate(message.structure):
intermediate_node = f"intermediate_{i}"
result.add_node(
Node(
Expand Down
21 changes: 14 additions & 7 deletions rflx/model/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@ def __init__(

assert len(self.identifier.parts) > 1, "type identifier must contain package"

if not structure:
structure = [Link(INITIAL, FINAL)]

self._structure = sorted(structure)
self._types = types
self._paths_cache: Dict[Field, Set[Tuple[Link, ...]]] = {}
Expand All @@ -142,7 +145,7 @@ def __init__(
self._byte_order = {}

try:
if not state and (structure or types):
if not state and not self.is_null:
self._state.has_unreachable = self._validate()
self._normalize()
fields = self._compute_topological_sorting(self._state.has_unreachable)
Expand Down Expand Up @@ -184,7 +187,7 @@ def __repr__(self) -> str:
return verbose_repr(self, ["identifier", "structure", "types", "checksums", "byte_order"])

def __str__(self) -> str:
if not self.structure or not self.types:
if self.is_null:
return f"type {self.name} is null message"

parameters = "; ".join(
Expand Down Expand Up @@ -220,6 +223,10 @@ def __str__(self) -> str:

return f"type {self.name}{parameters} is\n message\n{indent(fields, 6)}\n end message"

@property
def is_null(self) -> bool:
return self._structure == [Link(INITIAL, FINAL)] and not self._types

@property
def direct_dependencies(self) -> List[mty.Type]:
return [*self._types.values(), self]
Expand Down Expand Up @@ -839,7 +846,7 @@ def __init__(
self.error.propagate()

def verify(self) -> None:
if self.structure or self.types:
if not self.is_null:
self._verify_expression_types()
self._verify_expressions()
self._verify_checksums()
Expand Down Expand Up @@ -910,7 +917,7 @@ def type_(self) -> rty.Message:
)
for p in self.paths(FINAL)
}
if self.structure
if not self.is_null
else set(),
{f.identifier: t.type_ for f, t in self._state.parameter_types.items()},
{f.identifier: t.type_ for f, t in self._state.field_types.items()},
Expand Down Expand Up @@ -1005,7 +1012,7 @@ def typed_variable(expression: expr.Expr) -> expr.Expr:
self.location,
)
else:
if not self.structure:
if self.is_null:
return expr.Number(0)

fields = list(self.fields)
Expand Down Expand Up @@ -1164,7 +1171,7 @@ def remove_variable_prefix(expression: expr.Expr) -> expr.Expr:
)

def max_size(self) -> expr.Number:
if not self.structure:
if self.is_null:
return expr.Number(0)

if self.has_implicit_size:
Expand All @@ -1183,7 +1190,7 @@ def max_size(self) -> expr.Number:
return max_size

def max_field_sizes(self) -> Dict[Field, expr.Number]:
if not self.structure:
if self.is_null:
return {}

if self.has_implicit_size:
Expand Down
2 changes: 1 addition & 1 deletion rflx/model/type_.py
Original file line number Diff line number Diff line change
Expand Up @@ -603,7 +603,7 @@ def __init__(self, identifier: StrID, element_type: Type, location: Location = N
location,
)

if not element_type.structure:
if element_type.is_null:
self.error.extend(
[
error,
Expand Down
8 changes: 1 addition & 7 deletions rflx/pyrflx/typevalue.py
Original file line number Diff line number Diff line change
Expand Up @@ -741,9 +741,7 @@ def _valid_refinement_condition(self, refinement: "RefinementValue") -> bool:

def _next_link(self, source_field_name: str) -> ty.Optional[Link]:
field = Field(source_field_name)
if field == FINAL or not self._type.structure:
# structure is empty in case of NULL message
# https://github.com/Componolit/RecordFlux/issues/643
if field == FINAL:
return None
for link in self._type.outgoing(field):
if self._simplified(link.condition) == TRUE:
Expand All @@ -758,10 +756,6 @@ def _next_field(self, field_name: str, append_to_path: bool = False) -> str:
if append_to_path and next_link is not None:
self._path.append(next_link)

if next_link is None and field_name == INITIAL.name:
# the INITIAL field has no outgoing links in case of NULL message
# https://github.com/Componolit/RecordFlux/issues/643
return FINAL.name
return next_link.target.name if next_link is not None else ""

def _prev_field(self, fld: str) -> str:
Expand Down

0 comments on commit 34df54c

Please sign in to comment.