
Heriot-Watt University Research Gateway Tactics for the Dafny Program Verifier Citation for published version: Grov, G & Tumas, V 2016, Tactics for the Dafny Program Verifier. in M Chechik & J-F Raskin (eds), Tools and Algorithms for the Construction and Analysis of Systems: TACAS 2016. Lecture Notes in Computer Science, vol. 9636, Springer, pp. 36-53, 22nd International Conference on Tools and Algorithms for the Construction and Analysis of Systems 2016, Eindhoven, Netherlands, 2/04/16. https://doi.org/10.1007/978- 3-662-49674-9_3 Digital Object Identifier (DOI): 10.1007/978-3-662-49674-9_3 Link: Link to publication record in Heriot-Watt Research Portal Document Version: Early version, also known as pre-print Published In: Tools and Algorithms for the Construction and Analysis of Systems Publisher Rights Statement: This final publication is available at link.springer.com General rights Copyright for the publications made accessible via Heriot-Watt Research Portal is retained by the author(s) and / or other copyright owners and it is a condition of accessing these publications that users recognise and abide by the legal requirements associated with these rights. Take down policy Heriot-Watt University has made every reasonable effort to ensure that the content in Heriot-Watt Research Portal complies with UK legislation. If you believe that the public display of this file breaches copyright please contact [email protected] providing details, and we will remove access to the work immediately and investigate your claim. Download date: 25. Sep. 2021 Tactics for the Dafny Program Verifier? Gudmund Grov and Vytautas Tumas School of Mathematical and Computer Sciences, Heriot-Watt University, Edinburgh, UK. fG.Grov,[email protected] Abstract. Many modern program verifiers are based on automated the- orem provers, which enable full hiding of proof details and allow users to focus all their effort on the program text. This has the advantage that the additional expertise of theorem provers is not required, but has the drawback that when the prover fails to verify a valid program, the user has to annotate the program text with guidance for the verifier. This can be tedious, low-level and repetitive, and may impact on the annotation overhead, readability of the program text and overall development time. Inspired by proof tactics for interactive theorem provers [19], a notion of `tactics' for the state-of-the-art Dafny program verifier, called Tacny, is developed. With only minor extensions to the Dafny syntax, a user can encode high-level proof patterns as Dafny tactics, liberating herself from low-level and repetitive search tasks, whilst still working with fa- miliar Dafny programming constructs. Manual search and guidance can be replaced with calls to such tactics, which will automate this task. We provide syntax and semantics for Tacny, and show feasibility through a prototype implementation, applied to several examples. 1 Introduction Properties that programs should satisfy are commonly expressed by contracts: given a precondition the program guarantees that a given postcondition holds. Many modern program verifiers can then be used to verify that a program satis- fies its contract by automatically generating verification conditions (VCs), which are sent to an automated theorem prover. Failure to prove VCs will then be highlighted in the program text, and the user must then update the code with auxiliary annotations to guide the proof. A feature of this approach is that all interaction, including proof guidance, is conducted in the program text using a single programming language. Spec# [6], VCC [9], Verifast [24], Dafny [27], and SPARK 2014 [34] are program verifiers that follow this approach. The ability of users to guide the prover for the cases where the underlying theorem prover fails to verify a correct program is crucial. Such guidance involves changing, and in most cases adding, auxiliary annotations, and, in many cases, manipulation of a ghost state: a state that can be updated and used as normal, but is only used for verification purposes and will not be compiled. With the exception of generic lemmas that can be reused in e.g. Dafny, the support for reuse of previous verification tasks in order to reduce the required ? This work has been supported by EPSRC grants EP/M018407/1 and EP/J001058/1. We would like to the anonymous reviewers for excellent suggestions, thank our collab- orators Rustan Leino (who suggested the perm tactic and one case study), Rosemary Monahan, Altran and Escher. user interaction is limited. In particular, there is no support for users to encode knowledge of common \proof" steps used for verification tasks. Some trial-and- error is involved as several known \verification patterns" may be attempted, and there could be multiple options for each of them. For these cases, the verification guidance process can be unnecessarily tedious and cost-ineffective. This paper presents a novel extension to program verifiers, by extending the Dafny program verifier with a tactic language where users can encode more abstract and reusable verification patterns. Our hypothesis is that it is possible to abstract over low-level manual proof guidance by encoding high-level and reusable verification patterns in the program text of Dafny. The work is inspired by proof tactics for interactive theorem provers (ITPs), which allow users to encode re-usable proof patterns [19], and our main contri- bution is the introduction of such a tactic language on top of Dafny. A high-level introduction is given in x2 before giving the details of the syntactic extension and semantics in x3, and the implementation as the Tacny system in x4. We believe that Dafny tactics can be used to (i) reduce the annotation overhead 1; (ii) reduce development time; and (iii) increase readability of the program text by abstracting low-level proof details. Based upon experiments in Tacny, x5 pro- vides some evidence for (i), x6 contains related work; while we conclude and discuss future work, including how we plan to address (ii) and (iii), in x7. 2 Dafny tactics by example2 Dafny [27] is a programming language and program verifier for the .NET plat- form, developed by Microsoft Research. The language is an imperative object- oriented language, containing both methods and proper functions (i.e. without side-effects). It also supports advanced features such as inductive [28] and co- inductive [29] datatypes and higher-order types [26]. It uses familiar notations for assignment (x := e), declarations (var x := e;), conditionals ( if and if −else) and loops (e.g. while). It also supports pattern matching (match) and a `such as' operator, where x :j p means that x is assigned a value such that p holds. Dafny has been designed for verification. Properties are specified by contracts for methods/functions in terms of preconditions (requires) and postconditions (ensures). To verify a program, Dafny translates it into an intermediate verifi- cation language (IVL)3 called Boogie [5]. From Boogie a set of VCs is generated and sent to the Z3 SMT solver [35]. If it fails, then the failure is translated back to the Dafny code, via Boogie. In the case of failure, a user must provide guidance in the program text4. The simplest form is to add assertions (assert) of true properties in the program text. In the case of loops, we might also provide loop invariants (invariant). 1 To illustrate, [37] reported on 4:8 Lines of Annotation for each Line of Code. 2 Full details of all examples and results in the paper available from [2]. 3 An IVL can be seen as a layer to ease the process of generating new program verifiers. 4 We assume correct programs: verification may also fail because the program is in- correct and in this case the program (or specification) needs to change. 2 Loops and recursion have to be shown to terminate and for advanced cases a user needs to provide a variant (decreases) to help Dafny prove this. For more advanced verification tasks, one can make use of the ghost state. A ghost variable (ghost var) or ghost method can be introduced and used by the verifier. A lemma (lemma) is a type of ghost method that can be used to express richer properties, where assumptions are preconditions, and the conclu- sion becomes the postcondition. The proof is a method body that satisfies the postcondition, given the precondition. We will see examples of this below, but note that standard programming language elements are used in the body of the lemma, which illustrates the close correspondence between proofs and programs. To illustrate Dafny, consider a simple compiler for arithmetic expressions5. Here, an inductive data type is used to capture arithmetic expressions as num- bers, variables or addition: datatype aexp = N( n : i n t ) j V( x : vname ) j Plus (0 : aexp , 1 : aexp ) A state s is a Dafny map from vnames to integers; Total(s) states that the state s is total; aval(a,s) is the evaluation of the arithmetic expression a over the state s; while asimp const(a) performs constant folding of arithmetic expression a: constants added together are recursively replaced by their sum. The following lemma proves that constant folding preserves the behaviour for a total state: lemma AsimpConst(a : aexp , s : s t a t e ) r e q u i r e s Total ( s ) ; ensures a v a l ( a s i m p const(a),s) = a v a l ( a , s ) ; f match a case N( n ) ) case V( x ) ) case Plus(a0,a1) ) AsimpConst(a0,s); AsimpConst(a1,s); g The proof follows by structural induction: using pattern matching, a case is introduced for each constructor and for the recursive case the lemma is applied recursively for each argument.
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages18 Page
-
File Size-