Translating Scala Programs to Isabelle/HOL

Translating Scala Programs to Isabelle/HOL

Lars Hupel, Viktor Kuncak: Translating Scala Programs to Isabelle/HOL
Paper: https://lars.hupel.info/pub/translating-scala.pdf
Presented at IJCAR 2016, Coimbra, Portugal

We present a trustworthy connection between the Leon verification system and the Isabelle proof assistant. Leon is a system for verifying functional Scala programs. It uses a variety of automated theorem provers (ATPs) to check verification conditions (VCs) stemming from the input program. This process is completely automatic: no user intervention is required for proving these conditions. Isabelle, on the other hand, is an interactive theorem prover used to verify mathematical specifications using its own input language Isabelle/Isar. Users specify (inductive) definitions and write proofs about them manually, albeit with the help of semi-automated tactics. The integration of these two system allows us to exploit Isabelle's rich standard library and give greater confidence guarantees in the correctness of analysed programs.

A1216674d5c9747bcdcc716872439137?s=128

Lars Hupel

June 30, 2016
Tweet

Transcript

  1. Translating Scala Programs to Isabelle/HOL Lars Hupel Technical University of

    Munich Viktor Kuncak École polytechnique fédérale de Lausanne June 30, 2016
  2. A Taste of Scala & Isabelle 2

  3. Scala functional & object-oriented language initially developed at EPFL by

    Martin Odersky 3
  4. Scala functional & object-oriented language initially developed at EPFL by

    Martin Odersky runs on JVM, Javascript and LLVM 3
  5. Scala functional & object-oriented language initially developed at EPFL by

    Martin Odersky runs on JVM, Javascript and LLVM strong industry support 3
  6. Scala Example sealed abstract class List[A] case class Cons[A](head: A,

    tail: List[A]) extends List[A] case class Nil[A]() extends List[A] def size[A](l: List[A]): BigInt = l match { case Nil() => BigInt(0) case Cons(_, xs) => 1 + size(xs) } 4
  7. Isabelle interactive proof assistant powerful automation 5

  8. Isabelle interactive proof assistant powerful automation classical and equational reasoning

    decision procedures (e.g. linear arithmetic) integration with external automated theorem provers ... 5
  9. Isabelle/HOL LCF tradition: small proof kernel 6

  10. Isabelle/HOL LCF tradition: small proof kernel most prominent logic: HOL

    offers commands for functional programming recursive functions, datatypes, ... are definitional 6
  11. Isabelle/HOL Example datatype α list = Nil | Cons α

    (α list) primrec size :: α list ⇒ int where size Nil = 0 | size(Cons x xs) = 1+size xs 7
  12. Isabelle/HOL Example datatype α list = Nil | Cons α

    (α list) primrec size :: α list ⇒ int where size Nil = 0 | size(Cons x xs) = 1+size xs lemma size xs ≥ 0 by(inductxs) simp+ 7
  13. Leon A Verification & Synthesis Toolkit for Scala 8

  14. Leon automated verification system for a subset of Scala 9

  15. Leon automated verification system for a subset of Scala functions

    & datatypes can be annotated with assertions (require, ensuring, assert) 9
  16. Leon automated verification system for a subset of Scala functions

    & datatypes can be annotated with assertions (require, ensuring, assert) uses SMT solvers to discharge conditions 9
  17. Leon automated verification system for a subset of Scala functions

    & datatypes can be annotated with assertions (require, ensuring, assert) uses SMT solvers Isabelle to discharge conditions 9
  18. Scala Example sealed abstract class List[A] case class Cons[A](head: A,

    tail: List[A]) extends List[A] case class Nil[A]() extends List[A] def size[A](l: List[A]): BigInt = l match { case Nil() => BigInt(0) case Cons(_, xs) => 1 + size(xs) } 10
  19. Leon Example sealed abstract class List[A] case class Cons[A](head: A,

    tail: List[A]) extends List[A] case class Nil[A]() extends List[A] def size[A](l: List[A]): BigInt = (l match { case Nil() => BigInt(0) case Cons(_, xs) => 1 + size(xs) }) ensuring(_ >= 0) 10
  20. 11

  21. Bridging the Gap 12

  22. Bridging the Gap ... but why? 12

  23. Motivation Isabelle brings a lot to the table ... 20+

    years of development 1M+ lines of libraries trustworthiness through LCF approach rich specification & proof language 13
  24. Motivation Leon brings a lot to the table ... readily-available

    verification for a wide-spread language Goal: Introduce developers to formal methods? 14
  25. Bridging the Gap 15

  26. Bridging the Gap ... with as little unverified code as

    possible 15
  27. Bridging the Gap Problem Input: Scala AST Translation: ??? Output:

    Isabelle ??? Possible solution Textual code generation 16
  28. Bridging the Gap Problem Input: Scala AST Translation: ??? Output:

    Isabelle ??? Possible solution Textual code generation FRAGILE 16
  29. Bridging the Gap Problem Input: Scala AST Translation: ??? Output:

    Isabelle API calls Reasonable solution Talk directly to Isabelle’s API 16
  30. Bridging the Gap Problem Input: Scala AST Translation: ??? Output:

    Isabelle API calls Reasonable solution Talk directly to Isabelle’s API 16
  31. Talking to Isabelle: libisabelle there is a Scala API for

    Isabelle, but it’s very low-level libisabelle is a high-level-wrapper 17
  32. Talking to Isabelle: libisabelle there is a Scala API for

    Isabelle, but it’s very low-level libisabelle is a high-level-wrapper supports multiple Isabelle versions supports multiple simultaneous processes supports Java & Scala can be used like an asynchronous RPC library setup-free 17
  33. Talking to Isabelle: libisabelle there is a Scala API for

    Isabelle, but it’s very low-level libisabelle is a high-level-wrapper supports multiple Isabelle versions supports multiple simultaneous processes supports Java & Scala can be used like an asynchronous RPC library setup-free can be used for other projects 17
  34. Talking to Isabelle: libisabelle there is a Scala API for

    Isabelle, but it’s very low-level libisabelle is a high-level-wrapper supports multiple Isabelle versions supports multiple simultaneous processes supports Java & Scala can be used like an asynchronous RPC library setup-free can be used for other projects still: manual work required 17
  35. Translating Datatypes Datatypes are almost straightforward. 18

  36. Translating Functions Scala input def size(xs: List[A]): BigInt = xs

    match { case Nil() => 0 case Cons(_, xs) => 1 + size(xs) } 19
  37. Translating Functions Scala input def size(xs: List[A]): BigInt = xs

    match { case Nil() => 0 case Cons(_, xs) => 1 + size(xs) } Isabelle output fun size xs = (case xs ofNil ⇒ 0 | Cons x xs ⇒ 1+sizexs) 19
  38. Translating Functions Scala input def size(xs: List[A]): BigInt = xs

    match { case Nil() => 0 case Cons(_, xs) => 1 + size(xs) } Ambitious Isabelle output fun size where size Nil = 0 | size(Cons x xs) = 1+size xs 19
  39. Translating Functions Scala input def size(xs: List[A]): BigInt = xs

    match { case Nil() => 0 case Cons(_, xs) => 1 + size(xs) } Ambitious Isabelle output fun size where size Nil = 0 | size(Cons x xs) = 1+size xs VERIFIED 19
  40. Evaluation 20

  41. Coverage of Leon’s Library almost complete 21

  42. Coverage of Leon’s Library almost complete ... including gnarly pattern

    matches 21
  43. Coverage of Leon’s Library almost complete ... including gnarly pattern

    matches Isabelle can prove 71% of the verification conditions automatically 21
  44. Coverage of Leon’s Library almost complete ... including gnarly pattern

    matches Isabelle can prove 71% of the verification conditions automatically missing: array, string operations 21
  45. Coverage of Leon’s Library almost complete ... including gnarly pattern

    matches Isabelle can prove 71% of the verification conditions automatically missing: array, string operations takes ≈ 40 seconds on a fast machine 21
  46. Reuse sealed abstract class List[T] { def size: BigInt =

    ... // implementation } case class Cons[T](h: T, t: List[T]) extends List[T] case class Nil[T]() extends List[T] 22
  47. Reuse @isabelle.typ(name = "List.list") sealed abstract class List[T] { @isabelle.function(term

    = "Int.int o List.length") def size: BigInt = ... // implementation } @isabelle.constructor(name = "List.list.Cons") case class Cons[T](h: T, t: List[T]) extends List[T] @isabelle.constructor(name = "List.list.Nil") case class Nil[T]() extends List[T] 22
  48. Reuse @isabelle.typ(name = "List.list") sealed abstract class List[T] { @isabelle.function(term

    = "Int.int o List.length") def size: BigInt = ... // implementation } @isabelle.constructor(name = "List.list.Cons") case class Cons[T](h: T, t: List[T]) extends List[T] @isabelle.constructor(name = "List.list.Nil") case class Nil[T]() extends List[T] VERIFIED 22
  49. Integration @proof(method = "(clarsimp, induct rule: list_induct2, auto)") def mapFstZip[A,

    B](xs: List[A], ys: List[B]) = { require(length(xs) == length(ys)) xs.zip(ys).map(_._1) } ensuring { _ == xs } 23
  50. Trustworthiness Scala and Isabelle/HOL are quite different translation is more

    intricate than we’d like it to be 24
  51. Trustworthiness Scala and Isabelle/HOL are quite different translation is more

    intricate than we’d like it to be but: just 3500 lines of code (including verified code) 24
  52. Trustworthiness Scala and Isabelle/HOL are quite different translation is more

    intricate than we’d like it to be but: just 3500 lines of code (including verified code) user doesn’t see resulting terms and definitions 24
  53. Trustworthiness Scala and Isabelle/HOL are quite different translation is more

    intricate than we’d like it to be but: just 3500 lines of code (including verified code) user doesn’t see resulting terms and definitions countermeasure: print report looks almost like an Isabelle theory can be copy-pasted into IDE 24
  54. Conclusion prove Scala code correct with high assurance co-develop specifications

    in Isabelle and Scala zero setup required, integrates seamlessly groundwork for using Isabelle as an API has been laid 25
  55. Q & A 26