Ejemplo n.º 1
0
    def create_present_function() -> UnitPart:
        specification = FunctionSpecification(
            "Present", "Boolean",
            [Parameter(["Ctx"], "Context"),
             Parameter(["Fld"], "Field")])

        return UnitPart(
            [SubprogramDeclaration(specification)],
            [
                ExpressionFunctionDeclaration(
                    specification,
                    AndThen(
                        Call("Structural_Valid", [
                            Indexed(Variable("Ctx.Cursors"), Variable("Fld"))
                        ]),
                        Less(
                            Selected(
                                Indexed(Variable("Ctx.Cursors"),
                                        Variable("Fld")), "First"),
                            Add(
                                Selected(
                                    Indexed(Variable("Ctx.Cursors"),
                                            Variable("Fld")), "Last"),
                                Number(1),
                            ),
                        ),
                    ),
                )
            ],
        )
Ejemplo n.º 2
0
    def create_structural_valid_function() -> UnitPart:
        specification = FunctionSpecification(
            "Structural_Valid",
            "Boolean",
            [Parameter(["Ctx"], "Context"),
             Parameter(["Fld"], "Field")],
        )

        return UnitPart(
            [SubprogramDeclaration(specification)],
            [
                ExpressionFunctionDeclaration(
                    specification,
                    And(
                        Or(*[
                            Equal(
                                Selected(
                                    Indexed(Variable("Ctx.Cursors"),
                                            Variable("Fld")), "State"),
                                Variable(s),
                            ) for s in ("S_Valid", "S_Structural_Valid")
                        ])),
                )
            ],
        )
Ejemplo n.º 3
0
    def create_invalid_function() -> UnitPart:
        specification = FunctionSpecification(
            "Invalid", "Boolean",
            [Parameter(["Ctx"], "Context"),
             Parameter(["Fld"], "Field")])

        return UnitPart(
            [SubprogramDeclaration(specification)],
            [
                ExpressionFunctionDeclaration(
                    specification,
                    Or(
                        Equal(
                            Selected(
                                Indexed(Variable("Ctx.Cursors"),
                                        Variable("Fld")), "State"),
                            Variable("S_Invalid"),
                        ),
                        Equal(
                            Selected(
                                Indexed(Variable("Ctx.Cursors"),
                                        Variable("Fld")), "State"),
                            Variable("S_Incomplete"),
                        ),
                    ),
                )
            ],
        )
Ejemplo n.º 4
0
 def extract_function(self, type_name: str) -> Subprogram:
     return GenericFunctionInstantiation(
         "Extract",
         FunctionSpecification(
             f"{self.types.types}.Extract",
             type_name,
             [Parameter(["Buffer"], self.types.bytes), Parameter(["Offset"], self.types.offset)],
         ),
         [self.types.index, self.types.byte, self.types.bytes, self.types.offset, type_name],
     )
Ejemplo n.º 5
0
    def create_valid_function() -> UnitPart:
        specification = FunctionSpecification(
            "Valid", "Boolean",
            [Parameter(["Ctx"], "Context"),
             Parameter(["Fld"], "Field")])

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification,
                    [
                        Postcondition(
                            If([(
                                Result("Valid"),
                                And(
                                    Call(
                                        "Structural_Valid",
                                        [Variable("Ctx"),
                                         Variable("Fld")],
                                    ),
                                    Call("Present",
                                         [Variable("Ctx"),
                                          Variable("Fld")]),
                                ),
                            )])),
                    ],
                )
            ],
            [
                ExpressionFunctionDeclaration(
                    specification,
                    AndThen(
                        Equal(
                            Selected(
                                Indexed(Variable("Ctx.Cursors"),
                                        Variable("Fld")), "State"),
                            Variable("S_Valid"),
                        ),
                        Less(
                            Selected(
                                Indexed(Variable("Ctx.Cursors"),
                                        Variable("Fld")), "First"),
                            Add(
                                Selected(
                                    Indexed(Variable("Ctx.Cursors"),
                                            Variable("Fld")), "Last"),
                                Number(1),
                            ),
                        ),
                    ),
                )
            ],
        )
Ejemplo n.º 6
0
 def insert_function(self, type_name: ID) -> Subprogram:
     return GenericProcedureInstantiation(
         "Insert",
         ProcedureSpecification(
             const.TYPES * "Insert",
             [
                 Parameter(["Val"], type_name),
                 InOutParameter(["Buffer"], const.TYPES_BYTES),
                 Parameter(["Offset"], const.TYPES_OFFSET),
             ],
         ),
         [common.prefixed_type_name(type_name, self.prefix)],
     )
Ejemplo n.º 7
0
 def extract_function(self, type_name: ID) -> Subprogram:
     return GenericFunctionInstantiation(
         "Extract",
         FunctionSpecification(
             const.TYPES * "Extract",
             type_name,
             [
                 Parameter(["Buffer"], const.TYPES_BYTES),
                 Parameter(["Offset"], const.TYPES_OFFSET),
             ],
         ),
         [common.prefixed_type_name(type_name, self.prefix)],
     )
Ejemplo n.º 8
0
 def insert_function(self, type_name: str) -> Subprogram:
     return GenericProcedureInstantiation(
         "Insert",
         ProcedureSpecification(
             f"{self.types.types}.Insert",
             [
                 Parameter(["Val"], type_name),
                 InOutParameter(["Buffer"], self.types.bytes),
                 Parameter(["Offset"], self.types.offset),
             ],
         ),
         [self.types.index, self.types.byte, self.types.bytes, self.types.offset, type_name],
     )
Ejemplo n.º 9
0
    def create_valid_message_function(self, message: Message) -> UnitPart:
        specification = FunctionSpecification("Valid_Message", "Boolean",
                                              [Parameter(["Ctx"], "Context")])

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification,
                    [
                        Precondition(
                            Call(
                                self.prefix * message.identifier *
                                "Has_Buffer",
                                [Variable("Ctx")],
                            ))
                    ],
                )
            ],
            private=[
                ExpressionFunctionDeclaration(
                    specification,
                    self.valid_message_condition(message),
                )
            ],
        )
Ejemplo n.º 10
0
    def create_composite_accessor_procedures(self, composite_fields: Sequence[Field]) -> UnitPart:
        def specification(field: Field) -> ProcedureSpecification:
            return ProcedureSpecification(f"Get_{field.name}", [Parameter(["Ctx"], "Context")])

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification(f),
                    [
                        Precondition(
                            And(
                                VALID_CONTEXT,
                                Call("Has_Buffer", [Name("Ctx")]),
                                Call("Present", [Name("Ctx"), Name(f.affixed_name)]),
                            )
                        )
                    ],
                    [
                        FormalSubprogramDeclaration(
                            ProcedureSpecification(
                                f"Process_{f.name}", [Parameter([f.name], self.types.bytes)]
                            )
                        )
                    ],
                )
                for f in composite_fields
            ],
            [
                SubprogramBody(
                    specification(f),
                    [
                        ObjectDeclaration(
                            ["First"],
                            self.types.index,
                            Call(
                                self.types.byte_index,
                                [Selected(Indexed("Ctx.Cursors", Name(f.affixed_name)), "First")],
                            ),
                            True,
                        ),
                        ObjectDeclaration(
                            ["Last"],
                            self.types.index,
                            Call(
                                self.types.byte_index,
                                [Selected(Indexed("Ctx.Cursors", Name(f.affixed_name)), "Last")],
                            ),
                            True,
                        ),
                    ],
                    [
                        CallStatement(
                            f"Process_{f.name}",
                            [Slice("Ctx.Buffer.all", Name("First"), Name("Last"))],
                        )
                    ],
                )
                for f in composite_fields
            ],
        )
Ejemplo n.º 11
0
    def create_incomplete_function() -> UnitPart:
        specification = FunctionSpecification(
            "Incomplete", "Boolean", [Parameter(["Ctx"], "Context"), Parameter(["Fld"], "Field")]
        )

        return UnitPart(
            [SubprogramDeclaration(specification, [Precondition(VALID_CONTEXT)])],
            [
                ExpressionFunctionDeclaration(
                    specification,
                    Equal(
                        Selected(Indexed("Ctx.Cursors", Name("Fld")), "State"), Name("S_Incomplete")
                    ),
                )
            ],
        )
Ejemplo n.º 12
0
 def _create_init_proc(self, slots: Sequence[NumberedSlotInfo]) -> UnitPart:
     proc = ProcedureSpecification(
         "Initialize",
         [OutParameter(["S"], "Slots"),
          Parameter(["M"], "Memory")])
     return UnitPart(
         [
             SubprogramDeclaration(
                 proc,
                 [Postcondition(Call("Initialized", [Variable("S")]))]),
         ],
         [
             SubprogramBody(
                 proc,
                 declarations=[],
                 statements=([
                     Assignment(
                         "S" * self._slot_name(slot.slot_id),
                         UnrestrictedAccess(
                             Variable(ID(f"M.Slot_{slot.slot_id}"))),
                     ) for slot in slots
                 ] if slots else [NullStatement()]),
                 aspects=[SparkMode(off=True)],
             )
         ],
     )
Ejemplo n.º 13
0
 def specification_bounded(field: Field) -> ProcedureSpecification:
     return ProcedureSpecification(
         f"Initialize_Bounded_{field.name}",
         [
             InOutParameter(["Ctx"], "Context"),
             Parameter(["Length"], const.TYPES_BIT_LENGTH)
         ],
     )
Ejemplo n.º 14
0
 def specification(field: Field) -> ProcedureSpecification:
     return ProcedureSpecification(
         f"Get_{field.name}",
         [
             Parameter(["Ctx"], "Context"),
             OutParameter(["Data"], const.TYPES_BYTES)
         ],
     )
Ejemplo n.º 15
0
        def specification(field: Field,
                          field_type: Type) -> FunctionSpecification:
            if field_type.package == BUILTINS_PACKAGE:
                type_name = ID(field_type.name)
            else:
                type_name = self.prefix * field_type.identifier

            return FunctionSpecification(f"Get_{field.name}", type_name,
                                         [Parameter(["Ctx"], "Context")])
Ejemplo n.º 16
0
 def _create_init_pred(self, slots: Sequence[NumberedSlotInfo]) -> UnitPart:
     return UnitPart([
         ExpressionFunctionDeclaration(
             FunctionSpecification("Initialized", "Boolean",
                                   [Parameter(["S"], "Slots")]),
             And(*[
                 NotEqual(
                     Variable("S" * self._slot_name(slot.slot_id)),
                     Variable("null"),
                 ) for slot in slots
             ]),
         )
     ])
Ejemplo n.º 17
0
 def specification(field: Field, field_type: Type) -> ProcedureSpecification:
     type_name = (
         field_type.enum_name
         if isinstance(field_type, Enumeration) and field_type.always_valid
         else field_type.name
     )
     return ProcedureSpecification(
         f"Set_{field.name}",
         [
             InOutParameter(["Ctx"], "Context"),
             Parameter(["Val"], f"{message.package}.{type_name}"),
         ],
     )
Ejemplo n.º 18
0
    def create_valid_message_function(self, message: Message) -> UnitPart:
        specification = FunctionSpecification(
            "Valid_Message", "Boolean", [Parameter(["Ctx"], "Context")]
        )

        return UnitPart(
            [SubprogramDeclaration(specification, [Precondition(VALID_CONTEXT)])],
            [
                ExpressionFunctionDeclaration(
                    specification,
                    valid_message_condition(message).simplified(self.common.substitution(message)),
                )
            ],
        )
Ejemplo n.º 19
0
 def formal_parameters(
         field: Field) -> Sequence[FormalSubprogramDeclaration]:
     return [
         FormalSubprogramDeclaration(
             ProcedureSpecification(
                 f"Process_{field.name}",
                 [OutParameter([field.name], const.TYPES_BYTES)],
             )),
         FormalSubprogramDeclaration(
             FunctionSpecification(
                 "Valid_Length",
                 "Boolean",
                 [Parameter(["Length"], const.TYPES_LENGTH)],
             )),
     ]
Ejemplo n.º 20
0
    def create_incomplete_message_function(message: Message) -> UnitPart:
        specification = FunctionSpecification("Incomplete_Message", "Boolean",
                                              [Parameter(["Ctx"], "Context")])

        return UnitPart(
            [SubprogramDeclaration(specification)],
            [
                ExpressionFunctionDeclaration(
                    specification,
                    Or(*[
                        Call("Incomplete",
                             [Variable("Ctx"),
                              Variable(f.affixed_name)])
                        for f in message.fields
                    ]),
                )
            ],
        )
Ejemplo n.º 21
0
    def create_valid_message_function(message: Message) -> UnitPart:
        specification = FunctionSpecification("Valid_Message", "Boolean",
                                              [Parameter(["Ctx"], "Context")])

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification,
                    [Precondition(Call("Has_Buffer", [Variable("Ctx")]))],
                )
            ],
            [
                ExpressionFunctionDeclaration(
                    specification,
                    valid_message_condition(message).substituted(
                        common.substitution(message)).simplified(),
                )
            ],
        )
Ejemplo n.º 22
0
        def specification(field: Field,
                          field_type: Type) -> ProcedureSpecification:
            if field_type.package == BUILTINS_PACKAGE:
                type_name = ID(field_type.name)
            elif isinstance(field_type,
                            Enumeration) and field_type.always_valid:
                type_name = common.prefixed_type_name(
                    common.full_enum_name(field_type), self.prefix)
            else:
                type_name = common.prefixed_type_name(field_type.identifier,
                                                      self.prefix)

            return ProcedureSpecification(
                f"Set_{field.name}",
                [
                    InOutParameter(["Ctx"], "Context"),
                    Parameter(["Val"], type_name)
                ],
            )
Ejemplo n.º 23
0
 def _create_global_allocated_pred(
         self, slots: Sequence[NumberedSlotInfo]) -> UnitPart:
     return UnitPart([
         ExpressionFunctionDeclaration(
             FunctionSpecification("Global_Allocated", "Boolean",
                                   [Parameter(["S"], "Slots")]),
             And(
                 *[
                     Equal(
                         Variable("S" * self._slot_name(slot.slot_id)),
                         Variable("null"),
                     ) for slot in slots if slot.global_
                 ],
                 *[
                     NotEqual(
                         Variable("S" * self._slot_name(slot.slot_id)),
                         Variable("null"),
                     ) for slot in slots if not slot.global_
                 ],
             ),
         )
     ])
Ejemplo n.º 24
0
    def create_incomplete_message_function() -> UnitPart:
        specification = FunctionSpecification("Incomplete_Message", "Boolean",
                                              [Parameter(["Ctx"], "Context")])

        return UnitPart(
            [
                # https://github.com/Componolit/Workarounds/issues/47
                Pragma(
                    "Warnings",
                    [
                        Variable("Off"),
                        String(
                            "postcondition does not mention function result")
                    ],
                ),
                SubprogramDeclaration(specification, [Postcondition(TRUE)]),
                Pragma(
                    "Warnings",
                    [
                        Variable("On"),
                        String(
                            "postcondition does not mention function result")
                    ],
                ),
            ],
            private=[
                ExpressionFunctionDeclaration(
                    specification,
                    ForSomeIn(
                        "F",
                        Variable("Field"),
                        Call(
                            "Incomplete",
                            [Variable("Ctx"), Variable("F")],
                        ),
                    ),
                )
            ],
        )
Ejemplo n.º 25
0
    def create_internal_functions(
        self,
        message: Message,
        scalar_fields: Mapping[Field, Type],
        composite_fields: Sequence[Field],
    ) -> UnitPart:
        def result(field: Field, message: Message) -> NamedAggregate:
            aggregate: List[Tuple[str, Expr]] = [
                ("Fld", Variable(field.affixed_name))
            ]
            if field in message.fields and isinstance(message.types[field],
                                                      Scalar):
                aggregate.append((
                    f"{field.name}_Value",
                    Call(
                        "Extract",
                        [
                            Slice(
                                Variable("Ctx.Buffer.all"),
                                Variable("Buffer_First"),
                                Variable("Buffer_Last"),
                            ),
                            Variable("Offset"),
                        ],
                    ),
                ))
            return NamedAggregate(*aggregate)

        return UnitPart(
            [],
            [
                ExpressionFunctionDeclaration(
                    FunctionSpecification("Composite_Field", "Boolean",
                                          [Parameter(["Fld"], "Field")]),
                    Case(
                        Variable("Fld"),
                        [(Variable(f.affixed_name),
                          TRUE if f in composite_fields else FALSE)
                         for f in message.fields],
                    ),
                ),
                SubprogramBody(
                    FunctionSpecification(
                        "Get_Field_Value",
                        "Field_Dependent_Value",
                        [
                            Parameter(["Ctx"], "Context"),
                            Parameter(["Fld"], "Field")
                        ],
                    ),
                    [
                        *common.field_bit_location_declarations(
                            Variable("Fld")),
                        *common.field_byte_location_declarations(),
                        *unique(
                            self.extract_function(common.full_base_type_name(
                                t)) for t in message.types.values()
                            if isinstance(t, Scalar)),
                    ] if scalar_fields else [],
                    [
                        ReturnStatement(
                            Case(
                                Variable("Fld"),
                                [(Variable(f.affixed_name), result(f, message))
                                 for f in message.fields],
                            ))
                    ],
                    [
                        Precondition(
                            AndThen(
                                Call("Has_Buffer", [Variable("Ctx")]),
                                Call("Valid_Next",
                                     [Variable("Ctx"),
                                      Variable("Fld")]),
                                Call("Sufficient_Buffer_Length",
                                     [Variable("Ctx"),
                                      Variable("Fld")]),
                            )),
                        Postcondition(
                            Equal(
                                Selected(Result("Get_Field_Value"), "Fld"),
                                Variable("Fld"),
                            )),
                    ],
                ),
            ],
        )
Ejemplo n.º 26
0
 def specification(field: Field) -> ProcedureSpecification:
     return ProcedureSpecification(f"Get_{field.name}",
                                   [Parameter(["Ctx"], "Context")])
Ejemplo n.º 27
0
 def specification_bounded(field: Field) -> ProcedureSpecification:
     return ProcedureSpecification(
         f"Initialize_Bounded_{field.name}",
         [InOutParameter(["Ctx"], "Context"), Parameter(["Length"], self.types.bit_length)],
     )
Ejemplo n.º 28
0
    def create_composite_accessor_procedures(
            composite_fields: Sequence[Field]) -> UnitPart:
        def specification(field: Field) -> ProcedureSpecification:
            return ProcedureSpecification(f"Get_{field.name}",
                                          [Parameter(["Ctx"], "Context")])

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification(f),
                    [
                        Precondition(
                            And(
                                Call("Has_Buffer", [Variable("Ctx")]),
                                Call("Present", [
                                    Variable("Ctx"),
                                    Variable(f.affixed_name)
                                ]),
                            ))
                    ],
                    [
                        FormalSubprogramDeclaration(
                            ProcedureSpecification(
                                f"Process_{f.name}",
                                [Parameter([f.name], const.TYPES_BYTES)]))
                    ],
                ) for f in composite_fields
            ],
            [
                SubprogramBody(
                    specification(f),
                    [
                        ObjectDeclaration(
                            ["First"],
                            const.TYPES_INDEX,
                            Call(
                                const.TYPES_BYTE_INDEX,
                                [
                                    Selected(
                                        Indexed(Variable("Ctx.Cursors"),
                                                Variable(f.affixed_name)),
                                        "First",
                                    )
                                ],
                            ),
                            True,
                        ),
                        ObjectDeclaration(
                            ["Last"],
                            const.TYPES_INDEX,
                            Call(
                                const.TYPES_BYTE_INDEX,
                                [
                                    Selected(
                                        Indexed(Variable("Ctx.Cursors"),
                                                Variable(f.affixed_name)),
                                        "Last",
                                    )
                                ],
                            ),
                            True,
                        ),
                    ],
                    [
                        CallStatement(
                            f"Process_{f.name}",
                            [
                                Slice(Variable("Ctx.Buffer.all"),
                                      Variable("First"), Variable("Last"))
                            ],
                        )
                    ],
                ) for f in composite_fields
            ],
        )
Ejemplo n.º 29
0
 def create_internal_functions(
     self, message: Message, scalar_fields: Mapping[Field, Scalar]
 ) -> UnitPart:
     return UnitPart(
         [],
         [
             SubprogramBody(
                 ProcedureSpecification(
                     "Set_Field_Value",
                     [
                         InOutParameter(["Ctx"], "Context"),
                         Parameter(["Val"], "Field_Dependent_Value"),
                         OutParameter(["Fst", "Lst"], self.types.bit_index),
                     ],
                 ),
                 [
                     *self.common.field_bit_location_declarations(Selected("Val", "Fld")),
                     *self.common.field_byte_location_declarations(),
                 ],
                 [
                     Assignment("Fst", Name("First")),
                     Assignment("Lst", Name("Last")),
                     CaseStatement(
                         Selected("Val", "Fld"),
                         [
                             (
                                 Name(f.affixed_name),
                                 [
                                     CallStatement(
                                         "Insert",
                                         [
                                             Selected("Val", f"{f.name}_Value"),
                                             Slice(
                                                 Selected(Selected("Ctx", "Buffer"), "all"),
                                                 Name("Buffer_First"),
                                                 Name("Buffer_Last"),
                                             ),
                                             Name("Offset"),
                                         ],
                                     )
                                     if f in scalar_fields
                                     else NullStatement()
                                 ],
                             )
                             for f in message.all_fields
                         ],
                     ),
                 ],
                 [
                     Precondition(
                         AndThen(
                             Not(Constrained("Ctx")),
                             Call("Has_Buffer", [Name("Ctx")]),
                             In(Selected("Val", "Fld"), Range("Field")),
                             Call("Valid_Next", [Name("Ctx"), Selected("Val", "Fld")]),
                             self.common.sufficient_space_for_field_condition(
                                 Selected("Val", "Fld")
                             ),
                             ForAllIn(
                                 "F",
                                 Range("Field"),
                                 If(
                                     [
                                         (
                                             Call(
                                                 "Structural_Valid",
                                                 [
                                                     Indexed(
                                                         Selected("Ctx", "Cursors"), Name("F"),
                                                     )
                                                 ],
                                             ),
                                             LessEqual(
                                                 Selected(
                                                     Indexed(
                                                         Selected("Ctx", "Cursors"), Name("F"),
                                                     ),
                                                     "Last",
                                                 ),
                                                 Call(
                                                     "Field_Last",
                                                     [Name("Ctx"), Selected("Val", "Fld")],
                                                 ),
                                             ),
                                         )
                                     ]
                                 ),
                             ),
                         )
                     ),
                     Postcondition(
                         And(
                             Call("Has_Buffer", [Name("Ctx")]),
                             Equal(
                                 Name("Fst"),
                                 Call("Field_First", [Name("Ctx"), Selected("Val", "Fld")]),
                             ),
                             Equal(
                                 Name("Lst"),
                                 Call("Field_Last", [Name("Ctx"), Selected("Val", "Fld")]),
                             ),
                             GreaterEqual(Name("Fst"), Selected("Ctx", "First")),
                             LessEqual(Name("Fst"), Add(Name("Lst"), Number(1))),
                             LessEqual(
                                 Call(self.types.byte_index, [Name("Lst")]),
                                 Selected("Ctx", "Buffer_Last"),
                             ),
                             ForAllIn(
                                 "F",
                                 Range("Field"),
                                 If(
                                     [
                                         (
                                             Call(
                                                 "Structural_Valid",
                                                 [
                                                     Indexed(
                                                         Selected("Ctx", "Cursors"), Name("F"),
                                                     )
                                                 ],
                                             ),
                                             LessEqual(
                                                 Selected(
                                                     Indexed(
                                                         Selected("Ctx", "Cursors"), Name("F"),
                                                     ),
                                                     "Last",
                                                 ),
                                                 Name("Lst"),
                                             ),
                                         )
                                     ]
                                 ),
                             ),
                             *[
                                 Equal(e, Old(e))
                                 for e in [
                                     Selected("Ctx", "Buffer_First"),
                                     Selected("Ctx", "Buffer_Last"),
                                     Selected("Ctx", "First"),
                                     Selected("Ctx", "Cursors"),
                                 ]
                             ],
                         )
                     ),
                 ],
             )
         ],
     )
Ejemplo n.º 30
0
    def create_verify_procedure(self, message: Message,
                                context_invariant: Sequence[Expr]) -> UnitPart:
        specification = ProcedureSpecification(
            "Verify",
            [InOutParameter(["Ctx"], "Context"),
             Parameter(["Fld"], "Field")])

        valid_field_condition = And(
            Call(
                "Valid_Value",
                [Variable("Value")],
            ),
            Call(
                "Field_Condition",
                [
                    Variable("Ctx"),
                    Variable("Value"),
                    *([
                        Call(
                            "Field_Length",
                            [Variable("Ctx"), Variable("Fld")])
                    ] if common.length_dependent_condition(message) else []),
                ],
            ),
        )

        set_cursors_statements = [
            IfStatement(
                [(
                    Call("Composite_Field", [Variable("Fld")]),
                    [
                        Assignment(
                            Indexed(Variable("Ctx.Cursors"), Variable("Fld")),
                            NamedAggregate(
                                ("State", Variable("S_Structural_Valid")),
                                (
                                    "First",
                                    Call("Field_First",
                                         [Variable("Ctx"),
                                          Variable("Fld")]),
                                ),
                                (
                                    "Last",
                                    Call("Field_Last",
                                         [Variable("Ctx"),
                                          Variable("Fld")]),
                                ),
                                ("Value", Variable("Value")),
                                (
                                    "Predecessor",
                                    Selected(
                                        Indexed(Variable("Ctx.Cursors"),
                                                Variable("Fld")),
                                        "Predecessor",
                                    ),
                                ),
                            ),
                        )
                    ],
                )],
                [
                    Assignment(
                        Indexed(Variable("Ctx.Cursors"), Variable("Fld")),
                        NamedAggregate(
                            ("State", Variable("S_Valid")),
                            ("First",
                             Call("Field_First",
                                  [Variable("Ctx"),
                                   Variable("Fld")])),
                            ("Last",
                             Call("Field_Last",
                                  [Variable("Ctx"),
                                   Variable("Fld")])),
                            ("Value", Variable("Value")),
                            (
                                "Predecessor",
                                Selected(
                                    Indexed(Variable("Ctx.Cursors"),
                                            Variable("Fld")), "Predecessor"),
                            ),
                        ),
                    )
                ],
            ),
            # WORKAROUND:
            # Limitation of GNAT Community 2019 / SPARK Pro 20.0
            # Provability of predicate is increased by adding part of
            # predicate as assert
            PragmaStatement("Assert", [
                str(common.message_structure_invariant(message, self.prefix))
            ]),
            # WORKAROUND:
            # Limitation of GNAT Community 2019 / SPARK Pro 20.0
            # Provability of predicate is increased by splitting
            # assignment in multiple statements
            IfStatement([(
                Equal(Variable("Fld"), Variable(f.affixed_name)),
                [
                    Assignment(
                        Indexed(
                            Variable("Ctx.Cursors"),
                            Call("Successor",
                                 [Variable("Ctx"),
                                  Variable("Fld")]),
                        ),
                        NamedAggregate(
                            ("State", Variable("S_Invalid")),
                            ("Predecessor", Variable("Fld")),
                        ),
                    )
                ],
            ) for f in message.fields]),
        ]

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification,
                    [
                        Postcondition(
                            And(
                                Equal(
                                    Call("Has_Buffer", [Variable("Ctx")]),
                                    Old(Call("Has_Buffer", [Variable("Ctx")])),
                                ),
                                *context_invariant,
                            )),
                    ],
                )
            ],
            [
                SubprogramBody(
                    specification,
                    [ObjectDeclaration(["Value"], "Field_Dependent_Value")],
                    [
                        IfStatement([(
                            AndThen(
                                Call("Has_Buffer", [Variable("Ctx")]),
                                Call(
                                    "Invalid",
                                    [
                                        Indexed(Variable("Ctx.Cursors"),
                                                Variable("Fld"))
                                    ],
                                ),
                                Call("Valid_Predecessor",
                                     [Variable("Ctx"),
                                      Variable("Fld")]),
                                Call("Path_Condition",
                                     [Variable("Ctx"),
                                      Variable("Fld")]),
                            ),
                            [
                                IfStatement(
                                    [(
                                        Call(
                                            "Sufficient_Buffer_Length",
                                            [Variable("Ctx"),
                                             Variable("Fld")],
                                        ),
                                        [
                                            Assignment(
                                                "Value",
                                                Call(
                                                    "Get_Field_Value",
                                                    [
                                                        Variable("Ctx"),
                                                        Variable("Fld")
                                                    ],
                                                ),
                                            ),
                                            IfStatement(
                                                [(
                                                    valid_field_condition,
                                                    set_cursors_statements,
                                                )],
                                                [
                                                    Assignment(
                                                        Indexed(
                                                            Variable(
                                                                "Ctx.Cursors"),
                                                            Variable("Fld"),
                                                        ),
                                                        NamedAggregate(
                                                            (
                                                                "State",
                                                                Variable(
                                                                    "S_Invalid"
                                                                ),
                                                            ),
                                                            (
                                                                "Predecessor",
                                                                Variable(
                                                                    FINAL.
                                                                    affixed_name
                                                                ),
                                                            ),
                                                        ),
                                                    )
                                                ],
                                            ),
                                        ],
                                    )],
                                    [
                                        Assignment(
                                            Indexed(Variable("Ctx.Cursors"),
                                                    Variable("Fld")),
                                            NamedAggregate(
                                                ("State",
                                                 Variable("S_Incomplete")),
                                                (
                                                    "Predecessor",
                                                    Variable(
                                                        FINAL.affixed_name),
                                                ),
                                            ),
                                        )
                                    ],
                                )
                            ],
                        )], )
                    ],
                )
            ],
        )