Пример #1
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
            ],
        )
Пример #2
0
 def field_bit_location_declarations(self, field_name: Name) -> Sequence[Declaration]:
     return [
         ObjectDeclaration(
             ["First"],
             self.types.bit_index,
             Call("Field_First", [Name("Ctx"), field_name]),
             True,
         ),
         ObjectDeclaration(
             ["Last"], self.types.bit_index, Call("Field_Last", [Name("Ctx"), field_name]), True,
         ),
     ]
Пример #3
0
def field_bit_location_declarations(field_name: Name) -> Sequence[Declaration]:
    return [
        ObjectDeclaration(
            ["First"],
            const.TYPES_BIT_INDEX,
            Call("Field_First", [Variable("Ctx"), field_name]),
            True,
        ),
        ObjectDeclaration(
            ["Last"],
            const.TYPES_BIT_INDEX,
            Call("Field_Last", [Variable("Ctx"), field_name]),
            True,
        ),
    ]
Пример #4
0
    def create_composite_initialize_procedures(self, message: Message) -> UnitPart:
        def specification(field: Field) -> ProcedureSpecification:
            return ProcedureSpecification(
                f"Initialize_{field.name}", [InOutParameter(["Ctx"], "Context")]
            )

        def specification_bounded(field: Field) -> ProcedureSpecification:
            return ProcedureSpecification(
                f"Initialize_Bounded_{field.name}",
                [InOutParameter(["Ctx"], "Context"), Parameter(["Length"], self.types.bit_length)],
            )

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification(f),
                    [
                        Precondition(
                            AndThen(
                                *self.setter_preconditions(f),
                                *self.unbounded_composite_setter_preconditions(message, f),
                            )
                        ),
                        Postcondition(
                            And(
                                *self.composite_setter_postconditions(message, f, message.types[f]),
                            )
                        ),
                    ],
                )
                for f, t in message.types.items()
                if isinstance(t, Payload) and unbounded_setter_required(message, f)
            ]
            + [
                SubprogramDeclaration(
                    specification_bounded(f),
                    [
                        Precondition(
                            AndThen(
                                *self.setter_preconditions(f),
                                *self.bounded_composite_setter_preconditions(message, f),
                            )
                        ),
                        Postcondition(
                            And(
                                *self.composite_setter_postconditions(message, f, message.types[f]),
                            )
                        ),
                    ],
                )
                for f, t in message.types.items()
                if isinstance(t, Payload) and bounded_setter_required(message, f)
            ],
            [
                SubprogramBody(
                    specification(f),
                    self.common.field_bit_location_declarations(Name(f.affixed_name)),
                    self.common.initialize_field_statements(message, f),
                )
                for f, t in message.types.items()
                if isinstance(t, Payload) and unbounded_setter_required(message, f)
            ]
            + [
                SubprogramBody(
                    specification_bounded(f),
                    [
                        ObjectDeclaration(
                            ["First"],
                            self.types.bit_index,
                            Call("Field_First", [Name("Ctx"), Name(f.affixed_name)]),
                            True,
                        ),
                        ObjectDeclaration(
                            ["Last"],
                            self.types.bit_index,
                            Add(Name("First"), Name("Length"), -Number(1)),
                            True,
                        ),
                    ],
                    self.common.initialize_field_statements(message, f),
                )
                for f, t in message.types.items()
                if isinstance(t, Payload) and bounded_setter_required(message, f)
            ],
        )
Пример #5
0
    def create_composite_setter_procedures(self, message: Message) -> UnitPart:
        def specification(field: Field) -> ProcedureSpecification:
            return ProcedureSpecification(f"Set_{field.name}", [InOutParameter(["Ctx"], "Context")])

        def specification_bounded(field: Field) -> ProcedureSpecification:
            return ProcedureSpecification(
                f"Set_Bounded_{field.name}",
                [InOutParameter(["Ctx"], "Context"), Parameter(["Length"], self.types.bit_length)],
            )

        formal_parameters = [
            FormalSubprogramDeclaration(
                ProcedureSpecification(
                    "Process_Payload", [OutParameter(["Payload"], self.types.bytes)],
                )
            )
        ]

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification(f),
                    [
                        Precondition(
                            AndThen(
                                *self.setter_preconditions(f),
                                *self.unbounded_composite_setter_preconditions(message, f),
                            )
                        ),
                        Postcondition(
                            And(
                                *self.composite_setter_postconditions(message, f, message.types[f]),
                            )
                        ),
                    ],
                    formal_parameters,
                )
                for f, t in message.types.items()
                if isinstance(t, Payload) and unbounded_setter_required(message, f)
            ]
            + [
                SubprogramDeclaration(
                    specification_bounded(f),
                    [
                        Precondition(
                            AndThen(
                                *self.setter_preconditions(f),
                                *self.bounded_composite_setter_preconditions(message, f),
                            )
                        ),
                        Postcondition(
                            And(
                                *self.composite_setter_postconditions(message, f, message.types[f]),
                            )
                        ),
                    ],
                    formal_parameters,
                )
                for f, t in message.types.items()
                if isinstance(t, Payload) and bounded_setter_required(message, f)
            ],
            [
                SubprogramBody(
                    specification(f),
                    [
                        *self.common.field_bit_location_declarations(Name(f.affixed_name)),
                        ExpressionFunctionDeclaration(
                            FunctionSpecification("Buffer_First", self.types.index),
                            Call(self.types.byte_index, [Name("First")]),
                        ),
                        ExpressionFunctionDeclaration(
                            FunctionSpecification("Buffer_Last", self.types.index),
                            Call(self.types.byte_index, [Name("Last")]),
                        ),
                    ],
                    [
                        CallStatement(f"Initialize_{f.name}", [Name("Ctx")]),
                        CallStatement(
                            "Process_Payload",
                            [
                                Slice(
                                    Selected(Selected("Ctx", "Buffer"), "all"),
                                    Name("Buffer_First"),
                                    Name("Buffer_Last"),
                                ),
                            ],
                        ),
                    ],
                )
                for f, t in message.types.items()
                if isinstance(t, Payload) and unbounded_setter_required(message, f)
            ]
            + [
                SubprogramBody(
                    specification_bounded(f),
                    [
                        ObjectDeclaration(
                            ["First"],
                            self.types.bit_index,
                            Call("Field_First", [Name("Ctx"), Name(f.affixed_name)]),
                            True,
                        ),
                        ObjectDeclaration(
                            ["Last"],
                            self.types.bit_index,
                            Add(Name("First"), Name("Length"), -Number(1)),
                            True,
                        ),
                        ExpressionFunctionDeclaration(
                            FunctionSpecification("Buffer_First", self.types.index),
                            Call(self.types.byte_index, [Name("First")]),
                        ),
                        ExpressionFunctionDeclaration(
                            FunctionSpecification("Buffer_Last", self.types.index),
                            Call(self.types.byte_index, [Name("Last")]),
                        ),
                    ],
                    [
                        CallStatement(
                            f"Initialize_Bounded_{f.name}", [Name("Ctx"), Name("Length")]
                        ),
                        CallStatement(
                            "Process_Payload",
                            [
                                Slice(
                                    Selected(Selected("Ctx", "Buffer"), "all"),
                                    Name("Buffer_First"),
                                    Name("Buffer_Last"),
                                ),
                            ],
                        ),
                    ],
                )
                for f, t in message.types.items()
                if isinstance(t, Payload) and bounded_setter_required(message, f)
            ],
        )
Пример #6
0
    def create_scalar_setter_procedures(
        self, message: Message, scalar_fields: Mapping[Field, Scalar]
    ) -> UnitPart:
        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}"),
                ],
            )

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification(f, t),
                    [
                        Precondition(
                            AndThen(
                                *self.setter_preconditions(f),
                                Call(
                                    "Field_Condition",
                                    [
                                        Name("Ctx"),
                                        Aggregate(
                                            Name(f.affixed_name),
                                            Name("Val")
                                            if not isinstance(t, Enumeration)
                                            else Call("Convert", [Name("Val")]),
                                        ),
                                    ],
                                ),
                                Call("Valid", [Name("Val")])
                                if not isinstance(t, Enumeration)
                                else TRUE,
                                self.common.sufficient_space_for_field_condition(
                                    Name(f.affixed_name)
                                ),
                            )
                        ),
                        Postcondition(
                            And(
                                VALID_CONTEXT,
                                Call("Has_Buffer", [Name("Ctx")]),
                                Call("Valid", [Name("Ctx"), Name(f.affixed_name)]),
                                Equal(
                                    Call(f"Get_{f.name}", [Name("Ctx")]),
                                    Aggregate(TRUE, Name("Val"))
                                    if isinstance(t, Enumeration) and t.always_valid
                                    else Name("Val"),
                                ),
                                *self.setter_postconditions(message, f, t),
                                *[
                                    Equal(
                                        Call("Cursor", [Name("Ctx"), Name(p.affixed_name)]),
                                        Old(Call("Cursor", [Name("Ctx"), Name(p.affixed_name)])),
                                    )
                                    for p in message.predecessors(f)
                                ],
                            )
                        ),
                    ],
                )
                for f, t in scalar_fields.items()
            ],
            [
                SubprogramBody(
                    specification(f, t),
                    [
                        ObjectDeclaration(
                            ["Field_Value"],
                            "Field_Dependent_Value",
                            Aggregate(
                                Name(f.affixed_name),
                                Name("Val")
                                if not isinstance(t, Enumeration)
                                else Call("Convert", [Name("Val")]),
                            ),
                            True,
                        ),
                        ObjectDeclaration(["First", "Last"], self.types.bit_index),
                    ],
                    [
                        CallStatement(
                            "Reset_Dependent_Fields", [Name("Ctx"), Name(f.affixed_name)],
                        ),
                        CallStatement(
                            "Set_Field_Value",
                            [Name("Ctx"), Name("Field_Value"), Name("First"), Name("Last")],
                        ),
                        Assignment(
                            "Ctx",
                            Aggregate(
                                Selected("Ctx", "Buffer_First"),
                                Selected("Ctx", "Buffer_Last"),
                                Selected("Ctx", "First"),
                                Name("Last"),
                                Selected("Ctx", "Buffer"),
                                Selected("Ctx", "Cursors"),
                            ),
                        ),
                        Assignment(
                            Indexed(Selected("Ctx", "Cursors"), Name(f.affixed_name)),
                            NamedAggregate(
                                ("State", Name("S_Valid")),
                                ("First", Name("First")),
                                ("Last", Name("Last")),
                                ("Value", Name("Field_Value")),
                                (
                                    "Predecessor",
                                    Selected(
                                        Indexed(Selected("Ctx", "Cursors"), Name(f.affixed_name)),
                                        "Predecessor",
                                    ),
                                ),
                            ),
                        ),
                        Assignment(
                            Indexed(
                                Selected("Ctx", "Cursors"),
                                Call("Successor", [Name("Ctx"), Name(f.affixed_name)]),
                            ),
                            NamedAggregate(
                                ("State", Name("S_Invalid")), ("Predecessor", Name(f.affixed_name)),
                            ),
                        ),
                    ],
                )
                for f, t in scalar_fields.items()
            ],
        )
Пример #7
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
            ],
        )
Пример #8
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),
                                                ),
                                            ),
                                        )
                                    ],
                                )
                            ],
                        )], )
                    ],
                )
            ],
        )
Пример #9
0
    def create_composite_setter_procedures(self, message: Message) -> UnitPart:
        def specification(field: Field) -> ProcedureSpecification:
            return ProcedureSpecification(f"Set_{field.name}",
                                          [InOutParameter(["Ctx"], "Context")])

        def specification_bounded(field: Field) -> ProcedureSpecification:
            return ProcedureSpecification(
                f"Set_Bounded_{field.name}",
                [
                    InOutParameter(["Ctx"], "Context"),
                    Parameter(["Length"], const.TYPES_BIT_LENGTH)
                ],
            )

        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)],
                    )),
            ]

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification(f),
                    [
                        Precondition(
                            AndThen(
                                *self.setter_preconditions(f),
                                *self.unbounded_composite_setter_preconditions(
                                    message, f),
                                Call(
                                    "Valid_Length",
                                    [
                                        Call(
                                            const.TYPES_LENGTH,
                                            [
                                                Div(
                                                    Call(
                                                        "Field_Length",
                                                        [
                                                            Variable("Ctx"),
                                                            Variable(
                                                                f.affixed_name)
                                                        ],
                                                    ),
                                                    Size(const.TYPES_BYTE),
                                                ),
                                            ],
                                        ),
                                    ],
                                ),
                            )),
                        Postcondition(
                            And(
                                *self.composite_setter_postconditions(
                                    message, f), )),
                    ],
                    formal_parameters(f),
                ) for f, t in message.types.items() if isinstance(t, Opaque)
                and unbounded_setter_required(message, f)
            ] + [
                SubprogramDeclaration(
                    specification_bounded(f),
                    [
                        Precondition(
                            AndThen(
                                *self.setter_preconditions(f),
                                *self.bounded_composite_setter_preconditions(
                                    message, f),
                                Call(
                                    "Valid_Length",
                                    [
                                        Call(
                                            const.TYPES_LENGTH,
                                            [
                                                Div(Variable("Length"),
                                                    Size(const.TYPES_BYTE))
                                            ],
                                        )
                                    ],
                                ),
                            )),
                        Postcondition(
                            And(
                                *self.composite_setter_postconditions(
                                    message, f), )),
                    ],
                    formal_parameters(f),
                ) for f, t in message.types.items() if isinstance(t, Opaque)
                and bounded_setter_required(message, f)
            ],
            [
                SubprogramBody(
                    specification(f),
                    [
                        *common.field_bit_location_declarations(
                            Variable(f.affixed_name)),
                        ExpressionFunctionDeclaration(
                            FunctionSpecification("Buffer_First",
                                                  const.TYPES_INDEX),
                            Call(const.TYPES_BYTE_INDEX, [Variable("First")]),
                        ),
                        ExpressionFunctionDeclaration(
                            FunctionSpecification("Buffer_Last",
                                                  const.TYPES_INDEX),
                            Call(const.TYPES_BYTE_INDEX, [Variable("Last")]),
                        ),
                    ],
                    [
                        CallStatement(f"Initialize_{f.name}",
                                      [Variable("Ctx")]),
                        CallStatement(
                            f"Process_{f.name}",
                            [
                                Slice(
                                    Selected(Variable("Ctx.Buffer"), "all"),
                                    Variable("Buffer_First"),
                                    Variable("Buffer_Last"),
                                ),
                            ],
                        ),
                    ],
                ) for f, t in message.types.items() if isinstance(t, Opaque)
                and unbounded_setter_required(message, f)
            ] + [
                SubprogramBody(
                    specification_bounded(f),
                    [
                        ObjectDeclaration(
                            ["First"],
                            const.TYPES_BIT_INDEX,
                            Call("Field_First",
                                 [Variable("Ctx"),
                                  Variable(f.affixed_name)]),
                            True,
                        ),
                        ObjectDeclaration(
                            ["Last"],
                            const.TYPES_BIT_INDEX,
                            Add(Variable("First"), Variable("Length"),
                                -Number(1)),
                            True,
                        ),
                        ExpressionFunctionDeclaration(
                            FunctionSpecification("Buffer_First",
                                                  const.TYPES_INDEX),
                            Call(const.TYPES_BYTE_INDEX, [Variable("First")]),
                        ),
                        ExpressionFunctionDeclaration(
                            FunctionSpecification("Buffer_Last",
                                                  const.TYPES_INDEX),
                            Call(const.TYPES_BYTE_INDEX, [Variable("Last")]),
                        ),
                    ],
                    [
                        CallStatement(f"Initialize_Bounded_{f.name}",
                                      [Variable("Ctx"),
                                       Variable("Length")]),
                        CallStatement(
                            f"Process_{f.name}",
                            [
                                Slice(
                                    Selected(Variable("Ctx.Buffer"), "all"),
                                    Variable("Buffer_First"),
                                    Variable("Buffer_Last"),
                                ),
                            ],
                        ),
                    ],
                ) for f, t in message.types.items() if isinstance(t, Opaque)
                and bounded_setter_required(message, f)
            ],
        )
Пример #10
0
    def create_composite_setter_empty_procedures(self,
                                                 message: Message) -> UnitPart:
        def specification(field: Field) -> ProcedureSpecification:
            return ProcedureSpecification(f"Set_{field.name}_Empty",
                                          [InOutParameter(["Ctx"], "Context")])

        return UnitPart(
            [
                *[
                    SubprogramDeclaration(
                        specification(f),
                        [
                            Precondition(
                                AndThen(
                                    *self.setter_preconditions(f),
                                    *self.
                                    unbounded_composite_setter_preconditions(
                                        message, f),
                                    Equal(
                                        Call(
                                            "Field_Length",
                                            [
                                                Variable("Ctx"),
                                                Variable(f.affixed_name)
                                            ],
                                        ),
                                        Number(0),
                                    ),
                                )),
                            Postcondition(
                                And(*self.composite_setter_postconditions(
                                    message, f))),
                        ],
                    ) for f, t in message.types.items()
                    if message.is_possibly_empty(f)
                ],
            ],
            [
                SubprogramBody(
                    specification(f),
                    [
                        ObjectDeclaration(
                            ["First"],
                            const.TYPES_BIT_INDEX,
                            Call("Field_First",
                                 [Variable("Ctx"),
                                  Variable(f.affixed_name)]),
                            True,
                        ),
                        ObjectDeclaration(
                            ["Last"],
                            const.TYPES_BIT_INDEX,
                            Call("Field_Last",
                                 [Variable("Ctx"),
                                  Variable(f.affixed_name)]),
                            True,
                        ),
                    ],
                    [
                        CallStatement(
                            "Reset_Dependent_Fields",
                            [Variable("Ctx"),
                             Variable(f.affixed_name)],
                        ),
                        Assignment(
                            "Ctx",
                            Aggregate(
                                Variable("Ctx.Buffer_First"),
                                Variable("Ctx.Buffer_Last"),
                                Variable("Ctx.First"),
                                Variable("Last"),
                                Variable("Ctx.Buffer"),
                                Variable("Ctx.Cursors"),
                            ),
                        ),
                        Assignment(
                            Indexed(Variable("Ctx.Cursors"),
                                    Variable(f.affixed_name)),
                            NamedAggregate(
                                ("State", Variable("S_Valid")),
                                ("First", Variable("First")),
                                ("Last", Variable("Last")),
                                ("Value",
                                 NamedAggregate(
                                     ("Fld", Variable(f.affixed_name)))),
                                (
                                    "Predecessor",
                                    Selected(
                                        Indexed(Variable("Ctx.Cursors"),
                                                Variable(f.affixed_name)),
                                        "Predecessor",
                                    ),
                                ),
                            ),
                        ),
                        Assignment(
                            Indexed(
                                Variable("Ctx.Cursors"),
                                Call("Successor", [
                                    Variable("Ctx"),
                                    Variable(f.affixed_name)
                                ]),
                            ),
                            NamedAggregate(
                                ("State", Variable("S_Invalid")),
                                ("Predecessor", Variable(f.affixed_name)),
                            ),
                        ),
                    ],
                ) for f, t in message.types.items()
                if message.is_possibly_empty(f)
            ],
        )
Пример #11
0
    def create_scalar_setter_procedures(
            self, message: Message,
            scalar_fields: Mapping[Field, Scalar]) -> UnitPart:
        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)
                ],
            )

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification(f, t),
                    [
                        Precondition(
                            AndThen(
                                *self.setter_preconditions(f),
                                Call(
                                    "Field_Condition",
                                    [
                                        Variable("Ctx"),
                                        Aggregate(
                                            Variable(f.affixed_name),
                                            Call("To_Base", [Variable("Val")]),
                                        ),
                                    ],
                                ),
                                Call("Valid",
                                     [Call("To_Base", [Variable("Val")])])
                                if not isinstance(t, Enumeration) else TRUE,
                                common.sufficient_space_for_field_condition(
                                    Variable(f.affixed_name)),
                            )),
                        Postcondition(
                            And(
                                Call("Has_Buffer", [Variable("Ctx")]),
                                Call("Valid", [
                                    Variable("Ctx"),
                                    Variable(f.affixed_name)
                                ]),
                                Equal(
                                    Call(f"Get_{f.name}", [Variable("Ctx")]),
                                    Aggregate(TRUE, Variable("Val"))
                                    if isinstance(t, Enumeration)
                                    and t.always_valid else Variable("Val"),
                                ),
                                *self.setter_postconditions(message, f),
                                *[
                                    Equal(
                                        Call(
                                            "Context_Cursor",
                                            [
                                                Variable("Ctx"),
                                                Variable(p.affixed_name)
                                            ],
                                        ),
                                        Old(
                                            Call(
                                                "Context_Cursor",
                                                [
                                                    Variable("Ctx"),
                                                    Variable(p.affixed_name)
                                                ],
                                            )),
                                    ) for p in message.predecessors(f)
                                ],
                            )),
                    ],
                ) for f, t in scalar_fields.items()
            ],
            [
                SubprogramBody(
                    specification(f, t),
                    [
                        ObjectDeclaration(
                            ["Field_Value"],
                            "Field_Dependent_Value",
                            Aggregate(
                                Variable(f.affixed_name),
                                Call("To_Base", [Variable("Val")]),
                            ),
                            True,
                        ),
                        ObjectDeclaration(["First", "Last"],
                                          const.TYPES_BIT_INDEX),
                    ],
                    [
                        CallStatement(
                            "Reset_Dependent_Fields",
                            [Variable("Ctx"),
                             Variable(f.affixed_name)],
                        ),
                        CallStatement(
                            "Set_Field_Value",
                            [
                                Variable("Ctx"),
                                Variable("Field_Value"),
                                Variable("First"),
                                Variable("Last"),
                            ],
                        ),
                        Assignment(
                            "Ctx",
                            Aggregate(
                                Variable("Ctx.Buffer_First"),
                                Variable("Ctx.Buffer_Last"),
                                Variable("Ctx.First"),
                                Variable("Last"),
                                Variable("Ctx.Buffer"),
                                Variable("Ctx.Cursors"),
                            ),
                        ),
                        Assignment(
                            Indexed(Variable("Ctx.Cursors"),
                                    Variable(f.affixed_name)),
                            NamedAggregate(
                                ("State", Variable("S_Valid")),
                                ("First", Variable("First")),
                                ("Last", Variable("Last")),
                                ("Value", Variable("Field_Value")),
                                (
                                    "Predecessor",
                                    Selected(
                                        Indexed(Variable("Ctx.Cursors"),
                                                Variable(f.affixed_name)),
                                        "Predecessor",
                                    ),
                                ),
                            ),
                        ),
                        Assignment(
                            Indexed(
                                Variable("Ctx.Cursors"),
                                Call("Successor", [
                                    Variable("Ctx"),
                                    Variable(f.affixed_name)
                                ]),
                            ),
                            NamedAggregate(
                                ("State", Variable("S_Invalid")),
                                ("Predecessor", Variable(f.affixed_name)),
                            ),
                        ),
                    ],
                ) for f, t in scalar_fields.items()
            ],
        )
Пример #12
0
    def create_opaque_getter_procedures(
            self, message: Message,
            opaque_fields: Sequence[Field]) -> UnitPart:
        def specification(field: Field) -> ProcedureSpecification:
            return ProcedureSpecification(
                f"Get_{field.name}",
                [
                    Parameter(["Ctx"], "Context"),
                    OutParameter(["Data"], const.TYPES_BYTES)
                ],
            )

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification(f),
                    [
                        Precondition(
                            AndThen(
                                Call(
                                    self.prefix * message.identifier *
                                    "Has_Buffer",
                                    [Variable("Ctx")],
                                ),
                                Call(
                                    self.prefix * message.identifier *
                                    "Structural_Valid",
                                    [
                                        Variable("Ctx"),
                                        Variable(
                                            self.prefix * message.identifier *
                                            f.affixed_name),
                                    ],
                                ),
                                Call(
                                    self.prefix * message.identifier *
                                    "Valid_Next",
                                    [
                                        Variable("Ctx"),
                                        Variable(
                                            self.prefix * message.identifier *
                                            f.affixed_name),
                                    ],
                                ),
                                Equal(
                                    Length("Data"),
                                    Call(
                                        const.TYPES_TO_LENGTH,
                                        [
                                            Call(
                                                self.prefix *
                                                message.identifier *
                                                "Field_Size",
                                                [
                                                    Variable("Ctx"),
                                                    Variable(self.prefix *
                                                             message.identifier
                                                             * f.affixed_name),
                                                ],
                                            )
                                        ],
                                    ),
                                ),
                            )),
                        Postcondition(
                            Call(
                                "Equal",
                                [
                                    Variable("Ctx"),
                                    Variable(f.affixed_name),
                                    Variable("Data"),
                                ],
                            )),
                    ],
                ) for f in opaque_fields
            ],
            [
                SubprogramBody(
                    specification(f),
                    [
                        ObjectDeclaration(
                            ["First"],
                            const.TYPES_INDEX,
                            Call(
                                const.TYPES_TO_INDEX,
                                [
                                    Selected(
                                        Indexed(
                                            Variable("Ctx.Cursors"),
                                            Variable(f.affixed_name),
                                        ),
                                        "First",
                                    )
                                ],
                            ),
                            constant=True,
                        ),
                        ObjectDeclaration(
                            ["Last"],
                            const.TYPES_INDEX,
                            Call(
                                const.TYPES_TO_INDEX,
                                [
                                    Selected(
                                        Indexed(
                                            Variable("Ctx.Cursors"),
                                            Variable(f.affixed_name),
                                        ),
                                        "Last",
                                    )
                                ],
                            ),
                            constant=True,
                        ),
                    ],
                    [
                        Assignment(
                            "Data",
                            NamedAggregate(
                                ("others", First(const.TYPES_BYTE))),
                        ),
                        Assignment(
                            Slice(
                                Variable("Data"),
                                First("Data"),
                                Add(First("Data"),
                                    Sub(Variable("Last"), Variable("First"))),
                            ),
                            Slice(
                                Variable("Ctx.Buffer.all"),
                                Variable("First"),
                                Variable("Last"),
                            ),
                        ),
                    ],
                ) for f in opaque_fields
            ],
        )
Пример #13
0
    def create_opaque_getter_functions(
            self, message: Message,
            opaque_fields: Sequence[Field]) -> UnitPart:
        def name(field: Field) -> str:
            return f"Get_{field.name}"

        def specification(field: Field) -> FunctionSpecification:
            return FunctionSpecification(
                name(field),
                const.TYPES_BYTES,
                [Parameter(["Ctx"], "Context")],
            )

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification(f),
                    [
                        Ghost(),
                        Precondition(
                            AndThen(
                                Call(
                                    self.prefix * message.identifier *
                                    "Has_Buffer",
                                    [Variable("Ctx")],
                                ),
                                Call(
                                    self.prefix * message.identifier *
                                    "Structural_Valid",
                                    [
                                        Variable("Ctx"),
                                        Variable(
                                            self.prefix * message.identifier *
                                            f.affixed_name),
                                    ],
                                ),
                                Call(
                                    self.prefix * message.identifier *
                                    "Valid_Next",
                                    [
                                        Variable("Ctx"),
                                        Variable(
                                            self.prefix * message.identifier *
                                            f.affixed_name),
                                    ],
                                ),
                            )),
                        Postcondition(
                            Equal(
                                Length(Result(name(f))),
                                Call(
                                    const.TYPES_TO_LENGTH,
                                    [
                                        Call(
                                            "Field_Size",
                                            [
                                                Variable("Ctx"),
                                                Variable(f.affixed_name),
                                            ],
                                        )
                                    ],
                                ),
                            )),
                    ],
                ) for f in opaque_fields
            ],
            [
                SubprogramBody(
                    specification(f),
                    [
                        ObjectDeclaration(
                            ["First"],
                            const.TYPES_INDEX,
                            Call(
                                const.TYPES_TO_INDEX,
                                [
                                    Selected(
                                        Indexed(
                                            Variable("Ctx.Cursors"),
                                            Variable(f.affixed_name),
                                        ),
                                        "First",
                                    )
                                ],
                            ),
                            constant=True,
                        ),
                        ObjectDeclaration(
                            ["Last"],
                            const.TYPES_INDEX,
                            Call(
                                const.TYPES_TO_INDEX,
                                [
                                    Selected(
                                        Indexed(
                                            Variable("Ctx.Cursors"),
                                            Variable(f.affixed_name),
                                        ),
                                        "Last",
                                    )
                                ],
                            ),
                            constant=True,
                        ),
                    ],
                    [
                        ReturnStatement(
                            Slice(Variable("Ctx.Buffer.all"),
                                  Variable("First"), Variable("Last")), )
                    ],
                ) for f in opaque_fields
            ],
        )
Пример #14
0
    def create_get_function(
        self,
        message: Message,
        scalar_fields: Mapping[Field, Scalar],
        composite_fields: Sequence[Field],
    ) -> UnitPart:
        if not scalar_fields:
            return UnitPart()

        comparison_to_aggregate = any(
            (isinstance(t, Composite)
             and common.has_aggregate_dependent_condition(message, f))
            for f, t in message.field_types.items())

        big_endian_fields = [
            f for f in scalar_fields
            if message.byte_order[f] == ByteOrder.HIGH_ORDER_FIRST
        ]
        little_endian_fields = [
            f for f in scalar_fields
            if message.byte_order[f] == ByteOrder.LOW_ORDER_FIRST
        ]

        return UnitPart(
            [],
            [
                SubprogramBody(
                    FunctionSpecification(
                        "Get",
                        const.TYPES_BASE_INT,
                        [
                            Parameter(["Ctx"], "Context"),
                            Parameter(["Fld"], "Field")
                        ],
                    ),
                    [
                        *common.field_bit_location_declarations(
                            Variable("Fld")),
                        ObjectDeclaration(
                            ["Buffer_First"],
                            const.TYPES_INDEX,
                            Call(const.TYPES_TO_INDEX, [Variable("First")]),
                            constant=True,
                        ),
                        ObjectDeclaration(
                            ["Buffer_Last"],
                            const.TYPES_INDEX,
                            Call(const.TYPES_TO_INDEX, [Variable("Last")]),
                            constant=True,
                        ),
                        ObjectDeclaration(
                            ["Offset"],
                            const.TYPES_OFFSET,
                            Call(
                                const.TYPES_OFFSET,
                                [
                                    Mod(
                                        Sub(
                                            Size(const.TYPES_BYTE),
                                            Mod(Variable("Last"),
                                                Size(const.TYPES_BYTE)),
                                        ),
                                        Size(const.TYPES_BYTE),
                                    )
                                ],
                            ),
                            constant=True,
                        ),
                        ObjectDeclaration(
                            ["Size"],
                            "Positive",
                            Case(
                                Variable("Fld"),
                                [
                                    *[(Variable(f.affixed_name),
                                       t.size.ada_expr())
                                      for f, t in scalar_fields.items()],
                                    *([(Variable("others"), Last("Positive"))]
                                      if composite_fields else []),
                                ],
                            ),
                            constant=True,
                        ),
                        ObjectDeclaration(
                            ["Byte_Order"],
                            const.TYPES_BYTE_ORDER,
                            If(
                                [(
                                    In(
                                        Variable("Fld"),
                                        ChoiceList(*[
                                            Variable(f.affixed_name)
                                            for f in big_endian_fields
                                        ]),
                                    ),
                                    Variable(const.TYPES_HIGH_ORDER_FIRST),
                                )],
                                Variable(const.TYPES_LOW_ORDER_FIRST),
                            ) if big_endian_fields and little_endian_fields
                            else Variable(const.TYPES_HIGH_ORDER_FIRST)
                            if big_endian_fields else Variable(
                                const.TYPES_LOW_ORDER_FIRST),
                            constant=True,
                        ),
                    ] if scalar_fields or comparison_to_aggregate else [],
                    [
                        ReturnStatement(
                            Call(
                                const.TYPES * "Extract",
                                [
                                    Variable("Ctx.Buffer"),
                                    Variable("Buffer_First"),
                                    Variable("Buffer_Last"),
                                    Variable("Offset"),
                                    Variable("Size"),
                                    Variable("Byte_Order"),
                                ],
                            ), ),
                    ],
                    [
                        Precondition(
                            AndThen(
                                Call(
                                    self.prefix * message.identifier *
                                    "Has_Buffer",
                                    [Variable("Ctx")],
                                ),
                                Call(
                                    self.prefix * message.identifier *
                                    "Valid_Next",
                                    [Variable("Ctx"),
                                     Variable("Fld")],
                                ),
                                Call(
                                    self.prefix * message.identifier *
                                    "Sufficient_Buffer_Length",
                                    [Variable("Ctx"),
                                     Variable("Fld")],
                                ),
                                *([
                                    Not(
                                        Call(
                                            self.prefix * message.identifier *
                                            "Composite_Field",
                                            [Variable("Fld")],
                                        ))
                                ] if composite_fields else []),
                            )),
                    ],
                ),
            ],
        )
Пример #15
0
    def create_verify_procedure(
        self,
        message: Message,
        scalar_fields: Mapping[Field, Scalar],
        composite_fields: Sequence[Field],
    ) -> UnitPart:
        specification = ProcedureSpecification(
            "Verify",
            [InOutParameter(["Ctx"], "Context"),
             Parameter(["Fld"], "Field")])

        valid_field_condition = AndThen(
            Call(
                "Valid_Value",
                [Variable("Fld"), Variable("Value")],
            ),
            Call(
                "Field_Condition",
                [
                    Variable("Ctx"),
                    Variable("Fld"),
                    *([Variable("Value")] if
                      common.has_value_dependent_condition(message) else []),
                    *([
                        Slice(
                            Variable("Ctx.Buffer.all"),
                            Call(
                                const.TYPES_TO_INDEX,
                                [
                                    Call("Field_First",
                                         [Variable("Ctx"),
                                          Variable("Fld")])
                                ],
                            ),
                            Call(
                                const.TYPES_TO_INDEX,
                                [
                                    Call("Field_Last",
                                         [Variable("Ctx"),
                                          Variable("Fld")])
                                ],
                            ),
                        )
                    ] if common.has_aggregate_dependent_condition(message) else
                      []),
                    *([Call("Field_Size",
                            [Variable("Ctx"), Variable("Fld")])]
                      if common.has_size_dependent_condition(message) else []),
                ],
            ),
        )

        last = Mul(
            Div(
                Add(
                    Call("Field_Last",
                         [Variable("Ctx"), Variable("Fld")]),
                    Size(const.TYPES_BYTE),
                    -Number(1),
                ),
                Size(const.TYPES_BYTE),
            ),
            Size(const.TYPES_BYTE),
        )
        set_cursors_statements = [
            *([
                PragmaStatement(
                    "Assert",
                    [
                        If([(
                            Or(*[
                                Equal(Variable("Fld"), Variable(
                                    f.affixed_name))
                                for f in message.direct_predecessors(FINAL)
                            ]),
                            Equal(
                                Mod(
                                    Call("Field_Last",
                                         [Variable("Ctx"),
                                          Variable("Fld")]),
                                    Size(const.TYPES_BYTE),
                                ),
                                Number(0),
                            ),
                        )])
                    ],
                )
            ] if len(message.fields) > 1 else []),
            # Improve provability of context predicate
            PragmaStatement(
                "Assert",
                [Equal(Mod(last, Size(const.TYPES_BYTE)), Number(0))]),
            Assignment(Variable("Ctx.Verified_Last"), last),
            PragmaStatement(
                "Assert",
                [
                    LessEqual(
                        Call("Field_Last", [Variable("Ctx"),
                                            Variable("Fld")]),
                        Variable("Ctx.Verified_Last"),
                    )
                ],
            ),
            IfStatement(
                [(
                    Call("Composite_Field", [Variable("Fld")]),
                    [set_context_cursor_composite_field("Fld")],
                )],
                [set_context_cursor_scalar()],
            ) if scalar_fields and composite_fields else
            set_context_cursor_scalar()
            if scalar_fields and not composite_fields else
            set_context_cursor_composite_field("Fld"),
            *([
                # https://github.com/Componolit/RecordFlux/issues/664
                # The provability of the context predicate is increased by splitting the
                # assignment into multiple statements.
                Assignment(
                    Indexed(
                        Variable("Ctx.Cursors"),
                        Call(
                            "Successor",
                            [Variable("Ctx"), Variable("Fld")],
                        ),
                    ),
                    NamedAggregate(
                        ("State", Variable("S_Invalid")),
                        ("Predecessor", Variable("Fld")),
                    ),
                )
            ] if len(message.fields) > 1 else []),
        ]

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification,
                    [
                        Precondition(
                            Call(
                                self.prefix * message.identifier *
                                "Has_Buffer",
                                [Variable("Ctx")],
                            )),
                        Postcondition(
                            And(
                                Call("Has_Buffer", [Variable("Ctx")]),
                                *common.context_invariant(message),
                            )),
                    ],
                )
            ],
            [
                SubprogramBody(
                    specification,
                    [ObjectDeclaration(["Value"], const.TYPES_BASE_INT)],
                    [
                        IfStatement([(
                            AndThen(
                                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",
                                                If(
                                                    [(
                                                        Call(
                                                            "Composite_Field",
                                                            [
                                                                Variable(
                                                                    "Fld"),
                                                            ],
                                                        ),
                                                        Number(0),
                                                    )],
                                                    Call(
                                                        "Get",
                                                        [
                                                            Variable("Ctx"),
                                                            Variable("Fld"),
                                                        ],
                                                    ),
                                                ) if scalar_fields
                                                and composite_fields else Call(
                                                    "Get",
                                                    [
                                                        Variable("Ctx"),
                                                        Variable("Fld"),
                                                    ],
                                                ) if scalar_fields else
                                                Number(0),
                                            ),
                                            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),
                                                ),
                                            ),
                                        )
                                    ],
                                )
                            ],
                        )], )
                    ],
                )
            ],
        )
Пример #16
0
    def create_generic_opaque_getter_procedures(
            self, message: Message,
            opaque_fields: Sequence[Field]) -> UnitPart:
        def specification(field: Field) -> ProcedureSpecification:
            return ProcedureSpecification(f"Generic_Get_{field.name}",
                                          [Parameter(["Ctx"], "Context")])

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification(f),
                    [
                        Precondition(
                            And(
                                Call(
                                    self.prefix * message.identifier *
                                    "Has_Buffer",
                                    [Variable("Ctx")],
                                ),
                                Call(
                                    self.prefix * message.identifier *
                                    "Present",
                                    [
                                        Variable("Ctx"),
                                        Variable(
                                            self.prefix * message.identifier *
                                            f.affixed_name),
                                    ],
                                ),
                            ))
                    ],
                    [
                        FormalSubprogramDeclaration(
                            ProcedureSpecification(
                                f"Process_{f.name}",
                                [Parameter([f.name], const.TYPES_BYTES)]))
                    ],
                ) for f in opaque_fields
            ],
            [
                SubprogramBody(
                    specification(f),
                    [
                        ObjectDeclaration(
                            ["First"],
                            const.TYPES_INDEX,
                            Call(
                                const.TYPES_TO_INDEX,
                                [
                                    Selected(
                                        Indexed(
                                            Variable("Ctx.Cursors"),
                                            Variable(f.affixed_name),
                                        ),
                                        "First",
                                    )
                                ],
                            ),
                            constant=True,
                        ),
                        ObjectDeclaration(
                            ["Last"],
                            const.TYPES_INDEX,
                            Call(
                                const.TYPES_TO_INDEX,
                                [
                                    Selected(
                                        Indexed(
                                            Variable("Ctx.Cursors"),
                                            Variable(f.affixed_name),
                                        ),
                                        "Last",
                                    )
                                ],
                            ),
                            constant=True,
                        ),
                    ],
                    [
                        CallStatement(
                            f"Process_{f.name}",
                            [
                                Slice(Variable("Ctx.Buffer.all"),
                                      Variable("First"), Variable("Last"))
                            ],
                        )
                    ],
                ) for f in opaque_fields
            ],
        )