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

        return UnitPart(
            [SubprogramDeclaration(specification)],
            [
                ExpressionFunctionDeclaration(
                    specification,
                    AndThen(
                        Call("Structural_Valid", [
                            Indexed(Variable("Ctx.Cursors"), Variable("Fld"))
                        ]),
                        Less(
                            Selected(
                                Indexed(Variable("Ctx.Cursors"),
                                        Variable("Fld")), "First"),
                            Add(
                                Selected(
                                    Indexed(Variable("Ctx.Cursors"),
                                            Variable("Fld")), "Last"),
                                Number(1),
                            ),
                        ),
                    ),
                )
            ],
        )
Esempio n. 2
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),
                )
            ],
        )
Esempio n. 3
0
    def create_invalid_function() -> UnitPart:
        specification = FunctionSpecification(
            "Invalid", "Boolean",
            [Parameter(["Ctx"], "Context"),
             Parameter(["Fld"], "Field")])

        return UnitPart(
            [SubprogramDeclaration(specification)],
            [
                ExpressionFunctionDeclaration(
                    specification,
                    Or(
                        Equal(
                            Selected(
                                Indexed(Variable("Ctx.Cursors"),
                                        Variable("Fld")), "State"),
                            Variable("S_Invalid"),
                        ),
                        Equal(
                            Selected(
                                Indexed(Variable("Ctx.Cursors"),
                                        Variable("Fld")), "State"),
                            Variable("S_Incomplete"),
                        ),
                    ),
                )
            ],
        )
Esempio n. 4
0
    def create_structural_valid_function() -> UnitPart:
        specification = FunctionSpecification(
            "Structural_Valid",
            "Boolean",
            [Parameter(["Ctx"], "Context"),
             Parameter(["Fld"], "Field")],
        )

        return UnitPart(
            [SubprogramDeclaration(specification)],
            [
                ExpressionFunctionDeclaration(
                    specification,
                    And(
                        Or(*[
                            Equal(
                                Selected(
                                    Indexed(Variable("Ctx.Cursors"),
                                            Variable("Fld")), "State"),
                                Variable(s),
                            ) for s in ("S_Valid", "S_Structural_Valid")
                        ])),
                )
            ],
        )
Esempio n. 5
0
def field_byte_location_declarations() -> Sequence[Declaration]:
    return [
        ExpressionFunctionDeclaration(
            FunctionSpecification("Buffer_First", const.TYPES_INDEX),
            Call(const.TYPES_BYTE_INDEX, [Variable("First")]),
        ),
        ExpressionFunctionDeclaration(
            FunctionSpecification("Buffer_Last", const.TYPES_INDEX),
            Call(const.TYPES_BYTE_INDEX, [Variable("Last")]),
        ),
        ExpressionFunctionDeclaration(
            FunctionSpecification("Offset", const.TYPES_OFFSET),
            Call(
                const.TYPES_OFFSET,
                [Mod(Sub(Number(8), Mod(Variable("Last"), Number(8))), Number(8))],
            ),
        ),
    ]
Esempio n. 6
0
        def specification(field: Field,
                          field_type: Type) -> FunctionSpecification:
            if field_type.package == BUILTINS_PACKAGE:
                type_name = ID(field_type.name)
            else:
                type_name = self.prefix * field_type.identifier

            return FunctionSpecification(f"Get_{field.name}", type_name,
                                         [Parameter(["Ctx"], "Context")])
Esempio n. 7
0
 def field_byte_location_declarations(self) -> Sequence[Declaration]:
     return [
         ExpressionFunctionDeclaration(
             FunctionSpecification("Buffer_First", self.types.index),
             Call(self.types.byte_index, [Name("First")]),
         ),
         ExpressionFunctionDeclaration(
             FunctionSpecification("Buffer_Last", self.types.index),
             Call(self.types.byte_index, [Name("Last")]),
         ),
         ExpressionFunctionDeclaration(
             FunctionSpecification("Offset", self.types.offset),
             Call(
                 self.types.offset,
                 [Mod(Sub(Number(8), Mod(Name("Last"), Number(8))), Number(8))],
             ),
         ),
     ]
Esempio n. 8
0
 def extract_function(self, type_name: str) -> Subprogram:
     return GenericFunctionInstantiation(
         "Extract",
         FunctionSpecification(
             f"{self.types.types}.Extract",
             type_name,
             [Parameter(["Buffer"], self.types.bytes), Parameter(["Offset"], self.types.offset)],
         ),
         [self.types.index, self.types.byte, self.types.bytes, self.types.offset, type_name],
     )
Esempio n. 9
0
    def create_valid_function() -> UnitPart:
        specification = FunctionSpecification(
            "Valid", "Boolean",
            [Parameter(["Ctx"], "Context"),
             Parameter(["Fld"], "Field")])

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification,
                    [
                        Postcondition(
                            If([(
                                Result("Valid"),
                                And(
                                    Call(
                                        "Structural_Valid",
                                        [Variable("Ctx"),
                                         Variable("Fld")],
                                    ),
                                    Call("Present",
                                         [Variable("Ctx"),
                                          Variable("Fld")]),
                                ),
                            )])),
                    ],
                )
            ],
            [
                ExpressionFunctionDeclaration(
                    specification,
                    AndThen(
                        Equal(
                            Selected(
                                Indexed(Variable("Ctx.Cursors"),
                                        Variable("Fld")), "State"),
                            Variable("S_Valid"),
                        ),
                        Less(
                            Selected(
                                Indexed(Variable("Ctx.Cursors"),
                                        Variable("Fld")), "First"),
                            Add(
                                Selected(
                                    Indexed(Variable("Ctx.Cursors"),
                                            Variable("Fld")), "Last"),
                                Number(1),
                            ),
                        ),
                    ),
                )
            ],
        )
Esempio n. 10
0
 def _create_init_pred(self, slots: Sequence[NumberedSlotInfo]) -> UnitPart:
     return UnitPart([
         ExpressionFunctionDeclaration(
             FunctionSpecification("Initialized", "Boolean",
                                   [Parameter(["S"], "Slots")]),
             And(*[
                 NotEqual(
                     Variable("S" * self._slot_name(slot.slot_id)),
                     Variable("null"),
                 ) for slot in slots
             ]),
         )
     ])
Esempio n. 11
0
 def extract_function(self, type_name: ID) -> Subprogram:
     return GenericFunctionInstantiation(
         "Extract",
         FunctionSpecification(
             const.TYPES * "Extract",
             type_name,
             [
                 Parameter(["Buffer"], const.TYPES_BYTES),
                 Parameter(["Offset"], const.TYPES_OFFSET),
             ],
         ),
         [common.prefixed_type_name(type_name, self.prefix)],
     )
Esempio n. 12
0
    def create_valid_message_function(self, message: Message) -> UnitPart:
        specification = FunctionSpecification(
            "Valid_Message", "Boolean", [Parameter(["Ctx"], "Context")]
        )

        return UnitPart(
            [SubprogramDeclaration(specification, [Precondition(VALID_CONTEXT)])],
            [
                ExpressionFunctionDeclaration(
                    specification,
                    valid_message_condition(message).simplified(self.common.substitution(message)),
                )
            ],
        )
Esempio n. 13
0
 def formal_parameters(
         field: Field) -> Sequence[FormalSubprogramDeclaration]:
     return [
         FormalSubprogramDeclaration(
             ProcedureSpecification(
                 f"Process_{field.name}",
                 [OutParameter([field.name], const.TYPES_BYTES)],
             )),
         FormalSubprogramDeclaration(
             FunctionSpecification(
                 "Valid_Length",
                 "Boolean",
                 [Parameter(["Length"], const.TYPES_LENGTH)],
             )),
     ]
Esempio n. 14
0
    def create_incomplete_function() -> UnitPart:
        specification = FunctionSpecification(
            "Incomplete", "Boolean", [Parameter(["Ctx"], "Context"), Parameter(["Fld"], "Field")]
        )

        return UnitPart(
            [SubprogramDeclaration(specification, [Precondition(VALID_CONTEXT)])],
            [
                ExpressionFunctionDeclaration(
                    specification,
                    Equal(
                        Selected(Indexed("Ctx.Cursors", Name("Fld")), "State"), Name("S_Incomplete")
                    ),
                )
            ],
        )
Esempio n. 15
0
    def create_incomplete_message_function(message: Message) -> UnitPart:
        specification = FunctionSpecification("Incomplete_Message", "Boolean",
                                              [Parameter(["Ctx"], "Context")])

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

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification,
                    [Precondition(Call("Has_Buffer", [Variable("Ctx")]))],
                )
            ],
            [
                ExpressionFunctionDeclaration(
                    specification,
                    valid_message_condition(message).substituted(
                        common.substitution(message)).simplified(),
                )
            ],
        )
Esempio n. 17
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")],
                        ),
                    ),
                )
            ],
        )
Esempio n. 18
0
 def _create_global_allocated_pred(
         self, slots: Sequence[NumberedSlotInfo]) -> UnitPart:
     return UnitPart([
         ExpressionFunctionDeclaration(
             FunctionSpecification("Global_Allocated", "Boolean",
                                   [Parameter(["S"], "Slots")]),
             And(
                 *[
                     Equal(
                         Variable("S" * self._slot_name(slot.slot_id)),
                         Variable("null"),
                     ) for slot in slots if slot.global_
                 ],
                 *[
                     NotEqual(
                         Variable("S" * self._slot_name(slot.slot_id)),
                         Variable("null"),
                     ) for slot in slots if not slot.global_
                 ],
             ),
         )
     ])
Esempio n. 19
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 []),
                            )),
                    ],
                ),
            ],
        )
Esempio n. 20
0
    def create_composite_setter_procedures(self, message: Message) -> UnitPart:
        def specification(field: Field) -> ProcedureSpecification:
            return ProcedureSpecification(f"Set_{field.name}", [InOutParameter(["Ctx"], "Context")])

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

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

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification(f),
                    [
                        Precondition(
                            AndThen(
                                *self.setter_preconditions(f),
                                *self.unbounded_composite_setter_preconditions(message, f),
                            )
                        ),
                        Postcondition(
                            And(
                                *self.composite_setter_postconditions(message, f, message.types[f]),
                            )
                        ),
                    ],
                    formal_parameters,
                )
                for f, t in message.types.items()
                if isinstance(t, Payload) and unbounded_setter_required(message, f)
            ]
            + [
                SubprogramDeclaration(
                    specification_bounded(f),
                    [
                        Precondition(
                            AndThen(
                                *self.setter_preconditions(f),
                                *self.bounded_composite_setter_preconditions(message, f),
                            )
                        ),
                        Postcondition(
                            And(
                                *self.composite_setter_postconditions(message, f, message.types[f]),
                            )
                        ),
                    ],
                    formal_parameters,
                )
                for f, t in message.types.items()
                if isinstance(t, Payload) and bounded_setter_required(message, f)
            ],
            [
                SubprogramBody(
                    specification(f),
                    [
                        *self.common.field_bit_location_declarations(Name(f.affixed_name)),
                        ExpressionFunctionDeclaration(
                            FunctionSpecification("Buffer_First", self.types.index),
                            Call(self.types.byte_index, [Name("First")]),
                        ),
                        ExpressionFunctionDeclaration(
                            FunctionSpecification("Buffer_Last", self.types.index),
                            Call(self.types.byte_index, [Name("Last")]),
                        ),
                    ],
                    [
                        CallStatement(f"Initialize_{f.name}", [Name("Ctx")]),
                        CallStatement(
                            "Process_Payload",
                            [
                                Slice(
                                    Selected(Selected("Ctx", "Buffer"), "all"),
                                    Name("Buffer_First"),
                                    Name("Buffer_Last"),
                                ),
                            ],
                        ),
                    ],
                )
                for f, t in message.types.items()
                if isinstance(t, Payload) and unbounded_setter_required(message, f)
            ]
            + [
                SubprogramBody(
                    specification_bounded(f),
                    [
                        ObjectDeclaration(
                            ["First"],
                            self.types.bit_index,
                            Call("Field_First", [Name("Ctx"), Name(f.affixed_name)]),
                            True,
                        ),
                        ObjectDeclaration(
                            ["Last"],
                            self.types.bit_index,
                            Add(Name("First"), Name("Length"), -Number(1)),
                            True,
                        ),
                        ExpressionFunctionDeclaration(
                            FunctionSpecification("Buffer_First", self.types.index),
                            Call(self.types.byte_index, [Name("First")]),
                        ),
                        ExpressionFunctionDeclaration(
                            FunctionSpecification("Buffer_Last", self.types.index),
                            Call(self.types.byte_index, [Name("Last")]),
                        ),
                    ],
                    [
                        CallStatement(
                            f"Initialize_Bounded_{f.name}", [Name("Ctx"), Name("Length")]
                        ),
                        CallStatement(
                            "Process_Payload",
                            [
                                Slice(
                                    Selected(Selected("Ctx", "Buffer"), "all"),
                                    Name("Buffer_First"),
                                    Name("Buffer_Last"),
                                ),
                            ],
                        ),
                    ],
                )
                for f, t in message.types.items()
                if isinstance(t, Payload) and bounded_setter_required(message, f)
            ],
        )
Esempio n. 21
0
 def specification(field: Field) -> FunctionSpecification:
     return FunctionSpecification(
         name(field),
         const.TYPES_BYTES,
         [Parameter(["Ctx"], "Context")],
     )
Esempio n. 22
0
    def create_internal_functions(
        self,
        message: Message,
        scalar_fields: Mapping[Field, Type],
        composite_fields: Sequence[Field],
    ) -> UnitPart:
        def result(field: Field, message: Message) -> NamedAggregate:
            aggregate: List[Tuple[str, Expr]] = [
                ("Fld", Variable(field.affixed_name))
            ]
            if field in message.fields and isinstance(message.types[field],
                                                      Scalar):
                aggregate.append((
                    f"{field.name}_Value",
                    Call(
                        "Extract",
                        [
                            Slice(
                                Variable("Ctx.Buffer.all"),
                                Variable("Buffer_First"),
                                Variable("Buffer_Last"),
                            ),
                            Variable("Offset"),
                        ],
                    ),
                ))
            return NamedAggregate(*aggregate)

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

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

        def formal_parameters(
                field: Field) -> Sequence[FormalSubprogramDeclaration]:
            return [
                FormalSubprogramDeclaration(
                    ProcedureSpecification(
                        f"Process_{field.name}",
                        [OutParameter([field.name], const.TYPES_BYTES)],
                    )),
                FormalSubprogramDeclaration(
                    FunctionSpecification(
                        "Valid_Length",
                        "Boolean",
                        [Parameter(["Length"], const.TYPES_LENGTH)],
                    )),
            ]

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification(f),
                    [
                        Precondition(
                            AndThen(
                                *self.setter_preconditions(f),
                                *self.unbounded_composite_setter_preconditions(
                                    message, f),
                                Call(
                                    "Valid_Length",
                                    [
                                        Call(
                                            const.TYPES_LENGTH,
                                            [
                                                Div(
                                                    Call(
                                                        "Field_Length",
                                                        [
                                                            Variable("Ctx"),
                                                            Variable(
                                                                f.affixed_name)
                                                        ],
                                                    ),
                                                    Size(const.TYPES_BYTE),
                                                ),
                                            ],
                                        ),
                                    ],
                                ),
                            )),
                        Postcondition(
                            And(
                                *self.composite_setter_postconditions(
                                    message, f), )),
                    ],
                    formal_parameters(f),
                ) for f, t in message.types.items() if isinstance(t, Opaque)
                and unbounded_setter_required(message, f)
            ] + [
                SubprogramDeclaration(
                    specification_bounded(f),
                    [
                        Precondition(
                            AndThen(
                                *self.setter_preconditions(f),
                                *self.bounded_composite_setter_preconditions(
                                    message, f),
                                Call(
                                    "Valid_Length",
                                    [
                                        Call(
                                            const.TYPES_LENGTH,
                                            [
                                                Div(Variable("Length"),
                                                    Size(const.TYPES_BYTE))
                                            ],
                                        )
                                    ],
                                ),
                            )),
                        Postcondition(
                            And(
                                *self.composite_setter_postconditions(
                                    message, f), )),
                    ],
                    formal_parameters(f),
                ) for f, t in message.types.items() if isinstance(t, Opaque)
                and bounded_setter_required(message, f)
            ],
            [
                SubprogramBody(
                    specification(f),
                    [
                        *common.field_bit_location_declarations(
                            Variable(f.affixed_name)),
                        ExpressionFunctionDeclaration(
                            FunctionSpecification("Buffer_First",
                                                  const.TYPES_INDEX),
                            Call(const.TYPES_BYTE_INDEX, [Variable("First")]),
                        ),
                        ExpressionFunctionDeclaration(
                            FunctionSpecification("Buffer_Last",
                                                  const.TYPES_INDEX),
                            Call(const.TYPES_BYTE_INDEX, [Variable("Last")]),
                        ),
                    ],
                    [
                        CallStatement(f"Initialize_{f.name}",
                                      [Variable("Ctx")]),
                        CallStatement(
                            f"Process_{f.name}",
                            [
                                Slice(
                                    Selected(Variable("Ctx.Buffer"), "all"),
                                    Variable("Buffer_First"),
                                    Variable("Buffer_Last"),
                                ),
                            ],
                        ),
                    ],
                ) for f, t in message.types.items() if isinstance(t, Opaque)
                and unbounded_setter_required(message, f)
            ] + [
                SubprogramBody(
                    specification_bounded(f),
                    [
                        ObjectDeclaration(
                            ["First"],
                            const.TYPES_BIT_INDEX,
                            Call("Field_First",
                                 [Variable("Ctx"),
                                  Variable(f.affixed_name)]),
                            True,
                        ),
                        ObjectDeclaration(
                            ["Last"],
                            const.TYPES_BIT_INDEX,
                            Add(Variable("First"), Variable("Length"),
                                -Number(1)),
                            True,
                        ),
                        ExpressionFunctionDeclaration(
                            FunctionSpecification("Buffer_First",
                                                  const.TYPES_INDEX),
                            Call(const.TYPES_BYTE_INDEX, [Variable("First")]),
                        ),
                        ExpressionFunctionDeclaration(
                            FunctionSpecification("Buffer_Last",
                                                  const.TYPES_INDEX),
                            Call(const.TYPES_BYTE_INDEX, [Variable("Last")]),
                        ),
                    ],
                    [
                        CallStatement(f"Initialize_Bounded_{f.name}",
                                      [Variable("Ctx"),
                                       Variable("Length")]),
                        CallStatement(
                            f"Process_{f.name}",
                            [
                                Slice(
                                    Selected(Variable("Ctx.Buffer"), "all"),
                                    Variable("Buffer_First"),
                                    Variable("Buffer_Last"),
                                ),
                            ],
                        ),
                    ],
                ) for f, t in message.types.items() if isinstance(t, Opaque)
                and bounded_setter_required(message, f)
            ],
        )
Esempio n. 24
0
    def create_internal_functions(
        self, message: Message, composite_fields: Sequence[Field]
    ) -> UnitPart:
        def result(field: Field, message: Message) -> NamedAggregate:
            aggregate: List[Tuple[str, Expr]] = [("Fld", Name(field.affixed_name))]
            if field in message.fields and isinstance(message.types[field], Scalar):
                aggregate.append(
                    (
                        f"{field.name}_Value",
                        Call(
                            "Extract",
                            [
                                Slice("Ctx.Buffer.all", Name("Buffer_First"), Name("Buffer_Last")),
                                Name("Offset"),
                            ],
                        ),
                    )
                )
            return NamedAggregate(*aggregate)

        return UnitPart(
            [],
            [
                ExpressionFunctionDeclaration(
                    FunctionSpecification(
                        "Sufficient_Buffer_Length",
                        "Boolean",
                        [Parameter(["Ctx"], "Context"), Parameter(["Fld"], "Field")],
                    ),
                    And(
                        NotEqual(Name("Ctx.Buffer"), NULL),
                        LessEqual(Name("Ctx.First"), Div(Last(self.types.bit_index), Number(2))),
                        LessEqual(
                            Call("Field_First", [Name("Ctx"), Name("Fld")]),
                            Div(Last(self.types.bit_index), Number(2)),
                        ),
                        GreaterEqual(Call("Field_Length", [Name("Ctx"), Name("Fld")]), Number(0)),
                        LessEqual(
                            Call("Field_Length", [Name("Ctx"), Name("Fld")]),
                            Div(Last(self.types.bit_length), Number(2)),
                        ),
                        LessEqual(
                            Add(
                                Call("Field_First", [Name("Ctx"), Name("Fld")]),
                                Call("Field_Length", [Name("Ctx"), Name("Fld")]),
                            ),
                            Div(Last(self.types.bit_length), Number(2)),
                        ),
                        LessEqual(
                            Name("Ctx.First"), Call("Field_First", [Name("Ctx"), Name("Fld")])
                        ),
                        GreaterEqual(
                            Name("Ctx.Last"), Call("Field_Last", [Name("Ctx"), Name("Fld")])
                        ),
                    ),
                    [
                        Precondition(
                            And(
                                Call("Has_Buffer", [Name("Ctx")]),
                                Call("Valid_Next", [Name("Ctx"), Name("Fld")]),
                            )
                        )
                    ],
                ),
                ExpressionFunctionDeclaration(
                    FunctionSpecification(
                        "Composite_Field", "Boolean", [Parameter(["Fld"], "Field")]
                    ),
                    Case(
                        Name("Fld"),
                        [
                            (Name(f.affixed_name), TRUE if f in composite_fields else FALSE)
                            for f in message.fields
                        ],
                    ),
                ),
                SubprogramBody(
                    FunctionSpecification(
                        "Get_Field_Value",
                        "Field_Dependent_Value",
                        [Parameter(["Ctx"], "Context"), Parameter(["Fld"], "Field")],
                    ),
                    [
                        *self.common.field_bit_location_declarations(Name("Fld")),
                        *self.common.field_byte_location_declarations(),
                    ],
                    [
                        ReturnStatement(
                            Case(
                                Name("Fld"),
                                [
                                    (Name(f.affixed_name), result(f, message))
                                    for f in message.fields
                                ],
                            )
                        )
                    ],
                    [
                        Precondition(
                            AndThen(
                                Call("Has_Buffer", [Name("Ctx")]),
                                Call("Valid_Next", [Name("Ctx"), Name("Fld")]),
                                Call("Sufficient_Buffer_Length", [Name("Ctx"), Name("Fld")]),
                            )
                        ),
                        Postcondition(
                            Equal(Selected(Result("Get_Field_Value"), "Fld"), Name("Fld"))
                        ),
                    ],
                ),
            ],
        )
Esempio n. 25
0
 def specification(field: Field, field_type: Type) -> FunctionSpecification:
     return FunctionSpecification(
         f"Get_{field.name}", field_type.full_name, [Parameter(["Ctx"], "Context")]
     )