Lab 02 : An introduction to Leon's codebase
In this lab, you will start working on the Leon codebase directly. You will have to implement a series of simple tasks that will introduce you to the important classes and structures of the Leon verification system.
Please follow the instructions on Labs Setup to get started on this lab.
If you really, really, want to use Eclipse, follow these instructions: Eclipse Instructions.
A tour of Leon
Once you cloned your git repository you will find a rather big project. Here we will give you some information about the most important classes and packages that you will need to explore:
The sources can be found in src/main/scala/leon
, under which you will find:
Main.scala
: Entry point of Leon. Creates the pipeline and process some options.purescala/
: Definition of all pureScala Trees and operations on the trees.solvers/
: Definition and implementation of Solvers for Leon trees.verification/
: Construction of VCs for the verification of programs.sav/
: Definitions of the phase that we will work with here.
During this lab, you will spend most of your time working with classes from the purescala
and sav
packages.
The System
Leon works using a pipeline of phases. Each phase can be seen as a function from Input to Output. For instance, the phase compiling the script given as argument to a Leon Tree is the plugin.ExtractionPhase
, and its signature is List[String] ⇒ Program
.
For this lab, we will plug our SAV phase directly after this. Our phase will perform transformations, so it is defined as Program ⇒ Program
.
We can see this pipeline Main.scala's computePipeline
:
plugin.ExtractionPhase andThen sav.SAVPhase
If you run Leon with this pipeline, you will see the resulting program in the output. If we wish to perform verification after the SAV transformations, we can extend this pipeline using:
plugin.ExtractionPhase andThen sav.SAVPhase andThen verification.AnalysisPhase
The Trees
Leon builds its own trees out of Scala ASTs. The definitions of these trees can be found in the purescala
package: trees representing programs or functions declarations are found in purescala/Definitions.scala
. You can for instance find the definition for the Program
class there, which is given as input to your SAV phase.
The expression trees are defined in the purescala/Trees.scala
file. They represent purely function programs. Leon unifies programs and formulae by handling them using the same trees.
Another very important file is purescala/TreeOps.scala
which contains all kinds of operations on trees, including substitution, lookups, transformations, catamorphisms, …
Compiling Leon
You will need sbt 0.12.1 in order to compile Leon. You can either install this specific version of sbt, or use the https://github.com/paulp/sbt-extras package which simplifies this task, by auto-detecting and running the correct sbt version. Once sbt or sbt-extras is installed, compile Leon using:
$ sbt compile script
This should compile Leon and create two scripts, leon
and setupenv
. You should now be able to run Leon using:
$ ./leon --help
The Assignment
In this assignment you will work with Leon trees and perform several modifications to them. You are encouraged to look in the purescala
package for functions that may help you implement the desired functionality.
Part 1: Check for Recursion
Implement the function isRecursive(fi: FunctionInvocation)
in SAVPhase that checks whether the call is made to a function that is recursive.
Part 2: Inlining
Inlining consists of replacing the call to a function by its body. Implement the inline(fi: FunctionInvocation)
function in SAVPhase that returns the inlined code corresponding to the function call.
You can ignore potential pre/post conditions.
Part 3: Simplify Arithmetic Expressions
Implement the function simplifyArith(in: Expr)
in SAVPhase that should look for arithmetic expressions and simplify them when possible.
Kinds of simplifications you will have to implement:
1*v
⇒v
0*x
⇒0
v/1
⇒v
v+0
⇒v
v-0
⇒v
42+42
⇒84
or any kind of arithmetic static computations.(0 == 1)
⇒false
For this you will have to implement a tree transformer, take a close look to TreeOps functions simplePreTransform
and simplePostTransform
, and how they can be used.
Part 4: Automated Inlining
Implement the autoInline(in: Expr)
function. This function should inline all function calls to non-recursive functions found in in
and return the updated code.
Once this function is implemented, you will need to traverse all the defined functions in the Program and apply autoInline
to all defined bodies. Note that this inlining should be done transitively on all non-recursive calls. Return the resulting Program as result of the phase.
Deliverables
Deadline: Friday, Mar. 8th, 23.59pm.
You must use the interface on http://larasrv05.epfl.ch/sav13 as follows:
- Click on the “Deliverables” tab
- Click “Deliver this version” on the commit hash corresponding to the version of your code you want to submit
- In the dialog, make sure “Lab02 - Introduction” is selected, write a comment if you want
- Click on “Create Deliverable”
Note: You can deliver as many times as you want, we will only consider the last deliverable.