Ivy is a library that provides a simple imperative language called Imp with a built-in deductive verifier using SMT (Satisfiability Modulo Theories) solvers. The core Imp language, as well as the specification syntax, closely matches that of the Dafny project by Microsoft. In fact, Ivy is mostly our attempt to re-implement a simpler version of Dafny from the ground up for educational purposes.
Ivy parses and verifies Imp programs that include:
- Pre-conditions and post-conditions for methods
- Loop invariants in
whileloops - Simplified control-flow constructs (if-else, while, assignment, etc.)
- Arithmetic and boolean expressions
Once the program is parsed, Ivy generates verification conditions and checks them using Z3's Java API, automatically proving whether the program meets the requirements or not.
Imp is a small imperative language extended with logical annotations (inspired by Dafny). The language includes:
- Assignments
x = x + 1; - If-Else
if (x < 10) { x = x + 1; } else { x = x - 1; } - Composite Statements (S1; S2; ...; Sn)
x = 5; y = 2; x = x * y; - While Loops with invariants
while (x < 10) invariant x >= 0 invariant x <= 10 { x = x + 1; } - Method Declarations with pre-conditions (
requires) and post-conditions (ensures)method Foo(int n) returns (int result) requires n >= 0 ensures result == 2 * n { result = 2 * n; }
- Expressions
- Boolean:
&&,||,!,==>,<,>,<=,>=,== - Integer:
+,-,*,/,%, unary minus - Quantifiers:
forall (int i) :: ...,exists (bool b) :: ...
- Boolean:
- Pre/Post Conditions
requires <bool expr>ensures <bool expr>
- Loop Invariants
while (cond) invariant <bool expr> { ... }
- Methods
- Syntax and Z3 conversion are supported for methods; however, verification for programs with method calls is still not implemented.
The concrete syntax is defined in Imp.g4.
The library is organized into four main modules:
- Imp Language (package java/imp)
- Z3 Interpreter (package java/interpreter)
- Clause Generator (package java/verification/generator)
- Solver (ImpVerifier.java)
- Lexer & Parser
Implemented via ANTLR using the fileImp.g4. The generated code tokenizes and parses Imp source into a parse tree. - AST & AST Builder
TheASTBuilderperforms a parse-tree walk to construct a high-level, in-memory AST (Abstract Syntax Tree). - Type Checker
TheTypeCheckerensures that programs are well-typed.
Ivy uses AWP (Approximate Weakest Precondition) and AVC (Approximate Verification Condition) techniques to generate verification conditions.
Ivy uses the Z3 Java API to check the satisfiability of generated verification conditions.
- Java (JDK 8+)
- Maven (for building)
- Z3 Java bindings
mvn clean packageRun the verifier on an .imp file:
java -cp lib/com.microsoft.z3.jar:lib/antlr4-runtime-4.13.2.jar:target/imp-verifier-1.0.jar imp.ImpVerifier path/to/yourProgram.impjava -cp lib/com.microsoft.z3.jar:lib/antlr4-runtime-4.13.2.jar:target/imp-verifier-1.0.jar imp.ImpVerifier SumOfFirstNNumbers.impRun unit and integration tests with:
mvn test- Function calls and arrays are syntactically allowed, but their verification is not yet implemented.
- Counterexample reporting from Z3 is not implemented. That is, currently we determine whether the program meets the specification or not, but we don't provide the user an input/execution-path on where the code violates the specifications. This can be integrated by re-interpreting the falsifying model from Z3 to the corresponding Imp control/data flow elements.
This project was done in collaboration with my amazing teammates:
- Adam (@mistyrainforest)
- Yuehao Hu (@yuehaohu)
An earlier version of Ivy was our submission for the final project of the graduate-level course CMPT 770 - Formal Verification at Simon Fraser University.
Happy verifying! Feel free to open issues or contribute via pull requests.