1.2 conventions
Specifying a library or abstract usage rule is mainly done through method conventions. It clearly shows what the caller wants and what the caller can get from the implementation. To specify an implementation design
Sequencers mainly use specifications to constrain the value range of data. These specifications are called object constants and clearly describe what the data domains of each object should maintain when the object is in a stable State. For example
Class attendancerecord {
Student []! Students;
Bool []! Absent;
Invariant students. Length = absent. length;
Declared student and absent array length should be the same.
As we can see from the simple example above, it is impossible to keep the object invariant, because it is impossible to change the length of two arrays at the same time in the language. This is what we mean: the object's invariant is in a stable State.
It is essentially because this object is not the object of the current operation. Using our methodology for object invariant [, 6], spec # Must be clear when a pair
Such as in its stable state, which indicates that this object is vulnerable to modification. Spec # introduces a block declaration expose, which explicitly specifies when an object's invariant can be damaged temporarily:
Ming
Expose (o ){
S;
}
The object o is exposed during the duration of the sub-declaration S, which may operate on the member variables of O. Because of the object-orientedProgramModification of member variables tends to be compressed in the class that declares these member variables, so the table
Dashboard o is often this. The object invariant hypothesis is retained at the end of the expose declaration, while spec # ensures this assumption through a runtime check. Object invariant at the end of the constructor
It also needs to be checked once (although there is flexibility to allow the initial check of an object invariant elsewhere; here we ignore these details ).
By default, each public method of a class has an implicit
Expose (this ){...}
Around the method body. Our preliminary experience confirms that this default value eliminates most of the need for explicit expose declarations. When you need to re-import, you can use a custom feature on the method to invalidate the default value.
Exposing an object is not idempotent. This means that when o has been exposed, it will be a checked runtime error if it reaches expose (o. From this perspective, the exposure mechanism and concurrency
In programming, the thread-non-reentrant mutex is very similar. The monitor invariant [34] is similar to our object invariant concept. If the exposure is idempotent
You cannotCodeThe block depends on the object invariant to be immediately maintained. The idempotence of the same thread-reentrant mutex indicates that you cannot depend on the monitor invariant in each other.
Hold the request.
To make the object-invariant methodology of spec # reliable, all modifications to a member variable O. F must be made at O exposure. In addition, this methodology uses
To organize objects into a tree hierarchy. This relationship is state dependent and allows ownership conversion. Such modifications and ownership are implemented through boogie, rather than at runtime.
.
Object constants can be declared by any class. In order to support the module check of constants, a class does not need to know its superclass and future subclasses, these object constants are divided into class frameworks [3, 17] based on the differences of classes declared by each invariant. Expose mechanism to process the class framework.
To reduce the programmer's initial overhead of the expose statement and handle non-Virtual Methods in a more backward compatible manner (see [3]), spec # allows an expose statement to expose more than one class
Framework. To explain this feature, we first need to demonstrate a more general form of expose declaration in spec #, which is
Expose (O upto t ){...}
T is a superclass of the static type of expression o. If "upto
T "is omitted, and T is the static type of expression o by default. More accurately than described above, this statement exposes all o class frameworks (*) from the exposed class frameworks (*) at the same time
Exposing class framework t itself ). Non-idempotence requires at least one class framework to be exposed as part of the operation. At the end of the expose block, the exposed class framework should be changed to non-exposed
And the object constants of each class framework must be checked. This is done through the dynamic termination method sent by the compiler at runtime.
An unknown target class framework is exposed, especially when the class framework checks the invariant for those declared locations that may be unknown, pointing to a module problem, that is, static verification. Therefore, we use a stricter module for expose in Boogie. In particular,
Expose (O upto t ){...}
The precondition condition is that the T-class framework of O is not exposed-that is, the underlying derived non-exposure class framework of O is a subclass of T. Boogie requires that the underlying non-exposure class framework of o be
T to emphasize this preprocessing condition. With this method, Boogie has the ability to find all the object constants that need to be checked at the end of the expose block. As a result, the runtime behavior and
Boogie makes sure that the difference between things means that programmers can start to write and run spec # programs more easily, but in this way they may need to invest more effort to get higher Program correctness.
Confidence, the correctness of the program is ensured by boogie (just as the extra effort to make sure that boogie's modifications and ownership rules comply with requirements ).
Object constants can only involve constants, member variables, array elements, independent state methods, and restricted methods. If a method does not depend on a variable state, it is called a state independent. A restricted method may
Dependent on the state of the object that owns it. spec # The Compiler introduces a conservative impact analysis to check that these attributes are observed.
Spec # also supports class constants, which are useful in the assumption of static member variables. The methodology and constraints of class-invariant are similar to those of the object-invariant methodology and constraints, but class-invariant does not inherit [44]. The expose statement simply uses a class to replace an object as a parameter.
1.3 Other Details
If an exception is thrown during the evaluation of a contract in spec #, the exception is packaged into a contract evaluation exception and propagated. This corresponds to the agreed runtime evaluation in JML, where such an exception is caught and the formula around it is processed like it returns a Boolean value according to certain rules, see [14].
Standardized customization features
C # provides custom features as a method for placing arbitrary data on the program structure, such as classes, methods, and member variables. A custom feature is compiled into metadata. the standard format of metadata allows many applications.
Program to read custom features that are attached to special declarations. Spec # also allows each standard clause to use custom features for annotation.
Custom features allow third-party tool users to use tool-specific methods to mark specifications. For example, the spec # compiler uses the conditional custom feature to control which specification is issued as a runtime check in the current version. For example
Int binarysearch (object []! A, object o, int Lo, int hi)
Requires 0 <= lo & lo <= Hi & Hi <= A. length;
[Conditional ("debug")] requires issorted (A, lo, hi );
{...}
The compiler issues a runtime check for each preprocessing condition in the debug version, but only one check for the first preprocessing condition in a non-debug version. This supports the general programming style in debugging assertions (see [53] for example).
Purity
We want to have this attribute. A program can run normally when it opens the Convention check, and it can run normally when some of the conventions check is closed. Therefore, we require the expressions in all conventions to be pure.
They have no side effects and will not throw any checked exceptions. The compiler ensures this situation by using an appropriate system. We are considering a more free definition of purity,
For example, observing the purity [7] and providing a large amount of data for analysis completed by salcianu and rinard [58].
2. System Architecture
In terms of architecture, the spec # programming system consists of a compiler, A Runtime Library, and a boogie validator. The compiler has been fully embedded into Microsoft Visual
In the studio environment, the project system, construction process, design tools, syntax emphasis, and intelliisense context-sensitive editing and documentation assistance are provided.
Spec # the difference between a compiler and a common compiler is that it not only generates executable code based on a program written in spec # language, but also maintains all the specifications in a language-independent format. Make available rules
Fan becomes an independent unit that passes compilation, which means that program analysis and verification tools can consume these specifications. At the same time, you do not need to modify spec # compiler or write a new source language compiler.
Spec # the compiler can save the specification to the binary code that is the same as the compiled code because it specifies that the target is Microsoft's. Net Universal Language Runtime (CLR ). CLR enables multiple
Data Type information is associated with most elements of the Data Type System (types, methods, member variables, and so on) and provides a wide range of metadata tools. Spec # The Compiler attaches a specification to each program with a specification
Build. (Technically, these specifications are saved as strings in custom features. All the names are completely resolved; when the submission is cumbersome, it makes it easy for any tool to consume it.
Yes .)
As a result, we made this design decision to let boogie consume compiled code, insteadSource code. One additional benefit is that boogie can be used to verify the code written in languages other than spec #.
Code, as long as there is an out-of-hand process for every convention appended to such code. We use this
For details, see section 2.2.
2.0 runtime check
Spec # Both preprocessing and post-processing conditions are converted to Inline code. This is not only because of performance considerations, but also to avoid creating additional methods and member variables in the compilation code. All of these
Labels are attached to the Inline code, so that the code corresponding to the spec # convention can be distinguished from the code of other parts of the spec # program. This distinction is made by consuming spec # from metadata.
Required by the analysis tool. For example, Boogie must be able to determine whether the non-agreed code in the method matches the post-processing condition, rather than connecting the code that checks the post-processing condition after the non-agreed code. Inline code
Evaluate these conditions and, if any, throw an appropriate Convention exception.
The compiler adds a new method for each class that declares an invariant to check the object invariant. Special object member variables, such as the invariant level [3] and the object owner [45], are added
Use the top-level superclass (super-most) of the spec # feature in the subtree of each class hierarchy
Class. As we mentioned in the first part, the entire methodology is not executed during the runtime; for example, the runtime check does not check whether an object is exposed before updating a member variable. This means
An error that can be captured by boogie may not be detected at runtime.
2.1 static Verification
Build a program from the intermediate language (including metadata), spec #'s static program validators, Boogie, in its own intermediate language boogiepl. Boogiepl is
A simple language of a process. In most cases, the implementation of a process is a basic code block consisting of four types of statements: Specify, assert, hypothesis, and process call (Cf. [47]).
A Reasoning System can process boogiepl programs and use abstract interpretations between processes [15, 57] to obtain attributes such as cyclic constants. Any inherited attribute is declared as an asserted or hypothetical statement.
Add to the program. Then, the boogiepl program uses several transformations as the condition verification that is submitted to an automatic theorem proving program ends. These conversions, such as through the introduction of corrupt (havoc) Declarations
Cut off all loops to generate a non-circular control flow chart. This is done by maintaining the correctness of the analysis. A declaration of destruction assigns any value to a variable, and all variables allocated to a loop
Introducing a damage statement will enable the theorem proof program to consider an arbitrary cyclic iterator. All feedback from the theorem proof program is scheduled to return to the source program before it is released to the user [43. The result is
Programmers can only make some modifications at the program source level to interact with the boogie validators, such as adding conventions.
Currently, Boogie uses the simplify theorem to prove the program [18], but we intend to transfer it to a new experimental rule validators developed by Microsoft reserach.