LARA

Labs 01: Stainless

In this first lab, you will use Stainless (https://github.com/epfl-lara/stainless) to verify programs.

Preparation

Install the latest release of Stainless (v0.7.3 at the time of the writing). The release is an archive containing among other things a binary called stainless, that you should make available in your path. Instructions are available in this short video. Make sure that you are using Java 8 (there might be issues with other versions of Java). On some Linux distributions, you can use sudo update-alternatives –config java to change versions.

Note for Windows users

As Stainless currently does not work out of the box on Windows, we advise you to run it with either the Windows Subsystem for Linux or a virtual machine running Linux. It may also work with something like Cygwin but this has not been tested yet.

Deliverable

Upload your solutions on Moodle by ?? at 23:59.

The code below defines a relation on lists, which holds when the first list can be embedded in the second list. The goal is to prove basic properties on this relation, such as reflexivity, transitivity, and antisymmetry. More precisely, you should make Stainless accept the seven lemmas defined in the code.

To familiarize yourself with Stainless, you can have a look at this tutorial:

import stainless.collection._
import stainless.lang._
import stainless.annotation._
 
object SubList {
 
  def subList[T](l1: List[T], l2: List[T]): Boolean = (l1, l2) match {
    case (Nil(), _)                 => true
    case (_, Nil())                 => false
    case (Cons(x, xs), Cons(y, ys)) => (x == y && subList(xs, ys)) || subList(l1, ys)
  }
 
  def subListRefl[T](l: List[T]): Unit = {
 
  }.ensuring(_ =>
    subList(l, l)
  )
 
  def subListTail[T](l1: List[T], l2: List[T]): Unit = {
    require(!l1.isEmpty && subList(l1, l2))
 
  }.ensuring(_ =>
    subList(l1.tail, l2)
  )
 
  def subListTails[T](l1: List[T], l2: List[T]): Unit = {
    require(!l1.isEmpty && !l2.isEmpty && l1.head == l2.head && subList(l1, l2))
 
  }.ensuring(_ =>
    subList(l1.tail, l2.tail)
  )
 
  def subListTrans[T](l1: List[T], l2: List[T], l3: List[T]): Unit = {
    require(subList(l1, l2) && subList(l2, l3))
 
  }.ensuring(_ =>
    subList(l1, l3)
  )
 
  def subListLength[T](l1: List[T], l2: List[T]): Unit = {
    require(subList(l1, l2))
 
  }.ensuring(_ =>
    l1.length <= l2.length
  )
 
  def subListEqual[T](l1: List[T], l2: List[T]): Unit = {
    require(subList(l1, l2) && l1.length >= l2.length)
 
  }.ensuring(_ =>
    l1 == l2
  )
 
  def subListAntisym[T](l1: List[T], l2: List[T]): Unit = {
    require(subList(l1, l2) && subList(l2, l1))
 
  }.ensuring(_ =>
    l1 == l2
  )
 
}