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

        return UnitPart(
            [SubprogramDeclaration(specification)],
            private=[
                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),
                            ),
                        ),
                    ),
                )
            ],
        )
Example #2
0
    def create_invalid_function() -> UnitPart:
        specification = FunctionSpecification(
            "Invalid", "Boolean",
            [Parameter(["Ctx"], "Context"),
             Parameter(["Fld"], "Field")])

        return UnitPart(
            [SubprogramDeclaration(specification)],
            private=[
                ExpressionFunctionDeclaration(
                    specification,
                    Or(
                        Equal(
                            Selected(
                                Indexed(Variable("Ctx.Cursors"),
                                        Variable("Fld")), "State"),
                            Variable("S_Invalid"),
                        ),
                        Equal(
                            Selected(
                                Indexed(Variable("Ctx.Cursors"),
                                        Variable("Fld")), "State"),
                            Variable("S_Incomplete"),
                        ),
                    ),
                )
            ],
        )
Example #3
0
def set_context_cursor_composite_field(field_name: str) -> Assignment:
    return Assignment(
        Indexed(
            Variable("Ctx.Cursors"),
            Variable(field_name),
        ),
        NamedAggregate(
            ("State", Variable("S_Structural_Valid")),
            (
                "First",
                Call(
                    "Field_First",
                    [Variable("Ctx"), Variable(field_name)],
                ),
            ),
            (
                "Last",
                Call(
                    "Field_Last",
                    [Variable("Ctx"), Variable(field_name)],
                ),
            ),
            ("Value", Variable("Value")),
            (
                "Predecessor",
                Selected(
                    Indexed(
                        Variable("Ctx.Cursors"),
                        Variable(field_name),
                    ),
                    "Predecessor",
                ),
            ),
        ),
    )
Example #4
0
def set_context_cursor_scalar() -> Assignment:
    return 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"),
            ),
        ),
    )
Example #5
0
 def result(field: Field) -> Expr:
     return Call(
         "To_Actual",
         [
             Selected(
                 Indexed(Variable("Ctx.Cursors"),
                         Variable(field.affixed_name)), "Value")
         ],
     )
Example #6
0
 def valid_predecessors_invariant() -> Expr:
     return AndThen(
         *[
             If(
                 [
                     (
                         Call(
                             "Structural_Valid",
                             [
                                 Indexed(
                                     Variable("Cursors"),
                                     Variable(f.affixed_name),
                                 )
                             ],
                         ),
                         Or(
                             *[
                                 expr.AndThen(
                                     expr.Call(
                                         "Structural_Valid"
                                         if l.source in composite_fields
                                         else "Valid",
                                         [
                                             expr.Indexed(
                                                 expr.Variable("Cursors"),
                                                 expr.Variable(l.source.affixed_name),
                                             )
                                         ],
                                     ),
                                     expr.Equal(
                                         expr.Selected(
                                             expr.Indexed(
                                                 expr.Variable("Cursors"),
                                                 expr.Variable(f.affixed_name),
                                             ),
                                             "Predecessor",
                                         ),
                                         expr.Variable(l.source.affixed_name),
                                     ),
                                     l.condition.substituted(
                                         substitution(message, embedded=True, prefix=prefix)
                                     ),
                                 )
                                 .simplified()
                                 .ada_expr()
                                 for l in message.incoming(f)
                             ]
                         ),
                     )
                 ]
             )
             for f in message.fields
             if f not in message.direct_successors(model.INITIAL)
         ]
     )
Example #7
0
def unchanged_cursor_before_or_invalid(
    limit: Expr, loop_entry: bool, or_invalid: bool = True
) -> Expr:
    return ForAllIn(
        "F",
        Variable("Field"),
        IfExpr(
            [
                (
                    Less(Variable("F"), limit),
                    Equal(
                        Indexed(
                            Variable("Ctx.Cursors"),
                            Variable("F"),
                        ),
                        Indexed(
                            LoopEntry(Variable("Ctx.Cursors"))
                            if loop_entry
                            else Old(Variable("Ctx.Cursors")),
                            Variable("F"),
                        ),
                    ),
                )
            ],
            *(
                [
                    Call(
                        "Invalid",
                        [
                            Variable("Ctx"),
                            Variable("F"),
                        ],
                    )
                ]
                if or_invalid
                else []
            ),
        ),
    )
Example #8
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(model.INITIAL)
         ]
     )
Example #9
0
def conditional_field_size(field: model.Field, message: model.Message, prefix: str) -> Expr:
    def substituted(expression: expr.Expr) -> Expr:
        return (
            expression.substituted(
                substitution(message, prefix, target_type=const.TYPES_BIT_LENGTH)
            )
            .simplified()
            .ada_expr()
        )

    field_type = message.field_types[field]

    if isinstance(field_type, model.Scalar):
        return field_type.size.ada_expr()

    links = message.incoming(field)

    if len(links) == 1:
        return substituted(links[0].size)

    return If(
        [
            (
                AndThen(
                    Equal(
                        Selected(
                            Indexed(Variable("Ctx.Cursors"), Variable("Fld")),
                            "Predecessor",
                        ),
                        Variable(l.source.affixed_name),
                    ),
                    *([substituted(l.condition)] if l.condition != expr.TRUE else []),
                ),
                substituted(l.size),
            )
            for l in links
        ],
        const.UNREACHABLE,
    )
Example #10
0
 def cursors_invariant() -> Expr:
     return ForAllIn(
         "F",
         Variable("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("Verified_Last"),
                         ),
                         LessEqual(
                             Selected(Indexed(Variable("Cursors"), Variable("F")), "First"),
                             Add(
                                 Selected(
                                     Indexed(Variable("Cursors"), Variable("F")),
                                     "Last",
                                 ),
                                 Number(1),
                             ),
                         ),
                         Call(
                             "Valid_Value",
                             [
                                 Variable("F"),
                                 Selected(
                                     Indexed(Variable("Cursors"), Variable("F")),
                                     "Value",
                                 ),
                             ],
                         ),
                     ),
                 )
             ]
         ),
     )
Example #11
0
    def create_structural_valid_function() -> UnitPart:
        specification = FunctionSpecification(
            "Structural_Valid",
            "Boolean",
            [Parameter(["Ctx"], "Context"),
             Parameter(["Fld"], "Field")],
        )

        return UnitPart(
            [SubprogramDeclaration(specification)],
            private=[
                ExpressionFunctionDeclaration(
                    specification,
                    Or(*[
                        Equal(
                            Selected(
                                Indexed(Variable("Ctx.Cursors"), Variable(
                                    "Fld")), "State"),
                            Variable(s),
                        ) for s in ("S_Valid", "S_Structural_Valid")
                    ]),
                )
            ],
        )
Example #12
0
    def create_opaque_getter_procedures(
            self, message: Message,
            opaque_fields: Sequence[Field]) -> UnitPart:
        def specification(field: Field) -> ProcedureSpecification:
            return ProcedureSpecification(
                f"Get_{field.name}",
                [
                    Parameter(["Ctx"], "Context"),
                    OutParameter(["Data"], const.TYPES_BYTES)
                ],
            )

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

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

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification(f),
                    [
                        Ghost(),
                        Precondition(
                            AndThen(
                                Call(
                                    self.prefix * message.identifier *
                                    "Has_Buffer",
                                    [Variable("Ctx")],
                                ),
                                Call(
                                    self.prefix * message.identifier *
                                    "Structural_Valid",
                                    [
                                        Variable("Ctx"),
                                        Variable(
                                            self.prefix * message.identifier *
                                            f.affixed_name),
                                    ],
                                ),
                                Call(
                                    self.prefix * message.identifier *
                                    "Valid_Next",
                                    [
                                        Variable("Ctx"),
                                        Variable(
                                            self.prefix * message.identifier *
                                            f.affixed_name),
                                    ],
                                ),
                            )),
                        Postcondition(
                            Equal(
                                Length(Result(name(f))),
                                Call(
                                    const.TYPES_TO_LENGTH,
                                    [
                                        Call(
                                            "Field_Size",
                                            [
                                                Variable("Ctx"),
                                                Variable(f.affixed_name),
                                            ],
                                        )
                                    ],
                                ),
                            )),
                    ],
                ) for f in opaque_fields
            ],
            [
                SubprogramBody(
                    specification(f),
                    [
                        ObjectDeclaration(
                            ["First"],
                            const.TYPES_INDEX,
                            Call(
                                const.TYPES_TO_INDEX,
                                [
                                    Selected(
                                        Indexed(
                                            Variable("Ctx.Cursors"),
                                            Variable(f.affixed_name),
                                        ),
                                        "First",
                                    )
                                ],
                            ),
                            constant=True,
                        ),
                        ObjectDeclaration(
                            ["Last"],
                            const.TYPES_INDEX,
                            Call(
                                const.TYPES_TO_INDEX,
                                [
                                    Selected(
                                        Indexed(
                                            Variable("Ctx.Cursors"),
                                            Variable(f.affixed_name),
                                        ),
                                        "Last",
                                    )
                                ],
                            ),
                            constant=True,
                        ),
                    ],
                    [
                        ReturnStatement(
                            Slice(Variable("Ctx.Buffer.all"),
                                  Variable("First"), Variable("Last")), )
                    ],
                ) for f in opaque_fields
            ],
        )
Example #14
0
def initialize_field_statements(
    field: model.Field, reset_written_last: bool = False
) -> Sequence[Statement]:
    return [
        CallStatement(
            "Reset_Dependent_Fields",
            [Variable("Ctx"), Variable(field.affixed_name)],
        ),
        # https://github.com/Componolit/RecordFlux/issues/868
        PragmaStatement(
            "Warnings",
            [
                Variable("Off"),
                String("attribute Update is an obsolescent feature"),
            ],
        ),
        Assignment(
            "Ctx",
            Update(
                "Ctx",
                ("Verified_Last", Variable("Last")),
                (
                    "Written_Last",
                    Variable("Last")
                    if reset_written_last
                    else Max(
                        const.TYPES_BIT_LENGTH,
                        Variable("Ctx.Written_Last"),
                        Variable("Last"),
                    ),
                ),
            ),
        ),
        PragmaStatement(
            "Warnings",
            [
                Variable("On"),
                String("attribute Update is an obsolescent feature"),
            ],
        ),
        Assignment(
            Indexed(Variable("Ctx.Cursors"), Variable(field.affixed_name)),
            NamedAggregate(
                ("State", Variable("S_Structural_Valid")),
                ("First", Variable("First")),
                ("Last", Variable("Last")),
                ("Value", Number(0)),
                (
                    "Predecessor",
                    Selected(
                        Indexed(
                            Variable("Ctx.Cursors"),
                            Variable(field.affixed_name),
                        ),
                        "Predecessor",
                    ),
                ),
            ),
        ),
        Assignment(
            Indexed(
                Variable("Ctx.Cursors"),
                Call(
                    "Successor",
                    [Variable("Ctx"), Variable(field.affixed_name)],
                ),
            ),
            NamedAggregate(
                ("State", Variable("S_Invalid")),
                ("Predecessor", Variable(field.affixed_name)),
            ),
        ),
    ]
Example #15
0
    def create_generic_opaque_getter_procedures(
            self, message: Message,
            opaque_fields: Sequence[Field]) -> UnitPart:
        def specification(field: Field) -> ProcedureSpecification:
            return ProcedureSpecification(f"Generic_Get_{field.name}",
                                          [Parameter(["Ctx"], "Context")])

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification(f),
                    [
                        Precondition(
                            And(
                                Call(
                                    self.prefix * message.identifier *
                                    "Has_Buffer",
                                    [Variable("Ctx")],
                                ),
                                Call(
                                    self.prefix * message.identifier *
                                    "Present",
                                    [
                                        Variable("Ctx"),
                                        Variable(
                                            self.prefix * message.identifier *
                                            f.affixed_name),
                                    ],
                                ),
                            ))
                    ],
                    [
                        FormalSubprogramDeclaration(
                            ProcedureSpecification(
                                f"Process_{f.name}",
                                [Parameter([f.name], const.TYPES_BYTES)]))
                    ],
                ) for f in opaque_fields
            ],
            [
                SubprogramBody(
                    specification(f),
                    [
                        ObjectDeclaration(
                            ["First"],
                            const.TYPES_INDEX,
                            Call(
                                const.TYPES_TO_INDEX,
                                [
                                    Selected(
                                        Indexed(
                                            Variable("Ctx.Cursors"),
                                            Variable(f.affixed_name),
                                        ),
                                        "First",
                                    )
                                ],
                            ),
                            constant=True,
                        ),
                        ObjectDeclaration(
                            ["Last"],
                            const.TYPES_INDEX,
                            Call(
                                const.TYPES_TO_INDEX,
                                [
                                    Selected(
                                        Indexed(
                                            Variable("Ctx.Cursors"),
                                            Variable(f.affixed_name),
                                        ),
                                        "Last",
                                    )
                                ],
                            ),
                            constant=True,
                        ),
                    ],
                    [
                        CallStatement(
                            f"Process_{f.name}",
                            [
                                Slice(Variable("Ctx.Buffer.all"),
                                      Variable("First"), Variable("Last"))
                            ],
                        )
                    ],
                ) for f in opaque_fields
            ],
        )
Example #16
0
    def create_verify_procedure(
        self,
        message: Message,
        scalar_fields: Mapping[Field, Scalar],
        composite_fields: Sequence[Field],
    ) -> UnitPart:
        specification = ProcedureSpecification(
            "Verify",
            [InOutParameter(["Ctx"], "Context"),
             Parameter(["Fld"], "Field")])

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

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

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification,
                    [
                        Precondition(
                            Call(
                                self.prefix * message.identifier *
                                "Has_Buffer",
                                [Variable("Ctx")],
                            )),
                        Postcondition(
                            And(
                                Call("Has_Buffer", [Variable("Ctx")]),
                                *common.context_invariant(message),
                            )),
                    ],
                )
            ],
            [
                SubprogramBody(
                    specification,
                    [ObjectDeclaration(["Value"], const.TYPES_BASE_INT)],
                    [
                        IfStatement([(
                            AndThen(
                                Call(
                                    "Invalid",
                                    [
                                        Indexed(Variable("Ctx.Cursors"),
                                                Variable("Fld"))
                                    ],
                                ),
                                Call("Valid_Predecessor",
                                     [Variable("Ctx"),
                                      Variable("Fld")]),
                                Call("Path_Condition",
                                     [Variable("Ctx"),
                                      Variable("Fld")]),
                            ),
                            [
                                IfStatement(
                                    [(
                                        Call(
                                            "Sufficient_Buffer_Length",
                                            [Variable("Ctx"),
                                             Variable("Fld")],
                                        ),
                                        [
                                            Assignment(
                                                "Value",
                                                If(
                                                    [(
                                                        Call(
                                                            "Composite_Field",
                                                            [
                                                                Variable(
                                                                    "Fld"),
                                                            ],
                                                        ),
                                                        Number(0),
                                                    )],
                                                    Call(
                                                        "Get",
                                                        [
                                                            Variable("Ctx"),
                                                            Variable("Fld"),
                                                        ],
                                                    ),
                                                ) if scalar_fields
                                                and composite_fields else Call(
                                                    "Get",
                                                    [
                                                        Variable("Ctx"),
                                                        Variable("Fld"),
                                                    ],
                                                ) if scalar_fields else
                                                Number(0),
                                            ),
                                            IfStatement(
                                                [(
                                                    valid_field_condition,
                                                    set_cursors_statements,
                                                )],
                                                [
                                                    Assignment(
                                                        Indexed(
                                                            Variable(
                                                                "Ctx.Cursors"),
                                                            Variable("Fld"),
                                                        ),
                                                        NamedAggregate(
                                                            (
                                                                "State",
                                                                Variable(
                                                                    "S_Invalid"
                                                                ),
                                                            ),
                                                            (
                                                                "Predecessor",
                                                                Variable(
                                                                    FINAL.
                                                                    affixed_name,
                                                                ),
                                                            ),
                                                        ),
                                                    )
                                                ],
                                            ),
                                        ],
                                    )],
                                    [
                                        Assignment(
                                            Indexed(Variable("Ctx.Cursors"),
                                                    Variable("Fld")),
                                            NamedAggregate(
                                                ("State",
                                                 Variable("S_Incomplete")),
                                                (
                                                    "Predecessor",
                                                    Variable(
                                                        FINAL.affixed_name),
                                                ),
                                            ),
                                        )
                                    ],
                                )
                            ],
                        )], )
                    ],
                )
            ],
        )
Example #17
0
def message_structure_invariant(
    message: model.Message, prefix: str, link: model.Link = None, embedded: bool = False
) -> Expr:
    def prefixed(name: str) -> expr.Expr:
        return expr.Selected(expr.Variable("Ctx"), name) if not embedded else expr.Variable(name)

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

    source = link.source
    target = link.target

    if target == model.FINAL:
        return TRUE

    field_type = message.types[target]
    condition = link.condition.substituted(substitution(message, prefix, embedded)).simplified()
    size = (
        field_type.size
        if isinstance(field_type, model.Scalar)
        else link.size.substituted(
            substitution(message, prefix, embedded, target_type=const.TYPES_BIT_LENGTH)
        ).simplified()
    )
    first = (
        prefixed("First")
        if source == model.INITIAL
        else link.first.substituted(
            substitution(message, prefix, embedded, target_type=const.TYPES_BIT_INDEX)
        )
        .substituted(
            mapping={
                expr.UNDEFINED: expr.Add(
                    expr.Selected(
                        expr.Indexed(prefixed("Cursors"), expr.Variable(source.affixed_name)),
                        "Last",
                    ),
                    expr.Number(1),
                )
            }
        )
        .simplified()
    )
    invariant = [
        message_structure_invariant(message, prefix, l, embedded) for l in message.outgoing(target)
    ]

    return If(
        [
            (
                AndThen(
                    Call(
                        "Structural_Valid",
                        [Indexed(prefixed("Cursors").ada_expr(), Variable(target.affixed_name))],
                    ),
                    *([condition.ada_expr()] if condition != expr.TRUE else []),
                ),
                AndThen(
                    Equal(
                        Add(
                            Sub(
                                Selected(
                                    Indexed(
                                        prefixed("Cursors").ada_expr(),
                                        Variable(target.affixed_name),
                                    ),
                                    "Last",
                                ),
                                Selected(
                                    Indexed(
                                        prefixed("Cursors").ada_expr(),
                                        Variable(target.affixed_name),
                                    ),
                                    "First",
                                ),
                            ),
                            Number(1),
                        ),
                        size.ada_expr(),
                    ),
                    Equal(
                        Selected(
                            Indexed(
                                prefixed("Cursors").ada_expr(),
                                Variable(target.affixed_name),
                            ),
                            "Predecessor",
                        ),
                        Variable(source.affixed_name),
                    ),
                    Equal(
                        Selected(
                            Indexed(
                                prefixed("Cursors").ada_expr(),
                                Variable(target.affixed_name),
                            ),
                            "First",
                        ),
                        first.ada_expr(),
                    ),
                    *[i for i in invariant if i != TRUE],
                ),
            )
        ]
    )