예제 #1
0
def valid_path_to_next_field_condition(
    message: model.Message, field: model.Field, prefix: str
) -> Sequence[Expr]:
    return [
        If(
            [
                (
                    l.condition.substituted(substitution(message, public=True, prefix=prefix))
                    .simplified()
                    .ada_expr(),
                    And(
                        Equal(
                            Call(
                                "Predecessor",
                                [Variable("Ctx"), Variable(l.target.affixed_name)],
                            ),
                            Variable(field.affixed_name),
                        ),
                        Call(
                            "Valid_Next",
                            [Variable("Ctx"), Variable(l.target.affixed_name)],
                        )
                        if l.target != model.FINAL
                        else TRUE,
                    ),
                )
            ]
        )
        for l in message.outgoing(field)
        if l.target != model.FINAL
    ]
예제 #2
0
def field_condition_call(
    prefix: str,
    message: model.Message,
    field: model.Field,
    value: Expr = None,
    aggregate: Expr = None,
    size: Expr = None,
) -> Expr:
    package = prefix * message.identifier
    if value is None:
        value = Number(0)
    if aggregate is None:
        aggregate = EMPTY_ARRAY
    if size is None:
        size = Call(
            package * "Field_Size",
            [Variable("Ctx"), Variable(package * field.affixed_name)],
        )
    return Call(
        package * "Field_Condition",
        [
            Variable("Ctx"),
            Variable(package * field.affixed_name),
            *([value] if has_value_dependent_condition(message) else []),
            *([aggregate] if has_aggregate_dependent_condition(message) else []),
            *([size] if has_size_dependent_condition(message, field) else []),
        ],
    )
예제 #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",
                ),
            ),
        ),
    )
예제 #4
0
def public_context_predicate() -> Expr:
    return And(
        GreaterEqual(Call(const.TYPES_TO_INDEX, [Variable("First")]), Variable("Buffer_First")),
        LessEqual(Call(const.TYPES_TO_INDEX, [Variable("Last")]), Variable("Buffer_Last")),
        Less(Variable("Buffer_Last"), Last(const.TYPES_INDEX)),
        LessEqual(Variable("First"), Add(Variable("Last"), Number(1))),
        Less(Variable("Last"), Last(const.TYPES_BIT_INDEX)),
        Equal(Rem(Variable("First"), Size(const.TYPES_BYTE)), Number(1)),
        Equal(Rem(Variable("Last"), Size(const.TYPES_BYTE)), Number(0)),
    )
예제 #5
0
    def create_valid_function() -> UnitPart:
        specification = FunctionSpecification(
            "Valid", "Boolean",
            [Parameter(["Ctx"], "Context"),
             Parameter(["Fld"], "Field")])

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification,
                    [
                        Postcondition(
                            If([(
                                Result("Valid"),
                                And(
                                    Call(
                                        "Structural_Valid",
                                        [Variable("Ctx"),
                                         Variable("Fld")],
                                    ),
                                    Call("Present",
                                         [Variable("Ctx"),
                                          Variable("Fld")]),
                                ),
                            )])),
                    ],
                )
            ],
            private=[
                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),
                            ),
                        ),
                    ),
                )
            ],
        )
예제 #6
0
def context_cursor_unchanged(
    message: model.Message, field: model.Field, predecessors: bool
) -> List[Expr]:
    lower: model.Field
    upper: model.Field
    if predecessors:
        if len(message.predecessors(field)) == 0:
            return []
        lower = message.fields[0]
        upper = message.fields[message.fields.index(field) - 1]
    else:
        if len(message.successors(field)) == 0:
            return []
        lower = message.fields[message.fields.index(field) + 1]
        upper = message.fields[-1]
    return [
        ForAllIn(
            "F",
            ValueRange(
                lower=Variable(lower.affixed_name),
                upper=Variable(upper.affixed_name),
                type_identifier=ID("Field"),
            ),
            Equal(
                Call(
                    "Context_Cursors_Index",
                    [
                        Call(
                            "Context_Cursors",
                            [Variable("Ctx")],
                        ),
                        Variable("F"),
                    ],
                ),
                Call(
                    "Context_Cursors_Index",
                    [
                        Old(
                            Call(
                                "Context_Cursors",
                                [Variable("Ctx")],
                            )
                        ),
                        Variable("F"),
                    ],
                ),
            ),
        )
    ]
예제 #7
0
def field_bit_location_declarations(field_name: Name) -> Sequence[Declaration]:
    return [
        ObjectDeclaration(
            ["First"],
            const.TYPES_BIT_INDEX,
            Call("Field_First", [Variable("Ctx"), field_name]),
            constant=True,
        ),
        ObjectDeclaration(
            ["Last"],
            const.TYPES_BIT_INDEX,
            Call("Field_Last", [Variable("Ctx"), field_name]),
            constant=True,
        ),
    ]
예제 #8
0
    def create_verify_message_procedure(self, message: Message) -> UnitPart:
        specification = ProcedureSpecification(
            "Verify_Message", [InOutParameter(["Ctx"], "Context")])

        loop_invariant = And(
            Call("Has_Buffer", [Variable("Ctx")]),
            *common.context_invariant(message, loop_entry=True),
        )

        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,
                    [],
                    [
                        ForIn(
                            "F",
                            Variable("Field"),
                            [
                                PragmaStatement("Loop_Invariant",
                                                [loop_invariant]),
                                CallStatement("Verify",
                                              [Variable("Ctx"),
                                               Variable("F")]),
                            ],
                        )
                    ],
                )
            ],
        )
예제 #9
0
    def create_valid_message_function(self, message: Message) -> UnitPart:
        specification = FunctionSpecification("Valid_Message", "Boolean",
                                              [Parameter(["Ctx"], "Context")])

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification,
                    [
                        Precondition(
                            Call(
                                self.prefix * message.identifier *
                                "Has_Buffer",
                                [Variable("Ctx")],
                            ))
                    ],
                )
            ],
            private=[
                ExpressionFunctionDeclaration(
                    specification,
                    self.valid_message_condition(message),
                )
            ],
        )
예제 #10
0
 def _create_init_proc(self, slots: Sequence[NumberedSlotInfo]) -> UnitPart:
     proc = ProcedureSpecification(
         "Initialize",
         [OutParameter(["S"], "Slots"),
          Parameter(["M"], "Memory")])
     return UnitPart(
         [
             SubprogramDeclaration(
                 proc,
                 [Postcondition(Call("Initialized", [Variable("S")]))]),
         ],
         [
             SubprogramBody(
                 proc,
                 declarations=[],
                 statements=([
                     Assignment(
                         "S" * self._slot_name(slot.slot_id),
                         UnrestrictedAccess(
                             Variable(ID(f"M.Slot_{slot.slot_id}"))),
                     ) for slot in slots
                 ] if slots else [NullStatement()]),
                 aspects=[SparkMode(off=True)],
             )
         ],
     )
예제 #11
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"),
            ),
        ),
    )
예제 #12
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",
                                 ),
                             ],
                         ),
                     ),
                 )
             ]
         ),
     )
예제 #13
0
 def result(field: Field) -> Expr:
     return Call(
         "To_Actual",
         [
             Selected(
                 Indexed(Variable("Ctx.Cursors"),
                         Variable(field.affixed_name)), "Value")
         ],
     )
예제 #14
0
    def create_scalar_getter_functions(
            self, message: Message,
            scalar_fields: Mapping[Field, Scalar]) -> UnitPart:
        def specification(field: Field,
                          field_type: Type) -> FunctionSpecification:
            if field_type.package == BUILTINS_PACKAGE:
                type_identifier = ID(field_type.name)
            else:
                type_identifier = self.prefix * field_type.identifier

            return FunctionSpecification(f"Get_{field.name}", type_identifier,
                                         [Parameter(["Ctx"], "Context")])

        def result(field: Field) -> Expr:
            return Call(
                "To_Actual",
                [
                    Selected(
                        Indexed(Variable("Ctx.Cursors"),
                                Variable(field.affixed_name)), "Value")
                ],
            )

        return UnitPart(
            [
                # https://github.com/Componolit/Workarounds/issues/31
                Pragma(
                    "Warnings",
                    [Variable("Off"),
                     String("precondition is always False")]),
                *[
                    SubprogramDeclaration(
                        specification(f, t),
                        [
                            Precondition(
                                Call(
                                    self.prefix * message.identifier * "Valid",
                                    [
                                        Variable("Ctx"),
                                        Variable(
                                            self.prefix * message.identifier *
                                            f.affixed_name),
                                    ],
                                ), )
                        ],
                    ) for f, t in scalar_fields.items()
                ],
                Pragma(
                    "Warnings",
                    [Variable("On"),
                     String("precondition is always False")]),
            ],
            private=[
                ExpressionFunctionDeclaration(specification(f, t), result(f))
                for f, t in scalar_fields.items()
            ],
        )
예제 #15
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)
         ]
     )
예제 #16
0
def initialize_conditions(message: model.Message) -> Sequence[Expr]:
    return [
        *[
            Equal(
                Variable("Ctx" * ID(p.name)),
                Variable(p.name),
            )
            for p, t in message.parameter_types.items()
        ],
        Call("Initialized", [Variable("Ctx")]),
    ]
예제 #17
0
def byte_aligned_field(prefix: str, message: model.Message, field: model.Field) -> Expr:
    return Equal(
        Rem(
            Call(
                prefix * message.identifier * "Field_First",
                [
                    Variable("Ctx"),
                    Variable(prefix * message.identifier * field.affixed_name),
                ],
            ),
            Size(const.TYPES_BYTE),
        ),
        Number(1),
    )
예제 #18
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)
         ]
     )
예제 #19
0
    def create_incomplete_message_function() -> UnitPart:
        specification = FunctionSpecification("Incomplete_Message", "Boolean",
                                              [Parameter(["Ctx"], "Context")])

        return UnitPart(
            [
                # https://github.com/Componolit/Workarounds/issues/47
                Pragma(
                    "Warnings",
                    [
                        Variable("Off"),
                        String(
                            "postcondition does not mention function result")
                    ],
                ),
                SubprogramDeclaration(specification, [Postcondition(TRUE)]),
                Pragma(
                    "Warnings",
                    [
                        Variable("On"),
                        String(
                            "postcondition does not mention function result")
                    ],
                ),
            ],
            private=[
                ExpressionFunctionDeclaration(
                    specification,
                    ForSomeIn(
                        "F",
                        Variable("Field"),
                        Call(
                            "Incomplete",
                            [Variable("Ctx"), Variable("F")],
                        ),
                    ),
                )
            ],
        )
예제 #20
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 []
            ),
        ),
    )
예제 #21
0
 def _create_finalize_proc(self,
                           slots: Sequence[NumberedSlotInfo]) -> UnitPart:
     proc = ProcedureSpecification("Finalize",
                                   [InOutParameter(["S"], "Slots")])
     return UnitPart(
         [
             SubprogramDeclaration(
                 proc,
                 [Postcondition(Call("Uninitialized", [Variable("S")]))]),
         ],
         [
             SubprogramBody(
                 proc,
                 declarations=[],
                 statements=([
                     Assignment(
                         "S" * self._slot_name(slot.slot_id),
                         Variable("null"),
                     ) for slot in slots
                 ] if slots else [NullStatement()]),
                 aspects=[SparkMode(off=True)],
             )
         ],
     )
예제 #22
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
            ],
        )
예제 #23
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
            ],
        )
예제 #24
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],
                ),
            )
        ]
    )
예제 #25
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
            ],
        )
예제 #26
0
def sufficient_space_for_field_condition(
    message_id: ID, field_name: Name, size: Expr = None
) -> Expr:
    if size is None:
        size = Call(message_id * "Field_Size", [Variable("Ctx"), field_name])
    return GreaterEqual(Call(message_id * "Available_Space", [Variable("Ctx"), field_name]), size)
예제 #27
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)),
            ),
        ),
    ]
예제 #28
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),
                                                ),
                                            ),
                                        )
                                    ],
                                )
                            ],
                        )], )
                    ],
                )
            ],
        )
예제 #29
0
    def create_get_function(
        self,
        message: Message,
        scalar_fields: Mapping[Field, Scalar],
        composite_fields: Sequence[Field],
    ) -> UnitPart:
        if not scalar_fields:
            return UnitPart()

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

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

        return UnitPart(
            [],
            [
                SubprogramBody(
                    FunctionSpecification(
                        "Get",
                        const.TYPES_BASE_INT,
                        [
                            Parameter(["Ctx"], "Context"),
                            Parameter(["Fld"], "Field")
                        ],
                    ),
                    [
                        *common.field_bit_location_declarations(
                            Variable("Fld")),
                        ObjectDeclaration(
                            ["Buffer_First"],
                            const.TYPES_INDEX,
                            Call(const.TYPES_TO_INDEX, [Variable("First")]),
                            constant=True,
                        ),
                        ObjectDeclaration(
                            ["Buffer_Last"],
                            const.TYPES_INDEX,
                            Call(const.TYPES_TO_INDEX, [Variable("Last")]),
                            constant=True,
                        ),
                        ObjectDeclaration(
                            ["Offset"],
                            const.TYPES_OFFSET,
                            Call(
                                const.TYPES_OFFSET,
                                [
                                    Mod(
                                        Sub(
                                            Size(const.TYPES_BYTE),
                                            Mod(Variable("Last"),
                                                Size(const.TYPES_BYTE)),
                                        ),
                                        Size(const.TYPES_BYTE),
                                    )
                                ],
                            ),
                            constant=True,
                        ),
                        ObjectDeclaration(
                            ["Size"],
                            "Positive",
                            Case(
                                Variable("Fld"),
                                [
                                    *[(Variable(f.affixed_name),
                                       t.size.ada_expr())
                                      for f, t in scalar_fields.items()],
                                    *([(Variable("others"), Last("Positive"))]
                                      if composite_fields else []),
                                ],
                            ),
                            constant=True,
                        ),
                        ObjectDeclaration(
                            ["Byte_Order"],
                            const.TYPES_BYTE_ORDER,
                            If(
                                [(
                                    In(
                                        Variable("Fld"),
                                        ChoiceList(*[
                                            Variable(f.affixed_name)
                                            for f in big_endian_fields
                                        ]),
                                    ),
                                    Variable(const.TYPES_HIGH_ORDER_FIRST),
                                )],
                                Variable(const.TYPES_LOW_ORDER_FIRST),
                            ) if big_endian_fields and little_endian_fields
                            else Variable(const.TYPES_HIGH_ORDER_FIRST)
                            if big_endian_fields else Variable(
                                const.TYPES_LOW_ORDER_FIRST),
                            constant=True,
                        ),
                    ] if scalar_fields or comparison_to_aggregate else [],
                    [
                        ReturnStatement(
                            Call(
                                const.TYPES * "Extract",
                                [
                                    Variable("Ctx.Buffer"),
                                    Variable("Buffer_First"),
                                    Variable("Buffer_Last"),
                                    Variable("Offset"),
                                    Variable("Size"),
                                    Variable("Byte_Order"),
                                ],
                            ), ),
                    ],
                    [
                        Precondition(
                            AndThen(
                                Call(
                                    self.prefix * message.identifier *
                                    "Has_Buffer",
                                    [Variable("Ctx")],
                                ),
                                Call(
                                    self.prefix * message.identifier *
                                    "Valid_Next",
                                    [Variable("Ctx"),
                                     Variable("Fld")],
                                ),
                                Call(
                                    self.prefix * message.identifier *
                                    "Sufficient_Buffer_Length",
                                    [Variable("Ctx"),
                                     Variable("Fld")],
                                ),
                                *([
                                    Not(
                                        Call(
                                            self.prefix * message.identifier *
                                            "Composite_Field",
                                            [Variable("Fld")],
                                        ))
                                ] if composite_fields else []),
                            )),
                    ],
                ),
            ],
        )