Slide 1

Slide 1 text

Transla ng Scala programs to Isabelle with Leon Lars Hupel Technische Universität München September 8, 2015

Slide 2

Slide 2 text

Isabelle ▶ interactive proof assistant ▶ powerful automation ▶ classical and equational reasoning ▶ decision procedures (e.g. linear arithmetic) ▶ integration with external automated theorem provers ▶ ... ▶ based on a generic core logic 2 / 28

Slide 3

Slide 3 text

Structure of an Isabelle theory System perspec ve ▶ foundational unit of knowledge in Isabelle is a theory ▶ a command transforms a theory: theory → theory ▶ theories can be merged: theory → theory → theory ▶ theories can be extended by (primitive) value and type definitions ▶ everything else needs to be constructed 3 / 28

Slide 4

Slide 4 text

Structure of an Isabelle theory User perspec ve theory Words imports Bits Bool List begin typedef word = {x :: int | 0 ≤ x ∧ x < 232} definition word of int :: int → word where . . . lemma . . . end 4 / 28

Slide 5

Slide 5 text

Extensibility ▶ Isabelle’s core logic doesn’t support much ▶ however, users can define their own commands and own syntax ▶ the most prominent logic (HOL) is defined in user-space ▶ including commands for functional programming 5 / 28

Slide 6

Slide 6 text

Func onal Programming in Isabelle Datatypes datatype α list = Nil | Cons α (α list) This specification introduces: ▶ an induction principle ▶ a recursor rec list :: α → (β → β list → α → α) → β list → α ▶ ... a lot more 6 / 28

Slide 7

Slide 7 text

Func onal Programming in Isabelle Datatypes datatype α list = Nil | Cons α (α list) This specification is ... ▶ checked for wellformedness and inhabitants ▶ datatype α tree = Node (α tree set) is not admitted ▶ not axiomatic, but constructed! ▶ solution of the equation: τ = unit + (α × τ) 6 / 28

Slide 8

Slide 8 text

Func onal Programming in Isabelle Func ons ▶ definition principle of the logic: x def = λy1 . . . yn . t ▶ ... introduces a new constant and an axiom ▶ but: t must not depend on x itself ▶ primrec defines a function over a datatype using its recursor ▶ fun allows more flexible recursion, but need to prove termination 7 / 28

Slide 9

Slide 9 text

Example Defini ons datatype α list = Nil | Cons α (α list) primrec length :: α list → int where length Nil = 0 length (Cons x xs) = 1 + length xs 8 / 28

Slide 10

Slide 10 text

Example Defini ons datatype α list = Nil | Cons α (α list) primrec length :: α list → int where length Nil = 0 length (Cons x xs) = 1 + length xs Proofs lemma length xs ≥ 0 by (induct xs) simp+ 8 / 28

Slide 11

Slide 11 text

Func onal Programming in Scala more specifically: Leon’s subset of Scala ▶ OOP-style datatypes ▶ methods ▶ pattern matching with guards and type casing ▶ generics 9 / 28

Slide 12

Slide 12 text

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 length(xs: List[A]): BigInt = xs match { case Nil() => 0 case Cons(_, xs) => 1 + length(xs) } ensuring { _ >= 0 } 10 / 28

Slide 13

Slide 13 text

Isabelle as a solver in Leon Isabelle has two modes of operation: interac ve user types code into the IDE, checked continuously batch command line process checks a list of source files once Batch mode is comparable to most compilers 11 / 28

Slide 14

Slide 14 text

Isabelle as a solver in Leon Problems ▶ starting up an Isabelle process takes a couple of seconds ▶ Leon creates a solver instance for each verification condition ▶ an Isabelle batch process cannot be reused 12 / 28

Slide 15

Slide 15 text

Isabelle as a solver in Leon Problems ▶ starting up an Isabelle process takes a couple of seconds ▶ Leon creates a solver instance for each verification condition ▶ an Isabelle batch process cannot be reused Solu on ▶ use the interactive mode ▶ create one instance when Leon starts, reuse it 12 / 28

Slide 16

Slide 16 text

Bridging the gap Mantra: as little unverified code as possible 13 / 28

Slide 17

Slide 17 text

Bridging the gap Problem ▶ Input: Leon (≈ Scala) AST ▶ Translation: ??? ▶ Output: Isabelle ??? 14 / 28

Slide 18

Slide 18 text

Bridging the gap Problem ▶ Input: Leon (≈ Scala) AST ▶ Translation: ??? ▶ Output: Isabelle ??? Possible solu on Textual code generation! 14 / 28

Slide 19

Slide 19 text

Bridging the gap Problem ▶ Input: Leon (≈ Scala) AST ▶ Translation: ??? ▶ Output: Isabelle ??? Be er solu on Talk directly to Isabelle’s API 14 / 28

Slide 20

Slide 20 text

Bridging the gap Problem ▶ Input: Leon (≈ Scala) AST ▶ Translation: ??? ▶ Output: Isabelle ??? Be er solu on Talk directly to Isabelle’s API ... except I have to implement the API myself 14 / 28

Slide 21

Slide 21 text

Talking to Isabelle ▶ there is a Scala API for Isabelle, but it’s very low-level ▶ I’ve implemented a high-level wrapper: libisabelle ▶ supports multiple Isabelle versions ▶ supports multiple simultaneous processes ▶ can be used like an asynchronous RPC library ▶ downloads and installs Isabelle automatically 15 / 28

Slide 22

Slide 22 text

Isabelle API 16 / 28

Slide 23

Slide 23 text

Transla on from Scala to Isabelle Datatypes Datatypes are almost straightforward. 17 / 28

Slide 24

Slide 24 text

Transla on from Scala to Isabelle Func ons Functions are quite complicated. 18 / 28

Slide 25

Slide 25 text

Transla ng func ons Scala input def length(xs: List[A]): BigInt = xs match { case Nil() => 0 case Cons(_, xs) => 1 + length(xs) } 19 / 28

Slide 26

Slide 26 text

Transla ng func ons Scala input def length(xs: List[A]): BigInt = xs match { case Nil() => 0 case Cons(_, xs) => 1 + length(xs) } Naive Isabelle output definition length xs = (case xs of Nil ⇒ 0 | Cons x xs ⇒ 1 + length xs) 19 / 28

Slide 27

Slide 27 text

Transla ng func ons Scala input def length(xs: List[A]): BigInt = xs match { case Nil() => 0 case Cons(_, xs) => 1 + length(xs) } Ambi ous Isabelle output fun length xs = (case xs of Nil ⇒ 0 | Cons x xs ⇒ 1 + length xs) 19 / 28

Slide 28

Slide 28 text

Transla ng func ons Scala input def length(xs: List[A]): BigInt = xs match { case Nil() => 0 case Cons(_, xs) => 1 + length(xs) } Desired Isabelle output fun length where length Nil = 0 length (Cons x xs) = 1 + length xs 19 / 28

Slide 29

Slide 29 text

Recursive func ons ▶ detecting whether a function is recursive or not: trivial ▶ pick either fun or defini on ▶ but: mutually recursive functions must be defined together ▶ ... without any additional functions 20 / 28

Slide 30

Slide 30 text

Transla ng func ons Algorithm for recursive func ons 1. compute strongly connected components of call graph 2. define functions of each components together, using case expressions 3. postprocess into implicit pattern matching 4. obtain better induction principle This procedure takes ≈ 40 seconds on a fast machine for the Leon library. 21 / 28

Slide 31

Slide 31 text

Transla ng type informa on ▶ “best effort” approach ▶ in Isabelle, each atomic term stores its fully instantiated type ▶ except bound variables: types stored in enclosing term ▶ Example: f x1 x2 . . . ▶ f contains the types of the xi ▶ leave out redundant information, rely on type inference for the rest 22 / 28

Slide 32

Slide 32 text

Further issues Binders Issue Isabelle’s term language uses de Bruijn indices Solu on ▶ keep track of identifiers when recursing through binders ▶ caveat: open terms cannot be type checked 23 / 28

Slide 33

Slide 33 text

Further issues Pa ern matching Issue Isabelle’s pattern matching is just syntactic sugar Example Syntax case xs of Nil ⇒ 0 | Cons x xs ⇒ 1 + length xs Term case list 0 (λx xs. 1 + length xs) xs Solu on ▶ use Isabelle’s built-in translations ▶ but: clauses need to be type checked ▶ when pattern matching under binders, invent dummy variables 24 / 28

Slide 34

Slide 34 text

Further issues Pa ern matching Issue Isabelle requires unambiguous patterns Example case xs of Cons x xs ⇒ . . . | xs ⇒ . . . 25 / 28

Slide 35

Slide 35 text

Further issues Pa ern matching Issue Isabelle requires unambiguous patterns Example case xs of Cons x xs ⇒ . . . | xs ⇒ . . . “I have some experience with the combinatorial explosion [...] You don’t need much: just take extended regular expressions (≈ 10 constructors) and define binary normalizing constructors (by some sequential pattern matching on both arguments). [...] is full of ≈ 30 sec [function] declarations.” 25 / 28

Slide 36

Slide 36 text

Further issues Unsupported constructs Issue What to do with unsupported Leon constructs? Solu on ▶ in Isabelle’s logic, every type is inhabited ▶ unspecified constant undefined :: α ▶ but: reflexivity holds ▶ trick: use undefined with an additional unique number 26 / 28

Slide 37

Slide 37 text

Trustworthiness ▶ Scala and Isabelle/HOL are quite different ▶ translation is more intricate than I’d like it to be ▶ user doesn’t see resulting terms and definitions ▶ countermeasure: print report ▶ looks almost like an Isabelle theory ▶ can be copy-pasted into IDE ▶ option: dump full-blown files 27 / 28

Slide 38

Slide 38 text

Q & A