Ejemplo n.º 1
0
 def setter_postconditions(
     self, message: Message, field: Field, field_type: Type
 ) -> Sequence[Expr]:
     return [
         *[
             Call("Invalid", [Name("Ctx"), Name(p.affixed_name)])
             for p in message.successors(field)
             if p != FINAL
         ],
         *self.common.valid_path_to_next_field_condition(message, field, field_type),
         *[
             Equal(e, Old(e))
             for e in [
                 Selected("Ctx", "Buffer_First"),
                 Selected("Ctx", "Buffer_Last"),
                 Selected("Ctx", "First"),
                 Call("Predecessor", [Name("Ctx"), Name(field.affixed_name)]),
                 Call("Valid_Next", [Name("Ctx"), Name(field.affixed_name)]),
             ]
             + [
                 Call(f"Get_{p.name}", [Name("Ctx")])
                 for p in message.definite_predecessors(field)
                 if isinstance(message.types[p], Scalar)
             ]
         ],
     ]
Ejemplo n.º 2
0
 def invalid_successors_invariant() -> Expr:
     return AndThen(
         *[
             If(
                 [
                     (
                         AndThen(
                             *[
                                 Call(
                                     "Invalid",
                                     [Indexed(Variable("Cursors"), Variable(p.affixed_name))],
                                 )
                                 for p in message.direct_predecessors(f)
                             ]
                         ),
                         Call(
                             "Invalid", [Indexed(Variable("Cursors"), Variable(f.affixed_name))],
                         ),
                     )
                 ]
             )
             for f in message.fields
             if f not in message.direct_successors(INITIAL)
         ]
     )
Ejemplo n.º 3
0
def public_context_predicate() -> Expr:
    return And(
        GreaterEqual(Call(const.TYPES_BYTE_INDEX, [Variable("First")]), Variable("Buffer_First")),
        LessEqual(Call(const.TYPES_BYTE_INDEX, [Variable("Last")]), Variable("Buffer_Last")),
        LessEqual(Variable("First"), Variable("Last")),
        LessEqual(Variable("Last"), Div(Last(const.TYPES_BIT_INDEX), Number(2))),
    )
Ejemplo n.º 4
0
    def create_verify_message_procedure(
            message: Message, context_invariant: Sequence[Expr]) -> UnitPart:
        specification = ProcedureSpecification(
            "Verify_Message", [InOutParameter(["Ctx"], "Context")])

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification,
                    [
                        Postcondition(
                            And(
                                Equal(
                                    Call("Has_Buffer", [Variable("Ctx")]),
                                    Old(Call("Has_Buffer", [Variable("Ctx")])),
                                ),
                                *context_invariant,
                            )),
                    ],
                )
            ],
            [
                SubprogramBody(
                    specification,
                    [],
                    [
                        CallStatement(
                            "Verify",
                            [Variable("Ctx"),
                             Variable(f.affixed_name)]) for f in message.fields
                    ],
                )
            ],
        )
Ejemplo n.º 5
0
def test_attribute_expression_substituted() -> None:
    assert_equal(
        Val("X", Variable("Y")).substituted(
            lambda x: Number(42) if x == Val("X", Variable("Y")) else x
        ),
        Number(42),
    )
    assert_equal(
        -Val("X", Variable("Y")).substituted(
            lambda x: Number(42) if x == Val("X", Variable("Y")) else x
        ),
        Number(-42),
    )
    assert_equal(
        Val("X", Variable("Y")).substituted(lambda x: Call("Y") if x == Variable("Y") else x),
        Val("X", Call("Y")),
    )
    assert_equal(
        -Val("X", Variable("Y")).substituted(lambda x: Call("Y") if x == Variable("Y") else x),
        -Val("X", Call("Y")),
    )
    assert_equal(
        -Val("X", Variable("Y")).substituted(
            lambda x: Variable(f"P_{x}")
            if isinstance(x, Variable)
            else (Pos(x.prefix, x.expression) if isinstance(x, Val) else x)
        ),
        -Pos("P_X", Variable("P_Y")),
    )
Ejemplo 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
            ],
        )
Ejemplo n.º 7
0
 def valid_path_to_next_field_condition(
     self, message: Message, field: Field, field_type: Type
 ) -> Sequence[Expr]:
     return [
         If(
             [
                 (
                     l.condition,
                     And(
                         Equal(
                             Call("Predecessor", [Name("Ctx"), Name(l.target.affixed_name)],),
                             Name(field.affixed_name),
                         ),
                         Call("Valid_Next", [Name("Ctx"), Name(l.target.affixed_name)])
                         if l.target != FINAL
                         else TRUE,
                     ),
                 )
             ]
         ).simplified(
             {
                 **{
                     Variable(field.name): Call("Convert", [Name("Value")])
                     if isinstance(field_type, Enumeration) and field_type.always_valid
                     else Name("Value")
                 },
                 **self.public_substitution(message),
             }
         )
         for l in message.outgoing(field)
         if l.target != FINAL
     ]
Ejemplo n.º 8
0
 def composite_setter_postconditions(
     self, message: Message, field: Field, field_type: Type
 ) -> Sequence[Expr]:
     return [
         VALID_CONTEXT,
         Call("Has_Buffer", [Name("Ctx")]),
         *self.setter_postconditions(message, field, field_type),
         Call("Structural_Valid", [Name("Ctx"), Name(field.affixed_name)]),
     ]
Ejemplo n.º 9
0
 def composite_setter_postconditions(self, message: Message,
                                     field: Field) -> Sequence[Expr]:
     return [
         Call("Has_Buffer", [Variable("Ctx")]),
         *self.setter_postconditions(message, field),
         Call("Structural_Valid",
              [Variable("Ctx"),
               Variable(field.affixed_name)]),
     ]
Ejemplo n.º 10
0
 def setter_preconditions(self, field: Field) -> Sequence[Expr]:
     return [
         VALID_CONTEXT,
         Not(Constrained("Ctx")),
         Call("Has_Buffer", [Name("Ctx")]),
         Call("Valid_Next", [Name("Ctx"), Name(field.affixed_name)]),
         LessEqual(
             Call("Field_Last", [Name("Ctx"), Name(field.affixed_name)]),
             Div(Last(self.types.bit_index), Number(2)),
         ),
     ]
Ejemplo n.º 11
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),
                            ),
                        ),
                    ),
                )
            ],
        )
Ejemplo n.º 12
0
 def field_bit_location_declarations(self, field_name: Name) -> Sequence[Declaration]:
     return [
         ObjectDeclaration(
             ["First"],
             self.types.bit_index,
             Call("Field_First", [Name("Ctx"), field_name]),
             True,
         ),
         ObjectDeclaration(
             ["Last"], self.types.bit_index, Call("Field_Last", [Name("Ctx"), field_name]), True,
         ),
     ]
Ejemplo n.º 13
0
    def substitution(self, message: Message, prefix: bool = True) -> Mapping[Name, Expr]:
        def prefixed(name: str) -> Expr:
            return Selected(Name("Ctx"), name) if prefix else Name(name)

        first = prefixed("First")
        last = prefixed("Last")
        cursors = prefixed("Cursors")

        return {
            **{First("Message"): first},
            **{Last("Message"): last},
            **{
                First(f.name): Selected(Indexed(cursors, Name(f.affixed_name)), "First")
                for f in message.fields
            },
            **{
                Last(f.name): Selected(Indexed(cursors, Name(f.affixed_name)), "Last")
                for f in message.fields
            },
            **{
                Length(f.name): Add(
                    Sub(
                        Selected(Indexed(cursors, Name(f.affixed_name)), "Last"),
                        Selected(Indexed(cursors, Name(f.affixed_name)), "First"),
                    ),
                    Number(1),
                )
                for f in message.fields
            },
            **{
                Variable(f.name): Call(
                    self.types.bit_length,
                    [Selected(Indexed(cursors, Name(f.affixed_name)), f"Value.{f.name}_Value")],
                )
                for f, t in message.types.items()
                if not isinstance(t, Enumeration)
            },
            **{
                Variable(f.name): Call(
                    self.types.bit_length,
                    [Selected(Indexed(cursors, Name(f.affixed_name)), f"Value.{f.name}_Value")],
                )
                for f, t in message.types.items()
                if isinstance(t, Enumeration)
            },
            **{
                Variable(l): Call(self.types.bit_length, [Call("Convert", [Name(l)])])
                for l in itertools.chain.from_iterable(
                    t.literals.keys() for t in message.types.values() if isinstance(t, Enumeration)
                )
            },
        }
Ejemplo n.º 14
0
 def setter_preconditions(field: Field) -> Sequence[Expr]:
     return [
         Not(Constrained("Ctx")),
         Call("Has_Buffer", [Variable("Ctx")]),
         Call("Valid_Next", [Variable("Ctx"),
                             Variable(field.affixed_name)]),
         LessEqual(
             Call("Field_Last",
                  [Variable("Ctx"),
                   Variable(field.affixed_name)]),
             Div(Last(const.TYPES_BIT_INDEX), Number(2)),
         ),
     ]
Ejemplo n.º 15
0
def field_bit_location_declarations(field_name: Name) -> Sequence[Declaration]:
    return [
        ObjectDeclaration(
            ["First"],
            const.TYPES_BIT_INDEX,
            Call("Field_First", [Variable("Ctx"), field_name]),
            True,
        ),
        ObjectDeclaration(
            ["Last"],
            const.TYPES_BIT_INDEX,
            Call("Field_Last", [Variable("Ctx"), field_name]),
            True,
        ),
    ]
Ejemplo n.º 16
0
 def unbounded_composite_setter_preconditions(
     self, message: Message, field: Field
 ) -> Sequence[Expr]:
     return [
         Call(
             "Field_Condition",
             [Name("Ctx"), NamedAggregate(("Fld", Name(field.affixed_name)))]
             + (
                 [Call("Field_Length", [Name("Ctx"), Name(field.affixed_name)],)]
                 if length_dependent_condition(message)
                 else []
             ),
         ),
         self.common.sufficient_space_for_field_condition(Name(field.affixed_name)),
     ]
Ejemplo n.º 17
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),
                            ),
                        ),
                    ),
                )
            ],
        )
Ejemplo n.º 18
0
 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
Ejemplo n.º 19
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()
            ],
        )
Ejemplo n.º 20
0
 def valid_predecessors_invariant() -> Expr:
     return AndThen(
         *[
             If(
                 [
                     (
                         Call(
                             "Structural_Valid",
                             [Indexed(Variable("Cursors"), Variable(f.affixed_name))],
                         ),
                         Or(
                             *[
                                 AndThen(
                                     Call(
                                         "Structural_Valid"
                                         if l.source in composite_fields
                                         else "Valid",
                                         [
                                             Indexed(
                                                 Variable("Cursors"),
                                                 Variable(l.source.affixed_name),
                                             )
                                         ],
                                     ),
                                     Equal(
                                         Selected(
                                             Indexed(
                                                 Variable("Cursors"), Variable(f.affixed_name),
                                             ),
                                             "Predecessor",
                                         ),
                                         Variable(l.source.affixed_name),
                                     ),
                                     l.condition.substituted(
                                         substitution(message, embedded=True)
                                     ),
                                 ).simplified()
                                 for l in message.incoming(f)
                             ]
                         ),
                     )
                 ]
             )
             for f in message.fields
             if f not in message.direct_successors(INITIAL)
         ]
     )
Ejemplo n.º 21
0
 def field_value(field: Field, field_type: Type) -> Expr:
     if isinstance(field_type, Enumeration):
         if public:
             return Call(
                 target_type, [Call("To_Base", [Call(f"Get_{field.name}", [Variable("Ctx")])])],
             )
         return Call(
             target_type,
             [
                 Selected(
                     Indexed(cursors, Variable(field.affixed_name)), f"Value.{field.name}_Value"
                 )
             ],
         )
     if isinstance(field_type, Scalar):
         if public:
             return Call(target_type, [Call(f"Get_{field.name}", [Variable("Ctx")])])
         return Call(
             target_type,
             [
                 Selected(
                     Indexed(cursors, Variable(field.affixed_name)), f"Value.{field.name}_Value"
                 )
             ],
         )
     if isinstance(field_type, Composite):
         return Variable(field.name)
     assert False, f'unexpected type "{type(field_type).__name__}"'
     return UNDEFINED
Ejemplo n.º 22
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))],
            ),
        ),
    ]
Ejemplo n.º 23
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))],
             ),
         ),
     ]
Ejemplo n.º 24
0
 def field_length(field: Field) -> Expr:
     if public:
         return Call("Field_Length", [Variable("Ctx"), Variable(field.affixed_name)])
     return Add(
         Sub(
             Selected(Indexed(cursors, Variable(field.affixed_name)), "Last"),
             Selected(Indexed(cursors, Variable(field.affixed_name)), "First"),
         ),
         Number(1),
     )
Ejemplo n.º 25
0
 def field_value(field: Field) -> Expr:
     if public:
         return Call(f"Get_{field.name}", [Variable("Ctx")])
     return Selected(
         Indexed(
             Variable("Ctx.Cursors" if not embedded else "Cursors"),
             Variable(field.affixed_name),
         ),
         f"Value.{field.name}_Value",
     )
Ejemplo n.º 26
0
def test_attribute_substituted() -> None:
    assert_equal(First("X").substituted(lambda x: Number(42) if x == First("X") else x), Number(42))
    assert_equal(
        -First("X").substituted(lambda x: Number(42) if x == First("X") else x), Number(-42)
    )
    assert_equal(
        First("X").substituted(lambda x: Call("Y") if x == Variable("X") else x), First(Call("Y")),
    )
    assert_equal(
        -First("X").substituted(lambda x: Call("Y") if x == Variable("X") else x),
        -First(Call("Y")),
    )
    assert_equal(
        -First("X").substituted(
            lambda x: Variable(f"P_{x}")
            if isinstance(x, Variable)
            else (Last(x.prefix) if isinstance(x, First) else x)
        ),
        -Last(Variable("P_X")),
    )
Ejemplo n.º 27
0
 def result(field: Field) -> Expr:
     return Call(
         "To_Actual",
         [
             Selected(
                 Indexed(Variable("Ctx.Cursors"),
                         Variable(field.affixed_name)),
                 f"Value.{field.name}_Value",
             )
         ],
     )
Ejemplo n.º 28
0
 def bounded_composite_setter_preconditions(message: Message,
                                            field: Field) -> Sequence[Expr]:
     return [
         Call(
             "Field_Condition",
             [
                 Variable("Ctx"),
                 NamedAggregate(("Fld", Variable(field.affixed_name)))
             ] + ([Variable("Length")]
                  if common.length_dependent_condition(message) else []),
         ),
         GreaterEqual(
             Call("Available_Space",
                  [Variable("Ctx"),
                   Variable(field.affixed_name)]),
             Variable("Length"),
         ),
         LessEqual(
             Add(
                 Call("Field_First",
                      [Variable("Ctx"),
                       Variable(field.affixed_name)]),
                 Variable("Length"),
             ),
             Div(Last(const.TYPES_BIT_INDEX), Number(2)),
         ),
         Or(*[
             And(
                 *[
                     Call("Valid",
                          [Variable("Ctx"),
                           Variable(field.affixed_name)])
                     for field in message.fields
                     if Variable(field.name) in l.condition.variables()
                 ],
                 l.condition.substituted(
                     mapping={
                         Variable(field.name): Call(f"Get_{field.name}",
                                                    [Variable("Ctx")])
                         for field in message.fields
                         if Variable(field.name) in l.condition.variables()
                     }),
             ) for l in message.incoming(field)
             if Last("Message") in l.length
         ]),
         Equal(
             Mod(
                 Call("Field_First",
                      [Variable("Ctx"),
                       Variable(field.affixed_name)]),
                 Size(const.TYPES_BYTE),
             ),
             Number(1),
         ),
         Equal(
             Mod(Variable("Length"), Size(const.TYPES_BYTE)),
             Number(0),
         ),
     ]
Ejemplo n.º 29
0
def valid_path_to_next_field_condition(message: Message, field: Field) -> Sequence[Expr]:
    return [
        If(
            [
                (
                    l.condition.substituted(substitution(message, public=True)),
                    And(
                        Equal(
                            Call(
                                "Predecessor", [Variable("Ctx"), Variable(l.target.affixed_name)],
                            ),
                            Variable(field.affixed_name),
                        ),
                        Call("Valid_Next", [Variable("Ctx"), Variable(l.target.affixed_name)])
                        if l.target != FINAL
                        else TRUE,
                    ),
                )
            ]
        ).simplified()
        for l in message.outgoing(field)
        if l.target != FINAL
    ]
Ejemplo n.º 30
0
 def public_substitution(self, message: Message) -> Mapping[Name, Expr]:
     return {
         **{First("Message"): Selected(Name("Ctx"), "First")},
         **{Last("Message"): Selected(Name("Ctx"), "Last")},
         **{
             First(f.name): Call("Field_First", [Name("Ctx"), Name(f.affixed_name)])
             for f in message.fields
         },
         **{
             Last(f.name): Call("Field_Last", [Name("Ctx"), Name(f.affixed_name)])
             for f in message.fields
         },
         **{
             Length(f.name): Call("Field_Length", [Name("Ctx"), Name(f.affixed_name)])
             for f in message.fields
         },
         **{
             Variable(f.name): Call(
                 self.types.bit_length, [Call(f"Get_{f.name}", [Name("Ctx")])]
             )
             for f, t in message.types.items()
             if not isinstance(t, Enumeration)
         },
         **{
             Variable(f.name): Call(
                 self.types.bit_length, [Call("Convert", [Call(f"Get_{f.name}", [Name("Ctx")])])]
             )
             for f, t in message.types.items()
             if isinstance(t, Enumeration)
         },
         **{
             Variable(l): Call(self.types.bit_length, [Call("Convert", [Name(l)])])
             for l in itertools.chain.from_iterable(
                 t.literals.keys() for t in message.types.values() if isinstance(t, Enumeration)
             )
         },
     }