program synthesis with jennisys k. rustan m. leino research in software engineering (rise),...
TRANSCRIPT
Program synthesis with Jennisys
K. Rustan M. LeinoResearch in Software Engineering (RiSE), Microsoft Research, Redmond
Aleksandar MilicevicMIT
IFIP Working Group 2.3 meetingWinchester, UK22 September 2011
Post-mortem verification
TimelineIdea
CodeTest Verifi
catio
n
Ouch!
Need
specifications
Forward-looking design
More help during software designMore expressive languages
RefinementSynthesis…
This is where programs begin
Jennisys
Jennisys programs
Each type has:Public interfaceData modelCode
Example: Public interfaceinterface ExtensibleArray[T] { var Contents: seq[T] constructor Init() Contents := [] method Get(i) returns (t) requires 0 <= i && i < |Contents| t := Contents[i] method Set(i, t) requires 0 <= i && i < |Contents| Contents := Contents[i := t] method Append(t) Contents := Contents + [t]}
ExtensibleArray data structure
Extensible-
Array[T]
Append( )
.elements
ExtensibleArray data structure
Extensible-
Array[T]
Append( )
.elements
ExtensibleArray data structure
Extensible-
Array[T]
Append( )
.elements
ExtensibleArray data structure
Extensible-
Array[T]
Append( )
.elements
.more
ExtensibleArray data structure
Extensible-
Array[T] .elements
.more
ExtensibleArray
[array[T]]
Example: Data structure designdatamodel ExtensibleArray[T] {
var elements: array[T] var more: ExtensibleArray[array[T]] frame elements, more, more.Contents[*] invariant elements.Length = 256 256 < |Contents| ==> more != null more.Contents[*].Length = 256 val M = if more = null then 0 else 256 * |more.Contents| Contents[i] = elements[i – M] where i in M <= i Contents[i] = more.Contents[i / 256][i % 256] where i in i < M}
Example: Data structure designdatamodel ExtensibleArray<T> {
var elements: array<T> var more: ExtensibleArray<array<T>>? frame elements, more, more.Contents[*] invariant elements.Length = 256 256 < |Contents| ==> more != null more.Contents[*].Length = 256 val M = if more = null then 0 else 256 * |more.Contents| Contents[i] = elements[i – M] where i in M <= i Contents[i] = more.Contents[i / 256][i % 256] where i in i < M}
Can all operations be
implemented with
this design?
Example: Data structure designdatamodel ExtensibleArray<T> {
var elements: array<T> var more: ExtensibleArray<array<T>>? frame elements, more, more.Contents[*] invariant elements.Length = 256 256 < |Contents| ==> more != null more.Contents[*].Length = 256 val M = if more = null then 0 else 256 * |more.Contents| Contents[i] = elements[i – M] where i in M <= i Contents[i] = more.Contents[i / 256][i % 256] where i in i < M}
Is this good?|Contents| = 5more ≠ null|more.Contents| = 100
Example: Implementation
code ExtensibleArray[T] {
}Code is
generated
from public
interface and
data modelCode generated automaticallyProgrammer supplies hints
E.g., “loop n”, “e[n] := t”Programmer uses sketches, holes[Bodik, Solar-Lezama, …]
As last resort, code is written manually
Jennisys, abstractlyinterface T {
var aconstructor
Init()S(a)
}
datamodel T {var cinvariant R(a,
c)}
Jennisys, abstractlyinterface T {
var aconstructor
Init()a := E
}
datamodel T {var cinvariant R(a,
c)}
Synthesis basics:
Constraint solvinginterface T {
var aconstructor
Init()a := E
}
datamodel T {var cinvariant R(a,
c)}
var a, c
a := Ec :[ R(a, c) ]
constraint solve to find feasible a,c
here
Synthesis basics:
Constraint solvinginterface T {
var aconstructor
Init()a := E
}
datamodel T {var cinvariant R(a,
c)}
var a, c
a := Eassume R(a, c)assert false
attempt to verify and look
at resulting counterexampl
e model
a := 0 with a = ca := 0 with a = c+d
Demo
Extrapolationinterface T {
var aconstructor
Init(p)a := E(p)
}
datamodel T {var cinvariant R(a, c)
}
Constraint solving gives possible values for a,p,c
From this, we want to extrapolate a value for c in terms of p
Extrapolation: Exampleinterface T {
var aconstructor
Init(p)a := p
}
datamodel T {var cinvariant a = c
}
Sample values:a=7, p=7, c=7
Match up c with p
Custom spec evaluationinterface T {
var aconstructor
Init(p,q)a := {p + q}
}
datamodel T {var cinvariant a = {c}
}
Partially evaluate spec with the sample values for non-parameters
Match things upa={7}, p=3, q=4,
c=7
{7} = {p+q}, {7} = {7}
a := p+q with a = ca := {p+q} with a = {c}
Demo
Program extrapolation, so far
Constraint solving: get sample valuesPartial evaluation: simplify spec using samples valuesUnification: match things up
What if it doesn’t work?
Inferring branch structure
Program extrapolationAttempt to verifyIf resulting program does not verify:
Infer the needed guard using custom spec evaluationRepeat synthesis for remaining cases
Branch structure: Exampleinterface T {
var aconstructor
Init(p,q)a := {p, q}
} datamodel T {
var c, dinvariant a =
{c,d} c ≤ d
}
a={7}, p=3, q=4, c=3, d=4
Match c,d with p,qWorks only if p≤qGenerate ifRepeat assuming ¬(p≤q)
if (p≤q) {c,d := p,q
} else {c,d := q,p
}
Objects
Each interface denotes an instantiable type, that is, a class of objectsA data model can also make use of objects
SimpleCell
Demo
Delegation
An interface has model fieldspart of the specificationnot part of compiled code
If type X uses objects of type Y, its code should:
not set Y’s model fields directly, butuse Y’s interface to call constructors and methods to achieve the desired result
ConclusionsSynthesis by combination of:
Constraint solvingSymbolic/concrete evaluationUnification
More to do:MethodsFormalization, better understand the technique…
Reflection:Is this how we should be programming?