Пример #1
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
Пример #2
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]
Пример #3
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
Пример #4
0
def contain_functions() -> List[Subprogram]:
    return [
        ExpressionFunction('Is_Contained',
                           'Boolean', [('Buffer', 'Types.Bytes')],
                           aspects=[Ghost(), Import()]),
        Procedure('Label', [('Buffer', 'Types.Bytes')], [],
                  [PragmaStatement('Assume', ['Is_Contained (Buffer)'])],
                  aspects=[Postcondition(LogCall('Is_Contained (Buffer)'))])
    ]
Пример #5
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)])
Пример #6
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)])
Пример #7
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)')))])
Пример #8
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)])
Пример #9
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)])