Date post: | 01-Apr-2015 |
Category: |
Documents |
Upload: | jenifer-peak |
View: | 213 times |
Download: | 0 times |
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?