Beispiel #1
0
 def invalid_successors_invariant() -> Expr:
     return AndThen(
         *[
             If(
                 [
                     (
                         AndThen(
                             *[
                                 Call(
                                     "Invalid",
                                     [Indexed(Variable("Cursors"), Variable(p.affixed_name))],
                                 )
                                 for p in message.direct_predecessors(f)
                             ]
                         ),
                         Call(
                             "Invalid", [Indexed(Variable("Cursors"), Variable(f.affixed_name))],
                         ),
                     )
                 ]
             )
             for f in message.fields
             if f not in message.direct_successors(INITIAL)
         ]
     )
Beispiel #2
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),
                            ),
                        ),
                    ),
                )
            ],
        )
Beispiel #3
0
 def valid_predecessors_invariant() -> Expr:
     return AndThen(
         *[
             If(
                 [
                     (
                         Call(
                             "Structural_Valid",
                             [Indexed(Variable("Cursors"), Variable(f.affixed_name))],
                         ),
                         Or(
                             *[
                                 AndThen(
                                     Call(
                                         "Structural_Valid"
                                         if l.source in composite_fields
                                         else "Valid",
                                         [
                                             Indexed(
                                                 Variable("Cursors"),
                                                 Variable(l.source.affixed_name),
                                             )
                                         ],
                                     ),
                                     Equal(
                                         Selected(
                                             Indexed(
                                                 Variable("Cursors"), Variable(f.affixed_name),
                                             ),
                                             "Predecessor",
                                         ),
                                         Variable(l.source.affixed_name),
                                     ),
                                     l.condition.substituted(
                                         substitution(message, embedded=True)
                                     ),
                                 ).simplified()
                                 for l in message.incoming(f)
                             ]
                         ),
                     )
                 ]
             )
             for f in message.fields
             if f not in message.direct_successors(INITIAL)
         ]
     )
Beispiel #4
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),
                            ),
                        ),
                    ),
                )
            ],
        )
Beispiel #5
0
def valid_message_condition(message: Message,
                            field: Field = INITIAL,
                            structural: bool = False) -> Expr:
    if not message.outgoing(field):
        return TRUE
    return Or(*[
        l.condition if l.target == FINAL else AndThen(
            Call(
                "Structural_Valid" if structural and isinstance(
                    message.types[l.target], Composite) else "Valid",
                [Variable("Ctx"
                          ), Variable(l.target.affixed_name)],
            ),
            l.condition,
            valid_message_condition(message, l.target, structural),
        ) for l in message.outgoing(field)
    ])
Beispiel #6
0
def test_log_expr_str() -> None:
    assert_equal(
        str(And(Variable("A"), Or(Variable("B"), Variable("C")), Variable("D"))),
        multilinestr(
            """A
               and (B
                    or C)
               and D"""
        ),
    )
    assert_equal(
        str(AndThen(Variable("A"), OrElse(Variable("B"), Variable("C")), Variable("D"))),
        multilinestr(
            """A
               and then (B
                         or else C)
               and then D"""
        ),
    )
Beispiel #7
0
    def create_internal_functions(
        self, message: Message, composite_fields: Sequence[Field]
    ) -> UnitPart:
        def result(field: Field, message: Message) -> NamedAggregate:
            aggregate: List[Tuple[str, Expr]] = [("Fld", Name(field.affixed_name))]
            if field in message.fields and isinstance(message.types[field], Scalar):
                aggregate.append(
                    (
                        f"{field.name}_Value",
                        Call(
                            "Extract",
                            [
                                Slice("Ctx.Buffer.all", Name("Buffer_First"), Name("Buffer_Last")),
                                Name("Offset"),
                            ],
                        ),
                    )
                )
            return NamedAggregate(*aggregate)

        return UnitPart(
            [],
            [
                ExpressionFunctionDeclaration(
                    FunctionSpecification(
                        "Sufficient_Buffer_Length",
                        "Boolean",
                        [Parameter(["Ctx"], "Context"), Parameter(["Fld"], "Field")],
                    ),
                    And(
                        NotEqual(Name("Ctx.Buffer"), NULL),
                        LessEqual(Name("Ctx.First"), Div(Last(self.types.bit_index), Number(2))),
                        LessEqual(
                            Call("Field_First", [Name("Ctx"), Name("Fld")]),
                            Div(Last(self.types.bit_index), Number(2)),
                        ),
                        GreaterEqual(Call("Field_Length", [Name("Ctx"), Name("Fld")]), Number(0)),
                        LessEqual(
                            Call("Field_Length", [Name("Ctx"), Name("Fld")]),
                            Div(Last(self.types.bit_length), Number(2)),
                        ),
                        LessEqual(
                            Add(
                                Call("Field_First", [Name("Ctx"), Name("Fld")]),
                                Call("Field_Length", [Name("Ctx"), Name("Fld")]),
                            ),
                            Div(Last(self.types.bit_length), Number(2)),
                        ),
                        LessEqual(
                            Name("Ctx.First"), Call("Field_First", [Name("Ctx"), Name("Fld")])
                        ),
                        GreaterEqual(
                            Name("Ctx.Last"), Call("Field_Last", [Name("Ctx"), Name("Fld")])
                        ),
                    ),
                    [
                        Precondition(
                            And(
                                Call("Has_Buffer", [Name("Ctx")]),
                                Call("Valid_Next", [Name("Ctx"), Name("Fld")]),
                            )
                        )
                    ],
                ),
                ExpressionFunctionDeclaration(
                    FunctionSpecification(
                        "Composite_Field", "Boolean", [Parameter(["Fld"], "Field")]
                    ),
                    Case(
                        Name("Fld"),
                        [
                            (Name(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")],
                    ),
                    [
                        *self.common.field_bit_location_declarations(Name("Fld")),
                        *self.common.field_byte_location_declarations(),
                    ],
                    [
                        ReturnStatement(
                            Case(
                                Name("Fld"),
                                [
                                    (Name(f.affixed_name), result(f, message))
                                    for f in message.fields
                                ],
                            )
                        )
                    ],
                    [
                        Precondition(
                            AndThen(
                                Call("Has_Buffer", [Name("Ctx")]),
                                Call("Valid_Next", [Name("Ctx"), Name("Fld")]),
                                Call("Sufficient_Buffer_Length", [Name("Ctx"), Name("Fld")]),
                            )
                        ),
                        Postcondition(
                            Equal(Selected(Result("Get_Field_Value"), "Fld"), Name("Fld"))
                        ),
                    ],
                ),
            ],
        )
Beispiel #8
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()
            ],
        )
Beispiel #9
0
def context_predicate(message: Message, composite_fields: Sequence[Field], prefix: str) -> Expr:
    def valid_predecessors_invariant() -> Expr:
        return AndThen(
            *[
                If(
                    [
                        (
                            Call(
                                "Structural_Valid",
                                [Indexed(Variable("Cursors"), Variable(f.affixed_name))],
                            ),
                            Or(
                                *[
                                    AndThen(
                                        Call(
                                            "Structural_Valid"
                                            if l.source in composite_fields
                                            else "Valid",
                                            [
                                                Indexed(
                                                    Variable("Cursors"),
                                                    Variable(l.source.affixed_name),
                                                )
                                            ],
                                        ),
                                        Equal(
                                            Selected(
                                                Indexed(
                                                    Variable("Cursors"), Variable(f.affixed_name),
                                                ),
                                                "Predecessor",
                                            ),
                                            Variable(l.source.affixed_name),
                                        ),
                                        l.condition.substituted(
                                            substitution(message, embedded=True)
                                        ),
                                    ).simplified()
                                    for l in message.incoming(f)
                                ]
                            ),
                        )
                    ]
                )
                for f in message.fields
                if f not in message.direct_successors(INITIAL)
            ]
        )

    def invalid_successors_invariant() -> Expr:
        return AndThen(
            *[
                If(
                    [
                        (
                            AndThen(
                                *[
                                    Call(
                                        "Invalid",
                                        [Indexed(Variable("Cursors"), Variable(p.affixed_name))],
                                    )
                                    for p in message.direct_predecessors(f)
                                ]
                            ),
                            Call(
                                "Invalid", [Indexed(Variable("Cursors"), Variable(f.affixed_name))],
                            ),
                        )
                    ]
                )
                for f in message.fields
                if f not in message.direct_successors(INITIAL)
            ]
        )

    return AndThen(
        If(
            [
                (
                    NotEqual(Variable("Buffer"), Variable("null")),
                    And(
                        Equal(First("Buffer"), Variable("Buffer_First")),
                        Equal(Last("Buffer"), Variable("Buffer_Last")),
                    ),
                )
            ]
        ),
        public_context_predicate(),
        ForAllIn(
            "F",
            ValueRange(First("Field"), Last("Field")),
            If(
                [
                    (
                        Call("Structural_Valid", [Indexed(Variable("Cursors"), Variable("F"))]),
                        And(
                            GreaterEqual(
                                Selected(Indexed(Variable("Cursors"), Variable("F")), "First"),
                                Variable("First"),
                            ),
                            LessEqual(
                                Selected(Indexed(Variable("Cursors"), Variable("F")), "Last"),
                                Variable("Last"),
                            ),
                            LessEqual(
                                Selected(Indexed(Variable("Cursors"), Variable("F")), "First"),
                                Add(
                                    Selected(Indexed(Variable("Cursors"), Variable("F")), "Last"),
                                    Number(1),
                                ),
                            ),
                            Equal(
                                Selected(
                                    Selected(Indexed(Variable("Cursors"), Variable("F")), "Value"),
                                    "Fld",
                                ),
                                Variable("F"),
                            ),
                        ),
                    )
                ]
            ),
        ),
        valid_predecessors_invariant(),
        invalid_successors_invariant(),
        message_structure_invariant(message, prefix, embedded=True),
    )
Beispiel #10
0
def message_structure_invariant(
    message: Message, prefix: str, link: Link = None, embedded: bool = False
) -> Expr:
    def prefixed(name: str) -> Expr:
        return Selected(Variable("Ctx"), name) if not embedded else Variable(name)

    if not link:
        return message_structure_invariant(message, prefix, message.outgoing(INITIAL)[0], embedded)

    source = link.source
    target = link.target

    if target is FINAL:
        return TRUE

    field_type = message.types[target]
    condition = link.condition.substituted(substitution(message, embedded)).simplified()
    length = (
        Size(prefix * full_base_type_name(field_type))
        if isinstance(field_type, Scalar)
        else link.length.substituted(
            substitution(message, embedded, target_type=const.TYPES_BIT_LENGTH)
        ).simplified()
    )
    first = (
        prefixed("First")
        if source == INITIAL
        else link.first.substituted(substitution(message, embedded))
        .substituted(
            mapping={
                UNDEFINED: Add(
                    Selected(Indexed(prefixed("Cursors"), Variable(source.affixed_name)), "Last"),
                    Number(1),
                )
            }
        )
        .simplified()
    )

    return If(
        [
            (
                AndThen(
                    Call(
                        "Structural_Valid",
                        [Indexed(prefixed("Cursors"), Variable(target.affixed_name))],
                    ),
                    condition,
                ),
                AndThen(
                    Equal(
                        Add(
                            Sub(
                                Selected(
                                    Indexed(prefixed("Cursors"), Variable(target.affixed_name)),
                                    "Last",
                                ),
                                Selected(
                                    Indexed(prefixed("Cursors"), Variable(target.affixed_name)),
                                    "First",
                                ),
                            ),
                            Number(1),
                        ),
                        length,
                    ),
                    Equal(
                        Selected(
                            Indexed(prefixed("Cursors"), Variable(target.affixed_name)),
                            "Predecessor",
                        ),
                        Variable(source.affixed_name),
                    ),
                    Equal(
                        Selected(
                            Indexed(prefixed("Cursors"), Variable(target.affixed_name)), "First"
                        ),
                        first,
                    ),
                    *[
                        message_structure_invariant(message, prefix, l, embedded)
                        for l in message.outgoing(target)
                    ],
                ),
            )
        ]
    ).simplified()
Beispiel #11
0
    def context_predicate(self, message: Message, composite_fields: Sequence[Field]) -> Expr:
        def valid_predecessors_invariant() -> Expr:
            return AndThen(
                *[
                    If(
                        [
                            (
                                Call(
                                    "Structural_Valid", [Indexed("Cursors", Name(f.affixed_name))]
                                ),
                                Or(
                                    *[
                                        AndThen(
                                            Call(
                                                "Structural_Valid"
                                                if l.source in composite_fields
                                                else "Valid",
                                                [Indexed("Cursors", Name(l.source.affixed_name))],
                                            ),
                                            Equal(
                                                Selected(
                                                    Indexed("Cursors", Name(f.affixed_name)),
                                                    "Predecessor",
                                                ),
                                                Name(l.source.affixed_name),
                                            ),
                                            l.condition,
                                        ).simplified(self.substitution(message, False))
                                        for l in message.incoming(f)
                                    ]
                                ),
                            )
                        ]
                    )
                    for f in message.fields
                    if f not in message.direct_successors(INITIAL)
                ]
            )

        def invalid_successors_invariant() -> Expr:
            return AndThen(
                *[
                    If(
                        [
                            (
                                AndThen(
                                    *[
                                        Call("Invalid", [Indexed("Cursors", Name(p.affixed_name))])
                                        for p in message.direct_predecessors(f)
                                    ]
                                ),
                                Call("Invalid", [Indexed("Cursors", Name(f.affixed_name))]),
                            )
                        ]
                    )
                    for f in message.fields
                    if f not in message.direct_successors(INITIAL)
                ]
            )

        return AndThen(
            If(
                [
                    (
                        NotEqual(Name(Name("Buffer")), NULL),
                        And(
                            Equal(First(Name("Buffer")), Name(Name("Buffer_First"))),
                            Equal(Last(Name("Buffer")), Name(Name("Buffer_Last"))),
                        ),
                    )
                ]
            ),
            GreaterEqual(
                Call(self.types.byte_index, [Name(Name("First"))]), Name(Name("Buffer_First"))
            ),
            LessEqual(Call(self.types.byte_index, [Name(Name("Last"))]), Name(Name("Buffer_Last"))),
            LessEqual(Name(Name("First")), Name(Name("Last"))),
            LessEqual(Name(Name("Last")), Div(Last(self.types.bit_index), Number(2))),
            ForAllIn(
                "F",
                ValueRange(First("Field"), Last("Field")),
                If(
                    [
                        (
                            Call("Structural_Valid", [Indexed(Name("Cursors"), Name("F"))]),
                            And(
                                GreaterEqual(
                                    Selected(Indexed(Name("Cursors"), Name("F")), "First"),
                                    Name(Name("First")),
                                ),
                                LessEqual(
                                    Selected(Indexed(Name("Cursors"), Name("F")), "Last"),
                                    Name(Name("Last")),
                                ),
                                LessEqual(
                                    Selected(Indexed(Name("Cursors"), Name("F")), "First"),
                                    Add(
                                        Selected(Indexed(Name("Cursors"), Name("F")), "Last"),
                                        Number(1),
                                    ),
                                ),
                                Equal(
                                    Selected(
                                        Selected(Indexed(Name("Cursors"), Name("F")), "Value"),
                                        "Fld",
                                    ),
                                    Name("F"),
                                ),
                            ),
                        )
                    ]
                ),
            ),
            valid_predecessors_invariant(),
            invalid_successors_invariant(),
            self.message_structure_invariant(message, prefix=False),
        )
Beispiel #12
0
    def message_structure_invariant(
        self, message: Message, link: Link = None, prefix: bool = True
    ) -> Expr:
        def prefixed(name: str) -> Expr:
            return Selected(Name("Ctx"), name) if prefix else Name(name)

        if not link:
            return self.message_structure_invariant(message, message.outgoing(INITIAL)[0], prefix)

        source = link.source
        target = link.target

        if target is FINAL:
            return TRUE

        field_type = message.types[target]
        condition = link.condition.simplified(self.substitution(message, prefix))
        length = (
            Size(base_type_name(field_type))
            if isinstance(field_type, Scalar)
            else link.length.simplified(self.substitution(message, prefix))
        )
        first = (
            Name(prefixed("First"))
            if source == INITIAL
            else link.first.simplified(
                {
                    **self.substitution(message, prefix),
                    **{
                        UNDEFINED: Add(
                            Selected(
                                Indexed(prefixed("Cursors"), Name(source.affixed_name)), "Last"
                            ),
                            Number(1),
                        )
                    },
                }
            )
        )

        return If(
            [
                (
                    AndThen(
                        Call(
                            "Structural_Valid",
                            [Indexed(prefixed("Cursors"), Name(target.affixed_name))],
                        ),
                        condition,
                    ),
                    AndThen(
                        Equal(
                            Add(
                                Sub(
                                    Selected(
                                        Indexed(prefixed("Cursors"), Name(target.affixed_name)),
                                        "Last",
                                    ),
                                    Selected(
                                        Indexed(prefixed("Cursors"), Name(target.affixed_name)),
                                        "First",
                                    ),
                                ),
                                Number(1),
                            ),
                            length,
                        ),
                        Equal(
                            Selected(
                                Indexed(prefixed("Cursors"), Name(target.affixed_name)),
                                "Predecessor",
                            ),
                            Name(source.affixed_name),
                        ),
                        Equal(
                            Selected(
                                Indexed(prefixed("Cursors"), Name(target.affixed_name)), "First"
                            ),
                            first,
                        ),
                        *[
                            self.message_structure_invariant(message, l, prefix)
                            for l in message.outgoing(target)
                        ],
                    ),
                )
            ]
        ).simplified()
Beispiel #13
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"),
                                 ]
                             ],
                         )
                     ),
                 ],
             )
         ],
     )
Beispiel #14
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)
            ],
        )
Beispiel #15
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)
            ],
        )
Beispiel #16
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()
            ],
        )
Beispiel #17
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"),
                            )),
                    ],
                ),
            ],
        )
Beispiel #18
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)
            ],
        )
Beispiel #19
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)
            ],
        )
Beispiel #20
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),
                                                ),
                                            ),
                                        )
                                    ],
                                )
                            ],
                        )], )
                    ],
                )
            ],
        )
Beispiel #21
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"],
                                      const.TYPES_BIT_INDEX),
                     ],
                 ),
                 [
                     *common.field_bit_location_declarations(
                         Variable("Val.Fld")),
                     *common.field_byte_location_declarations(),
                     *unique(
                         self.insert_function(common.full_base_type_name(t))
                         for t in message.types.values()
                         if isinstance(t, Scalar)),
                 ],
                 [
                     Assignment("Fst", Variable("First")),
                     Assignment("Lst", Variable("Last")),
                     CaseStatement(
                         Variable("Val.Fld"),
                         [(
                             Variable(f.affixed_name),
                             [
                                 CallStatement(
                                     "Insert",
                                     [
                                         Variable(f"Val.{f.name}_Value"),
                                         Slice(
                                             Variable("Ctx.Buffer.all"),
                                             Variable("Buffer_First"),
                                             Variable("Buffer_Last"),
                                         ),
                                         Variable("Offset"),
                                     ],
                                 )
                                 if f in scalar_fields else NullStatement()
                             ],
                         ) for f in message.all_fields],
                     ),
                 ],
                 [
                     Precondition(
                         AndThen(
                             Not(Constrained("Ctx")),
                             Call("Has_Buffer", [Variable("Ctx")]),
                             In(Variable("Val.Fld"), Range("Field")),
                             Call("Valid_Next",
                                  [Variable("Ctx"),
                                   Variable("Val.Fld")]),
                             common.sufficient_space_for_field_condition(
                                 Variable("Val.Fld")),
                             ForAllIn(
                                 "F",
                                 Range("Field"),
                                 If([(
                                     Call(
                                         "Structural_Valid",
                                         [
                                             Indexed(
                                                 Variable("Ctx.Cursors"),
                                                 Variable("F"),
                                             )
                                         ],
                                     ),
                                     LessEqual(
                                         Selected(
                                             Indexed(
                                                 Variable("Ctx.Cursors"),
                                                 Variable("F"),
                                             ),
                                             "Last",
                                         ),
                                         Call(
                                             "Field_Last",
                                             [
                                                 Variable("Ctx"),
                                                 Variable("Val.Fld")
                                             ],
                                         ),
                                     ),
                                 )]),
                             ),
                         )),
                     Postcondition(
                         And(
                             Call("Has_Buffer", [Variable("Ctx")]),
                             Equal(
                                 Variable("Fst"),
                                 Call(
                                     "Field_First",
                                     [Variable("Ctx"),
                                      Variable("Val.Fld")]),
                             ),
                             Equal(
                                 Variable("Lst"),
                                 Call(
                                     "Field_Last",
                                     [Variable("Ctx"),
                                      Variable("Val.Fld")]),
                             ),
                             GreaterEqual(Variable("Fst"),
                                          Variable("Ctx.First")),
                             LessEqual(Variable("Fst"),
                                       Add(Variable("Lst"), Number(1))),
                             LessEqual(
                                 Call(const.TYPES_BYTE_INDEX,
                                      [Variable("Lst")]),
                                 Variable("Ctx.Buffer_Last"),
                             ),
                             ForAllIn(
                                 "F",
                                 Range("Field"),
                                 If([(
                                     Call(
                                         "Structural_Valid",
                                         [
                                             Indexed(
                                                 Variable("Ctx.Cursors"),
                                                 Variable("F"),
                                             )
                                         ],
                                     ),
                                     LessEqual(
                                         Selected(
                                             Indexed(
                                                 Variable("Ctx.Cursors"),
                                                 Variable("F"),
                                             ),
                                             "Last",
                                         ),
                                         Variable("Lst"),
                                     ),
                                 )]),
                             ),
                             *[
                                 Equal(e, Old(e)) for e in [
                                     Variable("Ctx.Buffer_First"),
                                     Variable("Ctx.Buffer_Last"),
                                     Variable("Ctx.First"),
                                     Variable("Ctx.Cursors"),
                                 ]
                             ],
                         )),
                 ],
             )
         ] if scalar_fields else [],
     )