From 9eb650b2e574483945104ef477de633dd064d42d Mon Sep 17 00:00:00 2001 From: Tobias Reiher Date: Tue, 8 Dec 2020 11:49:45 +0100 Subject: [PATCH] Fix type checking of messages Ref. #522 --- rflx/model/message.py | 17 ++++++++-------- tests/unit/model/message_test.py | 33 +++++++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/rflx/model/message.py b/rflx/model/message.py index b07705486..684ceca84 100644 --- a/rflx/model/message.py +++ b/rflx/model/message.py @@ -655,6 +655,7 @@ def __verify_expression_types(self) -> None: types: Dict[ID, mty.Type] = {} def typed_variable(expression: expr.Expr) -> expr.Expr: + expression = copy(expression) if isinstance(expression, expr.Variable): if expression.name.lower() == "message": expression.type_ = rty.OPAQUE @@ -683,15 +684,15 @@ def typed_variable(expression: expr.Expr) -> expr.Expr: if l.source in self.types: types[l.source.identifier] = self.types[l.source] - l.condition = l.condition.substituted(typed_variable) - l.size = l.size.substituted(typed_variable) - l.first = l.first.substituted(typed_variable) - - for t in [l.condition, l.size, l.first]: - if t == expr.UNDEFINED: + for expression in [ + l.condition.substituted(typed_variable), + l.size.substituted(typed_variable), + l.first.substituted(typed_variable), + ]: + if expression == expr.UNDEFINED: continue - error = t.check_type(rty.Any()) + error = expression.check_type(rty.Any()) self.error.extend(error) @@ -700,7 +701,7 @@ def typed_variable(expression: expr.Expr) -> expr.Expr: "on path " + " -> ".join(f.name for f in path), Subsystem.MODEL, Severity.INFO, - t.location, + expression.location, ) def __verify_expressions(self) -> None: diff --git a/tests/unit/model/message_test.py b/tests/unit/model/message_test.py index 9f351820c..b9c8823f6 100644 --- a/tests/unit/model/message_test.py +++ b/tests/unit/model/message_test.py @@ -679,7 +679,7 @@ def test_subsequent_variable() -> None: ) -def test_reference_to_optional_field() -> None: +def test_reference_to_optional_field_1() -> None: structure = [ Link(INITIAL, Field("F1")), Link(Field("F1"), Field("F2"), Equal(Variable("F1"), TRUE)), @@ -704,6 +704,37 @@ def test_reference_to_optional_field() -> None: ) +def test_reference_to_optional_field_2() -> None: + structure = [ + Link(INITIAL, Field("Flag")), + Link(Field("Flag"), Field("Opt"), Equal(Variable("Flag"), Number(1))), + Link(Field("Flag"), Field("Any"), NotEqual(Variable("Flag"), Number(1))), + Link(Field("Opt"), Field("Any")), + Link( + Field("Any"), + Field("Data"), + size=Mul( + Variable("Opt", location=Location((10, 30))), Number(8), location=Location((10, 20)) + ), + ), + Link(Field("Data"), FINAL), + ] + types = { + Field("Flag"): MODULAR_INTEGER, + Field("Opt"): MODULAR_INTEGER, + Field("Any"): MODULAR_INTEGER, + Field("Data"): OPAQUE, + } + assert_message_model_error( + structure, + types, + r"^" + r':10:30: model: error: undefined variable "Opt"\n' + r":10:20: model: info: on path Flag -> Any -> Data" + r"$", + ) + + def test_invalid_use_of_size_attribute() -> None: structure = [ Link(INITIAL, Field("F1")),