Exemplo n.º 1
0
def enumeration_functions(enum: Enumeration) -> List[Subprogram]:
    common_precondition = And(
        Less(Value('Offset'), Number(8)),
        Equal(
            Length('Buffer'),
            Add(
                Div(Add(Size(enum.base_name), Value('Offset'), Number(-1)),
                    Number(8)), Number(1))))

    control_expression = LogCall(
        f'Convert_To_{enum.base_name} (Buffer, Offset)')

    validation_expression: Expr
    if enum.always_valid:
        validation_expression = Value('True')
    else:
        validation_cases: List[Tuple[Expr, Expr]] = []
        validation_cases.extend(
            (value, Value('True')) for value in enum.literals.values())
        validation_cases.append((Value('others'), Value('False')))

        validation_expression = CaseExpression(control_expression,
                                               validation_cases)
    validation_function = ExpressionFunction(
        f'Valid_{enum.name}', 'Boolean', [('Buffer', 'Types.Bytes'),
                                          ('Offset', 'Natural')],
        validation_expression, [Precondition(common_precondition)])

    function_name = f'Convert_To_{enum.name}'
    parameters = [('Buffer', 'Types.Bytes'), ('Offset', 'Natural')]
    precondition = Precondition(
        And(common_precondition,
            LogCall(f'Valid_{enum.name} (Buffer, Offset)')))
    conversion_cases: List[Tuple[Expr, Expr]] = []
    conversion_function: Subprogram

    if enum.always_valid:
        conversion_cases.extend((value, Aggregate(Value('True'), Value(key)))
                                for key, value in enum.literals.items())
        conversion_cases.append(
            (Value('others'), Aggregate(Value('False'), Value('Raw'))))

        conversion_function = Function(
            function_name, enum.name, parameters,
            [Declaration('Raw', enum.base_name, control_expression)],
            [ReturnStatement(CaseExpression(Value('Raw'), conversion_cases))],
            [precondition])
    else:
        conversion_cases.extend(
            (value, Value(key)) for key, value in enum.literals.items())
        conversion_cases.append(
            (Value('others'), LogCall(f'Unreachable_{enum.name}')))

        conversion_function = ExpressionFunction(
            function_name, enum.name, parameters,
            CaseExpression(control_expression, conversion_cases),
            [precondition])

    return [validation_function, conversion_function]
Exemplo n.º 2
0
    def create_scalar_accessor_functions(scalar_fields: Mapping[Field, Scalar]) -> UnitPart:
        def specification(field: Field, field_type: Type) -> FunctionSpecification:
            return FunctionSpecification(
                f"Get_{field.name}", field_type.full_name, [Parameter(["Ctx"], "Context")]
            )

        def result(field: Field, field_type: Type) -> Expr:
            value = Selected(
                Indexed("Ctx.Cursors", Name(field.affixed_name)), f"Value.{field.name}_Value"
            )
            if isinstance(field_type, Enumeration):
                return Call("Convert", [value])
            return value

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification(f, t),
                    [
                        Precondition(
                            And(VALID_CONTEXT, Call("Valid", [Name("Ctx"), Name(f.affixed_name)]))
                        )
                    ],
                )
                for f, t in scalar_fields.items()
            ],
            [
                ExpressionFunctionDeclaration(specification(f, t), result(f, t))
                for f, t in scalar_fields.items()
            ],
        )
Exemplo n.º 3
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),
                )
            ],
        )
Exemplo n.º 4
0
def contains_function(name: str, pdu: str, field: str, sdu: str,
                      condition: LogExpr) -> Subprogram:

    success_statements: List[Statement] = [ReturnStatement(TRUE)]
    aspects: List[Aspect] = [
        Precondition(
            And(LogCall(f'{pdu}.Is_Contained (Buffer)'),
                LogCall(f'{pdu}.Is_Valid (Buffer)')))
    ]
    if sdu != 'null':
        success_statements.insert(
            0,
            PragmaStatement('Assume', [(
                f'{sdu}.Is_Contained (Buffer ({pdu}.Get_{field}_First (Buffer)'
                f' .. {pdu}.Get_{field}_Last (Buffer)))')]))
        aspects.append(
            Postcondition(
                IfExpression([
                    (LogCall(f'{name}\'Result'),
                     LogCall((f'{sdu}.Is_Contained (Buffer ('
                              f'{pdu}.Get_{field}_First (Buffer)'
                              f' .. {pdu}.Get_{field}_Last (Buffer)))')))
                ])))

    return Function(name, 'Boolean', [('Buffer', 'Types.Bytes')], [], [
        IfStatement([(condition, success_statements)]),
        ReturnStatement(FALSE)
    ], aspects)
Exemplo n.º 5
0
    def create_structural_valid_function() -> UnitPart:
        specification = FunctionSpecification(
            "Structural_Valid",
            "Boolean",
            [Parameter(["Ctx"], "Context"), Parameter(["Fld"], "Field")],
        )

        return UnitPart(
            [SubprogramDeclaration(specification, [Precondition(VALID_CONTEXT)])],
            [
                ExpressionFunctionDeclaration(
                    specification,
                    And(
                        Or(
                            *[
                                Equal(
                                    Selected(Indexed("Ctx.Cursors", Name("Fld")), "State"), Name(s)
                                )
                                for s in ("S_Valid", "S_Structural_Valid")
                            ]
                        )
                    ),
                )
            ],
        )
Exemplo n.º 6
0
    def create_composite_accessor_procedures(self, composite_fields: Sequence[Field]) -> UnitPart:
        def specification(field: Field) -> ProcedureSpecification:
            return ProcedureSpecification(f"Get_{field.name}", [Parameter(["Ctx"], "Context")])

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification(f),
                    [
                        Precondition(
                            And(
                                VALID_CONTEXT,
                                Call("Has_Buffer", [Name("Ctx")]),
                                Call("Present", [Name("Ctx"), Name(f.affixed_name)]),
                            )
                        )
                    ],
                    [
                        FormalSubprogramDeclaration(
                            ProcedureSpecification(
                                f"Process_{f.name}", [Parameter([f.name], self.types.bytes)]
                            )
                        )
                    ],
                )
                for f in composite_fields
            ],
            [
                SubprogramBody(
                    specification(f),
                    [
                        ObjectDeclaration(
                            ["First"],
                            self.types.index,
                            Call(
                                self.types.byte_index,
                                [Selected(Indexed("Ctx.Cursors", Name(f.affixed_name)), "First")],
                            ),
                            True,
                        ),
                        ObjectDeclaration(
                            ["Last"],
                            self.types.index,
                            Call(
                                self.types.byte_index,
                                [Selected(Indexed("Ctx.Cursors", Name(f.affixed_name)), "Last")],
                            ),
                            True,
                        ),
                    ],
                    [
                        CallStatement(
                            f"Process_{f.name}",
                            [Slice("Ctx.Buffer.all", Name("First"), Name("Last"))],
                        )
                    ],
                )
                for f in composite_fields
            ],
        )
Exemplo n.º 7
0
def variant_accessor_functions(field: Field, variant_id: str,
                               variant: Variant) -> List[Subprogram]:

    first_byte, last_byte, offset = field_location(field.name, variant_id,
                                                   variant)

    name = f'Get_{field.name}_{variant_id}'
    precondition = Precondition(
        And(COMMON_PRECONDITION,
            LogCall(f'Valid_{field.name}_{variant_id} (Buffer)')))

    functions: List[Subprogram] = []
    if isinstance(field.type, Array):
        functions.append(
            ExpressionFunction(f'{name}_First', 'Types.Index_Type',
                               [('Buffer', 'Types.Bytes')], first_byte,
                               [precondition]))
        functions.append(
            ExpressionFunction(f'{name}_Last', 'Types.Index_Type',
                               [('Buffer', 'Types.Bytes')], last_byte,
                               [precondition]))
    else:
        functions.append(
            ExpressionFunction(
                name, field.type.name, [('Buffer', 'Types.Bytes')],
                Convert(
                    field.type.name if field.type.constraints == TRUE else
                    field.type.base_name, 'Buffer', first_byte, last_byte,
                    offset), [precondition]))
    return functions
Exemplo n.º 8
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()
            ],
        )
Exemplo n.º 9
0
def message_validation_function(variants: List[Variant]) -> Subprogram:
    expr: LogExpr = FALSE

    for variant in variants:
        condition = variant_condition(variant)
        expr = condition if expr == FALSE else Or(expr, condition)

    return ExpressionFunction('Is_Valid', 'Boolean',
                              [('Buffer', 'Types.Bytes')], expr,
                              [Precondition(COMMON_PRECONDITION)])
Exemplo n.º 10
0
def field_validation_function(field: Field) -> Subprogram:
    variants: List[LogExpr] = list(valid_variants(field))

    expr = variants.pop()
    for e in variants:
        if e is not TRUE:
            expr = Or(expr, e)

    return ExpressionFunction(f'Valid_{field.name}', 'Boolean',
                              [('Buffer', 'Types.Bytes')], expr,
                              [Precondition(COMMON_PRECONDITION)])
Exemplo n.º 11
0
def field_accessor_functions(field: Field,
                             package_name: str) -> List[Subprogram]:
    precondition = Precondition(
        And(COMMON_PRECONDITION, LogCall(f'Valid_{field.name} (Buffer)')))

    functions: List[Subprogram] = []
    if isinstance(field.type, Array):
        for attribute in ['First', 'Last']:
            functions.append(
                ExpressionFunction(
                    f'Get_{field.name}_{attribute}', 'Types.Index_Type',
                    [('Buffer', 'Types.Bytes')],
                    IfExpression([(
                        LogCall(f'Valid_{field.name}_{variant_id} (Buffer)'),
                        LogCall(
                            f'Get_{field.name}_{variant_id}_{attribute} (Buffer)'
                        )) for variant_id in field.variants],
                                 'Unreachable_Types_Index_Type'),
                    [precondition]))

        body: List[Statement] = [
            Assignment('First', MathCall(f'Get_{field.name}_First (Buffer)')),
            Assignment('Last', MathCall(f'Get_{field.name}_Last (Buffer)'))
        ]
        postcondition = Postcondition(
            And(
                Equal(Value('First'),
                      MathCall(f'Get_{field.name}_First (Buffer)')),
                Equal(Value('Last'),
                      MathCall(f'Get_{field.name}_Last (Buffer)'))))
        if 'Payload' not in field.type.name:
            predicate = f'{package_name}.{field.type.name}.Is_Contained (Buffer (First .. Last))'
            body.append(PragmaStatement('Assume', [predicate]))
            postcondition.expr = And(postcondition.expr, LogCall(predicate))

        functions.append(
            Procedure(f'Get_{field.name}', [('Buffer', 'Types.Bytes'),
                                            ('First', 'out Types.Index_Type'),
                                            ('Last', 'out Types.Index_Type')],
                      [], body, [precondition, postcondition]))

    else:
        functions.append(
            ExpressionFunction(
                f'Get_{field.name}', field.type.name,
                [('Buffer', 'Types.Bytes')],
                IfExpression(
                    [(LogCall(f'Valid_{field.name}_{variant_id} (Buffer)'),
                      MathCall(f'Get_{field.name}_{variant_id} (Buffer)'))
                     for variant_id in field.variants],
                    f'Unreachable_{field.type.name}'), [precondition]))

    return functions
Exemplo 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)),
                )
            ],
        )
Exemplo n.º 13
0
def message_length_function(variants: List[Variant]) -> Subprogram:
    condition_expressions: List[Tuple[LogExpr, Expr]] = []

    for variant in variants:
        condition = variant_condition(variant)
        length = Add(
            Last(variant.previous[-1][0]), -First(variant.previous[0][0]),
            Number(1)).simplified(variant.facts).simplified(
                value_to_call_facts(variant.previous)).to_bytes().simplified()
        condition_expressions.append((condition, length))

    return ExpressionFunction(
        'Message_Length', 'Types.Length_Type', [('Buffer', 'Types.Bytes')],
        IfExpression(condition_expressions, 'Unreachable_Types_Length_Type'),
        [Precondition(And(COMMON_PRECONDITION, LogCall('Is_Valid (Buffer)')))])
Exemplo n.º 14
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")]),
                            ],
                        )
                    ],
                )
            ],
        )
Exemplo n.º 15
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")
                    ),
                )
            ],
        )
Exemplo 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(),
                )
            ],
        )
Exemplo n.º 17
0
    def create_incomplete_message_function(message: Message) -> UnitPart:
        specification = FunctionSpecification(
            "Incomplete_Message", "Boolean", [Parameter(["Ctx"], "Context")]
        )

        return UnitPart(
            [SubprogramDeclaration(specification, [Precondition(VALID_CONTEXT)])],
            [
                ExpressionFunctionDeclaration(
                    specification,
                    Or(
                        *[
                            Call("Incomplete", [Name("Ctx"), Name(f.affixed_name)])
                            for f in message.fields
                        ]
                    ),
                )
            ],
        )
Exemplo n.º 18
0
    def create_valid_function() -> UnitPart:
        specification = FunctionSpecification(
            "Valid", "Boolean", [Parameter(["Ctx"], "Context"), Parameter(["Fld"], "Field")]
        )

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification,
                    [
                        Precondition(VALID_CONTEXT),
                        Postcondition(
                            If(
                                [
                                    (
                                        Result("Valid"),
                                        And(
                                            Call("Structural_Valid", [Name("Ctx"), Name("Fld")]),
                                            Call("Present", [Name("Ctx"), Name("Fld")]),
                                        ),
                                    )
                                ]
                            )
                        ),
                    ],
                )
            ],
            [
                ExpressionFunctionDeclaration(
                    specification,
                    AndThen(
                        Equal(
                            Selected(Indexed("Ctx.Cursors", Name("Fld")), "State"), Name("S_Valid")
                        ),
                        Less(
                            Selected(Indexed("Ctx.Cursors", Name("Fld")), "First"),
                            Add(Selected(Indexed("Ctx.Cursors", Name("Fld")), "Last"), Number(1)),
                        ),
                    ),
                )
            ],
        )
Exemplo n.º 19
0
    def create_scalar_accessor_functions(
            self, scalar_fields: Mapping[Field, Scalar]) -> UnitPart:
        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")])

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

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification(f, t),
                    [
                        Precondition(
                            Call("Valid",
                                 [Variable("Ctx"),
                                  Variable(f.affixed_name)]), )
                    ],
                ) for f, t in scalar_fields.items()
            ],
            [
                ExpressionFunctionDeclaration(specification(f, t), result(f))
                for f, t in scalar_fields.items()
            ],
        )
Exemplo n.º 20
0
def variant_validation_function(field: Field, variant_id: str,
                                variant: Variant) -> Subprogram:

    type_constraints: LogExpr = TRUE

    if field.type.constraints != TRUE or isinstance(field.type, Enumeration):
        first_byte, last_byte, offset = field_location(field.name, variant_id,
                                                       variant)

        if field.type.constraints != TRUE:
            convert = Convert(field.type.base_name, 'Buffer', first_byte,
                              last_byte, offset)
            type_constraints = field.type.constraints.simplified(
                {Value(field.type.name): convert})

        if isinstance(field.type, Enumeration):
            type_constraints = And(
                type_constraints,
                LogCall((f'Valid_{field.type.name} (Buffer ({first_byte}'
                         f' .. {last_byte}), {offset})')))

    value_to_call = value_to_call_facts([(field.name, variant_id)] +
                                        variant.previous)

    return ExpressionFunction(
        f'Valid_{field.name}_{variant_id}', 'Boolean',
        [('Buffer', 'Types.Bytes')],
        And(
            LogCall(
                f'Valid_{variant.previous[-1][0]}_{variant.previous[-1][1]} (Buffer)'
            ) if variant.previous else TRUE,
            And(
                And(
                    buffer_constraints(variant.facts[Last(
                        field.name)].to_bytes()).simplified(value_to_call),
                    variant.condition.simplified(
                        variant.facts).simplified(value_to_call)),
                type_constraints)).simplified(),
        [Precondition(COMMON_PRECONDITION)])
Exemplo n.º 21
0
    def create_verify_message_procedure(
        message: Message, context_invariant: Sequence[Expr]
    ) -> UnitPart:
        specification = ProcedureSpecification(
            "Verify_Message", [InOutParameter(["Ctx"], "Context")]
        )

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification,
                    [
                        Precondition(VALID_CONTEXT),
                        Postcondition(
                            And(
                                VALID_CONTEXT,
                                Equal(
                                    Call("Has_Buffer", [Name("Ctx")]),
                                    Old(Call("Has_Buffer", [Name("Ctx")])),
                                ),
                                *context_invariant,
                            )
                        ),
                    ],
                )
            ],
            [
                SubprogramBody(
                    specification,
                    [],
                    [
                        CallStatement("Verify", [Name("Ctx"), Name(f.affixed_name)])
                        for f in message.fields
                    ],
                )
            ],
        )
Exemplo n.º 22
0
def unreachable_function(type_name: str, base_name: str = None) -> Subprogram:
    return ExpressionFunction(
        f'Unreachable_{type_name}'.replace('.', '_'), type_name, [],
        First(type_name) if not base_name else Aggregate(
            Value('False'), First(base_name)), [Precondition(FALSE)])
Exemplo n.º 23
0
 def create_internal_functions(
         self, message: Message,
         scalar_fields: Mapping[Field, Scalar]) -> UnitPart:
     return UnitPart(
         [],
         [
             SubprogramBody(
                 ProcedureSpecification(
                     "Set_Field_Value",
                     [
                         InOutParameter(["Ctx"], "Context"),
                         Parameter(["Val"], "Field_Dependent_Value"),
                         OutParameter(["Fst", "Lst"],
                                      const.TYPES_BIT_INDEX),
                     ],
                 ),
                 [
                     *common.field_bit_location_declarations(
                         Variable("Val.Fld")),
                     *common.field_byte_location_declarations(),
                     *unique(
                         self.insert_function(common.full_base_type_name(t))
                         for t in message.types.values()
                         if isinstance(t, Scalar)),
                 ],
                 [
                     Assignment("Fst", Variable("First")),
                     Assignment("Lst", Variable("Last")),
                     CaseStatement(
                         Variable("Val.Fld"),
                         [(
                             Variable(f.affixed_name),
                             [
                                 CallStatement(
                                     "Insert",
                                     [
                                         Variable(f"Val.{f.name}_Value"),
                                         Slice(
                                             Variable("Ctx.Buffer.all"),
                                             Variable("Buffer_First"),
                                             Variable("Buffer_Last"),
                                         ),
                                         Variable("Offset"),
                                     ],
                                 )
                                 if f in scalar_fields else NullStatement()
                             ],
                         ) for f in message.all_fields],
                     ),
                 ],
                 [
                     Precondition(
                         AndThen(
                             Not(Constrained("Ctx")),
                             Call("Has_Buffer", [Variable("Ctx")]),
                             In(Variable("Val.Fld"), Range("Field")),
                             Call("Valid_Next",
                                  [Variable("Ctx"),
                                   Variable("Val.Fld")]),
                             common.sufficient_space_for_field_condition(
                                 Variable("Val.Fld")),
                             ForAllIn(
                                 "F",
                                 Range("Field"),
                                 If([(
                                     Call(
                                         "Structural_Valid",
                                         [
                                             Indexed(
                                                 Variable("Ctx.Cursors"),
                                                 Variable("F"),
                                             )
                                         ],
                                     ),
                                     LessEqual(
                                         Selected(
                                             Indexed(
                                                 Variable("Ctx.Cursors"),
                                                 Variable("F"),
                                             ),
                                             "Last",
                                         ),
                                         Call(
                                             "Field_Last",
                                             [
                                                 Variable("Ctx"),
                                                 Variable("Val.Fld")
                                             ],
                                         ),
                                     ),
                                 )]),
                             ),
                         )),
                     Postcondition(
                         And(
                             Call("Has_Buffer", [Variable("Ctx")]),
                             Equal(
                                 Variable("Fst"),
                                 Call(
                                     "Field_First",
                                     [Variable("Ctx"),
                                      Variable("Val.Fld")]),
                             ),
                             Equal(
                                 Variable("Lst"),
                                 Call(
                                     "Field_Last",
                                     [Variable("Ctx"),
                                      Variable("Val.Fld")]),
                             ),
                             GreaterEqual(Variable("Fst"),
                                          Variable("Ctx.First")),
                             LessEqual(Variable("Fst"),
                                       Add(Variable("Lst"), Number(1))),
                             LessEqual(
                                 Call(const.TYPES_BYTE_INDEX,
                                      [Variable("Lst")]),
                                 Variable("Ctx.Buffer_Last"),
                             ),
                             ForAllIn(
                                 "F",
                                 Range("Field"),
                                 If([(
                                     Call(
                                         "Structural_Valid",
                                         [
                                             Indexed(
                                                 Variable("Ctx.Cursors"),
                                                 Variable("F"),
                                             )
                                         ],
                                     ),
                                     LessEqual(
                                         Selected(
                                             Indexed(
                                                 Variable("Ctx.Cursors"),
                                                 Variable("F"),
                                             ),
                                             "Last",
                                         ),
                                         Variable("Lst"),
                                     ),
                                 )]),
                             ),
                             *[
                                 Equal(e, Old(e)) for e in [
                                     Variable("Ctx.Buffer_First"),
                                     Variable("Ctx.Buffer_Last"),
                                     Variable("Ctx.First"),
                                     Variable("Ctx.Cursors"),
                                 ]
                             ],
                         )),
                 ],
             )
         ] if scalar_fields else [],
     )
Exemplo n.º 24
0
    def create_composite_initialize_procedures(self, message: Message) -> UnitPart:
        def specification(field: Field) -> ProcedureSpecification:
            return ProcedureSpecification(
                f"Initialize_{field.name}", [InOutParameter(["Ctx"], "Context")]
            )

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

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification(f),
                    [
                        Precondition(
                            AndThen(
                                *self.setter_preconditions(f),
                                *self.unbounded_composite_setter_preconditions(message, f),
                            )
                        ),
                        Postcondition(
                            And(
                                *self.composite_setter_postconditions(message, f, message.types[f]),
                            )
                        ),
                    ],
                )
                for f, t in message.types.items()
                if isinstance(t, Payload) and unbounded_setter_required(message, f)
            ]
            + [
                SubprogramDeclaration(
                    specification_bounded(f),
                    [
                        Precondition(
                            AndThen(
                                *self.setter_preconditions(f),
                                *self.bounded_composite_setter_preconditions(message, f),
                            )
                        ),
                        Postcondition(
                            And(
                                *self.composite_setter_postconditions(message, f, message.types[f]),
                            )
                        ),
                    ],
                )
                for f, t in message.types.items()
                if isinstance(t, Payload) and bounded_setter_required(message, f)
            ],
            [
                SubprogramBody(
                    specification(f),
                    self.common.field_bit_location_declarations(Name(f.affixed_name)),
                    self.common.initialize_field_statements(message, f),
                )
                for f, t in message.types.items()
                if isinstance(t, Payload) and unbounded_setter_required(message, f)
            ]
            + [
                SubprogramBody(
                    specification_bounded(f),
                    [
                        ObjectDeclaration(
                            ["First"],
                            self.types.bit_index,
                            Call("Field_First", [Name("Ctx"), Name(f.affixed_name)]),
                            True,
                        ),
                        ObjectDeclaration(
                            ["Last"],
                            self.types.bit_index,
                            Add(Name("First"), Name("Length"), -Number(1)),
                            True,
                        ),
                    ],
                    self.common.initialize_field_statements(message, f),
                )
                for f, t in message.types.items()
                if isinstance(t, Payload) and bounded_setter_required(message, f)
            ],
        )
Exemplo n.º 25
0
    def create_scalar_setter_procedures(
        self, message: Message, scalar_fields: Mapping[Field, Scalar]
    ) -> UnitPart:
        def specification(field: Field, field_type: Type) -> ProcedureSpecification:
            type_name = (
                field_type.enum_name
                if isinstance(field_type, Enumeration) and field_type.always_valid
                else field_type.name
            )
            return ProcedureSpecification(
                f"Set_{field.name}",
                [
                    InOutParameter(["Ctx"], "Context"),
                    Parameter(["Val"], f"{message.package}.{type_name}"),
                ],
            )

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification(f, t),
                    [
                        Precondition(
                            AndThen(
                                *self.setter_preconditions(f),
                                Call(
                                    "Field_Condition",
                                    [
                                        Name("Ctx"),
                                        Aggregate(
                                            Name(f.affixed_name),
                                            Name("Val")
                                            if not isinstance(t, Enumeration)
                                            else Call("Convert", [Name("Val")]),
                                        ),
                                    ],
                                ),
                                Call("Valid", [Name("Val")])
                                if not isinstance(t, Enumeration)
                                else TRUE,
                                self.common.sufficient_space_for_field_condition(
                                    Name(f.affixed_name)
                                ),
                            )
                        ),
                        Postcondition(
                            And(
                                VALID_CONTEXT,
                                Call("Has_Buffer", [Name("Ctx")]),
                                Call("Valid", [Name("Ctx"), Name(f.affixed_name)]),
                                Equal(
                                    Call(f"Get_{f.name}", [Name("Ctx")]),
                                    Aggregate(TRUE, Name("Val"))
                                    if isinstance(t, Enumeration) and t.always_valid
                                    else Name("Val"),
                                ),
                                *self.setter_postconditions(message, f, t),
                                *[
                                    Equal(
                                        Call("Cursor", [Name("Ctx"), Name(p.affixed_name)]),
                                        Old(Call("Cursor", [Name("Ctx"), Name(p.affixed_name)])),
                                    )
                                    for p in message.predecessors(f)
                                ],
                            )
                        ),
                    ],
                )
                for f, t in scalar_fields.items()
            ],
            [
                SubprogramBody(
                    specification(f, t),
                    [
                        ObjectDeclaration(
                            ["Field_Value"],
                            "Field_Dependent_Value",
                            Aggregate(
                                Name(f.affixed_name),
                                Name("Val")
                                if not isinstance(t, Enumeration)
                                else Call("Convert", [Name("Val")]),
                            ),
                            True,
                        ),
                        ObjectDeclaration(["First", "Last"], self.types.bit_index),
                    ],
                    [
                        CallStatement(
                            "Reset_Dependent_Fields", [Name("Ctx"), Name(f.affixed_name)],
                        ),
                        CallStatement(
                            "Set_Field_Value",
                            [Name("Ctx"), Name("Field_Value"), Name("First"), Name("Last")],
                        ),
                        Assignment(
                            "Ctx",
                            Aggregate(
                                Selected("Ctx", "Buffer_First"),
                                Selected("Ctx", "Buffer_Last"),
                                Selected("Ctx", "First"),
                                Name("Last"),
                                Selected("Ctx", "Buffer"),
                                Selected("Ctx", "Cursors"),
                            ),
                        ),
                        Assignment(
                            Indexed(Selected("Ctx", "Cursors"), Name(f.affixed_name)),
                            NamedAggregate(
                                ("State", Name("S_Valid")),
                                ("First", Name("First")),
                                ("Last", Name("Last")),
                                ("Value", Name("Field_Value")),
                                (
                                    "Predecessor",
                                    Selected(
                                        Indexed(Selected("Ctx", "Cursors"), Name(f.affixed_name)),
                                        "Predecessor",
                                    ),
                                ),
                            ),
                        ),
                        Assignment(
                            Indexed(
                                Selected("Ctx", "Cursors"),
                                Call("Successor", [Name("Ctx"), Name(f.affixed_name)]),
                            ),
                            NamedAggregate(
                                ("State", Name("S_Invalid")), ("Predecessor", Name(f.affixed_name)),
                            ),
                        ),
                    ],
                )
                for f, t in scalar_fields.items()
            ],
        )
Exemplo n.º 26
0
def array_functions(array: Array, package: str) -> List[Subprogram]:
    common_precondition = LogCall(f'Is_Contained (Buffer)')

    return [
        Function('Valid_First', 'Boolean', [('Buffer', 'Types.Bytes')], [], [
            ReturnStatement(
                LogCall('Valid_Next (Buffer, Offset_Type (Buffer\'First))'))
        ], [Precondition(common_precondition)]),
        Procedure('Get_First', [
            ('Buffer', 'Types.Bytes'), ('Offset', 'out Offset_Type'),
            ('First', 'out Types.Index_Type'), ('Last', 'out Types.Index_Type')
        ], [], [
            Assignment('Offset', Value('Offset_Type (Buffer\'First)')),
            CallStatement('Get_Next', ['Buffer', 'Offset', 'First', 'Last'])
        ], [
            Precondition(
                And(common_precondition, LogCall('Valid_First (Buffer)'))),
            Postcondition(
                And(
                    And(GreaterEqual(Value('First'), First('Buffer')),
                        LessEqual(Value('Last'), Last('Buffer'))),
                    LogCall(f'{package}.{array.element_type}.Is_Contained '
                            '(Buffer (First .. Last))')))
        ]),
        Function('Valid_Next', 'Boolean', [
            ('Buffer', 'Types.Bytes'), ('Offset', 'Offset_Type')
        ], [], [
            PragmaStatement('Assume', [
                (f'{package}.{array.element_type}.Is_Contained '
                 '(Buffer (Types.Index_Type (Offset) .. Buffer\'Last))')
            ]),
            ReturnStatement(
                LogCall(
                    f'{package}.{array.element_type}.Is_Valid '
                    '(Buffer (Types.Index_Type (Offset) .. Buffer\'Last))'))
        ], [Precondition(common_precondition)]),
        Procedure(
            'Get_Next', [('Buffer', 'Types.Bytes'),
                         ('Offset', 'in out Offset_Type'),
                         ('First', 'out Types.Index_Type'),
                         ('Last', 'out Types.Index_Type')], [],
            [
                Assignment('First', Value('Types.Index_Type (Offset)')),
                Assignment(
                    'Last',
                    Add(
                        Value('First'),
                        Cast(
                            'Types.Length_Type',
                            MathCall(f'{package}.{array.element_type}.'
                                     'Message_Length (Buffer (First '
                                     '.. Buffer\'Last))')), Number(-1))),
                Assignment('Offset', Value('Offset_Type (Last + 1)')),
                PragmaStatement(
                    'Assume', [(f'{package}.{array.element_type}.Is_Contained '
                                '(Buffer (First .. Last))')])
            ], [
                Precondition(
                    And(common_precondition,
                        LogCall('Valid_Next (Buffer, Offset)'))),
                Postcondition(
                    And(
                        And(GreaterEqual(Value('First'), First('Buffer')),
                            LessEqual(Value('Last'), Last('Buffer'))),
                        LogCall(f'{package}.{array.element_type}.Is_Contained '
                                '(Buffer (First .. Last))')))
            ])
    ]
Exemplo n.º 27
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)
            ],
        )
Exemplo n.º 28
0
    def create_composite_accessor_procedures(
            composite_fields: Sequence[Field]) -> UnitPart:
        def specification(field: Field) -> ProcedureSpecification:
            return ProcedureSpecification(f"Get_{field.name}",
                                          [Parameter(["Ctx"], "Context")])

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification(f),
                    [
                        Precondition(
                            And(
                                Call("Has_Buffer", [Variable("Ctx")]),
                                Call("Present", [
                                    Variable("Ctx"),
                                    Variable(f.affixed_name)
                                ]),
                            ))
                    ],
                    [
                        FormalSubprogramDeclaration(
                            ProcedureSpecification(
                                f"Process_{f.name}",
                                [Parameter([f.name], const.TYPES_BYTES)]))
                    ],
                ) for f in composite_fields
            ],
            [
                SubprogramBody(
                    specification(f),
                    [
                        ObjectDeclaration(
                            ["First"],
                            const.TYPES_INDEX,
                            Call(
                                const.TYPES_BYTE_INDEX,
                                [
                                    Selected(
                                        Indexed(Variable("Ctx.Cursors"),
                                                Variable(f.affixed_name)),
                                        "First",
                                    )
                                ],
                            ),
                            True,
                        ),
                        ObjectDeclaration(
                            ["Last"],
                            const.TYPES_INDEX,
                            Call(
                                const.TYPES_BYTE_INDEX,
                                [
                                    Selected(
                                        Indexed(Variable("Ctx.Cursors"),
                                                Variable(f.affixed_name)),
                                        "Last",
                                    )
                                ],
                            ),
                            True,
                        ),
                    ],
                    [
                        CallStatement(
                            f"Process_{f.name}",
                            [
                                Slice(Variable("Ctx.Buffer.all"),
                                      Variable("First"), Variable("Last"))
                            ],
                        )
                    ],
                ) for f in composite_fields
            ],
        )
Exemplo n.º 29
0
 def create_internal_functions(
     self, message: Message, scalar_fields: Mapping[Field, Scalar]
 ) -> UnitPart:
     return UnitPart(
         [],
         [
             SubprogramBody(
                 ProcedureSpecification(
                     "Set_Field_Value",
                     [
                         InOutParameter(["Ctx"], "Context"),
                         Parameter(["Val"], "Field_Dependent_Value"),
                         OutParameter(["Fst", "Lst"], self.types.bit_index),
                     ],
                 ),
                 [
                     *self.common.field_bit_location_declarations(Selected("Val", "Fld")),
                     *self.common.field_byte_location_declarations(),
                 ],
                 [
                     Assignment("Fst", Name("First")),
                     Assignment("Lst", Name("Last")),
                     CaseStatement(
                         Selected("Val", "Fld"),
                         [
                             (
                                 Name(f.affixed_name),
                                 [
                                     CallStatement(
                                         "Insert",
                                         [
                                             Selected("Val", f"{f.name}_Value"),
                                             Slice(
                                                 Selected(Selected("Ctx", "Buffer"), "all"),
                                                 Name("Buffer_First"),
                                                 Name("Buffer_Last"),
                                             ),
                                             Name("Offset"),
                                         ],
                                     )
                                     if f in scalar_fields
                                     else NullStatement()
                                 ],
                             )
                             for f in message.all_fields
                         ],
                     ),
                 ],
                 [
                     Precondition(
                         AndThen(
                             Not(Constrained("Ctx")),
                             Call("Has_Buffer", [Name("Ctx")]),
                             In(Selected("Val", "Fld"), Range("Field")),
                             Call("Valid_Next", [Name("Ctx"), Selected("Val", "Fld")]),
                             self.common.sufficient_space_for_field_condition(
                                 Selected("Val", "Fld")
                             ),
                             ForAllIn(
                                 "F",
                                 Range("Field"),
                                 If(
                                     [
                                         (
                                             Call(
                                                 "Structural_Valid",
                                                 [
                                                     Indexed(
                                                         Selected("Ctx", "Cursors"), Name("F"),
                                                     )
                                                 ],
                                             ),
                                             LessEqual(
                                                 Selected(
                                                     Indexed(
                                                         Selected("Ctx", "Cursors"), Name("F"),
                                                     ),
                                                     "Last",
                                                 ),
                                                 Call(
                                                     "Field_Last",
                                                     [Name("Ctx"), Selected("Val", "Fld")],
                                                 ),
                                             ),
                                         )
                                     ]
                                 ),
                             ),
                         )
                     ),
                     Postcondition(
                         And(
                             Call("Has_Buffer", [Name("Ctx")]),
                             Equal(
                                 Name("Fst"),
                                 Call("Field_First", [Name("Ctx"), Selected("Val", "Fld")]),
                             ),
                             Equal(
                                 Name("Lst"),
                                 Call("Field_Last", [Name("Ctx"), Selected("Val", "Fld")]),
                             ),
                             GreaterEqual(Name("Fst"), Selected("Ctx", "First")),
                             LessEqual(Name("Fst"), Add(Name("Lst"), Number(1))),
                             LessEqual(
                                 Call(self.types.byte_index, [Name("Lst")]),
                                 Selected("Ctx", "Buffer_Last"),
                             ),
                             ForAllIn(
                                 "F",
                                 Range("Field"),
                                 If(
                                     [
                                         (
                                             Call(
                                                 "Structural_Valid",
                                                 [
                                                     Indexed(
                                                         Selected("Ctx", "Cursors"), Name("F"),
                                                     )
                                                 ],
                                             ),
                                             LessEqual(
                                                 Selected(
                                                     Indexed(
                                                         Selected("Ctx", "Cursors"), Name("F"),
                                                     ),
                                                     "Last",
                                                 ),
                                                 Name("Lst"),
                                             ),
                                         )
                                     ]
                                 ),
                             ),
                             *[
                                 Equal(e, Old(e))
                                 for e in [
                                     Selected("Ctx", "Buffer_First"),
                                     Selected("Ctx", "Buffer_Last"),
                                     Selected("Ctx", "First"),
                                     Selected("Ctx", "Cursors"),
                                 ]
                             ],
                         )
                     ),
                 ],
             )
         ],
     )
Exemplo n.º 30
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"),
                            )),
                    ],
                ),
            ],
        )