Synthesizing and Repairing Expressions using Types and Weights

64
Synthesizing and Repairing Expressions using Types and Weights Tihomir Gvero, Viktor Kuncak, Ivan Kuraj and Ruzica Piskac 1

description

Synthesizing and Repairing Expressions using Types and Weights. Tihomir Gvero, Viktor Kuncak , Ivan Kuraj and Ruzica Piskac. Motivation. Large APIs and libraries classes in Java 6.0 standard library Using those APIs (for the first time) can be Tedious Time consuming - PowerPoint PPT Presentation

Transcript of Synthesizing and Repairing Expressions using Types and Weights

Page 1: Synthesizing and Repairing Expressions using Types and Weights

1

Synthesizing and Repairing Expressions using Types and

WeightsTihomir Gvero, Viktor Kuncak, Ivan Kuraj and Ruzica Piskac

Page 2: Synthesizing and Repairing Expressions using Types and Weights

2

Motivation

• Large APIs and libraries classes in Java 6.0 standard library

• Using those APIs (for the first time) can be • Tedious• Time consuming

• Developers should focus on solving creative tasks • Manual Solution

• Read Documentation• Inspect Examples

• Automation = Code synthesis + Code completion

Page 3: Synthesizing and Repairing Expressions using Types and Weights

3

Our Solution• InSynth: Interactive Synthesis of Code Snippets• Input:

• Scala partial program• Cursor point

• We automatically extract: • Declarations in scope (with/without statistics from corpus)• Desired type

• Algorithm• Complete• Efficient – output N expressions in less than T ms• Effective – favor useful expressions over obscure ones• Generates expressions with higher order functions

• Output• Ranked list of expressions

Page 4: Synthesizing and Repairing Expressions using Types and Weights

4

def main(args:Array[String]) = { var body:String = "email.txt" var sig:String = "signature.txt" var inStream:SeqInStr = …}

Sequence of Streams

Page 5: Synthesizing and Repairing Expressions using Types and Weights

5

def main(args:Array[String]) = { var body:String = "email.txt" var sig:String = "signature.txt" var inStream:SeqInStr = …}

Sequence of Streams

new SeqInStr(new FileInStr(sig), new FileInStr(sig))new SeqInStr(new FileInStr(sig), new FileInStr(body))new SeqInStr(new FileInStr(body), new FileInStr(sig))new SeqInStr(new FileInStr(body), new FileInStr(body))new SeqInStr(new FileInStr(sig), System.in)

Page 6: Synthesizing and Repairing Expressions using Types and Weights

6

def main(args:Array[String]) = { var body:String = "email.txt" var sig:String = "signature.txt" var inStream:SeqInStr = …}

Sequence of Streams

new SeqInStr(new FileInStr(sig), new FileInStr(sig))new SeqInStr(new FileInStr(sig), new FileInStr(body))new SeqInStr(new FileInStr(body), new FileInStr(sig))new SeqInStr(new FileInStr(body), new FileInStr(body))new SeqInStr(new FileInStr(sig), System.in)

Page 7: Synthesizing and Repairing Expressions using Types and Weights

7

def main(args:Array[String]) = { var body:String = "email.txt" var sig:String = "signature.txt" var inStream:SeqInStr = new SeqInStr(new FileInStr(sig), new FileInStr(body)) …}

Sequence of Streams

Page 8: Synthesizing and Repairing Expressions using Types and Weights

8

def main(args:Array[String]) = { var body:String = "email.txt" var sig:String = "signature.txt" var inStream:SeqInStr = new SeqInStr(new FileInStr(sig), new FileInStr(body)) …}

Sequence of Streams

Imported over 3300 declarations

Executed in less than 250ms

Page 9: Synthesizing and Repairing Expressions using Types and Weights

9

def filter(p: Tree => Boolean): List[Tree] = { val ft:FilterTreeTraverser = ft.traverse(tree) ft.hits.toList}

TreeFilter (HOF)

Page 10: Synthesizing and Repairing Expressions using Types and Weights

10

def filter(p: Tree => Boolean): List[Tree] = { val ft:FilterTreeTraverser = ft.traverse(tree) ft.hits.toList}

TreeFilter (HOF)

new FilterTreeTraverser(x => p(x))new FilterTreeTraverser(x => isType)new FilterTreeTraverser(x => p(tree))new FilterTreeTraverser(x => new Wrapper(x).isType)new FilterTreeTraverser(x => p(new Wrapper(x).tree))

Page 11: Synthesizing and Repairing Expressions using Types and Weights

11

def filter(p: Tree => Boolean): List[Tree] = { val ft:FilterTreeTraverser = ft.traverse(tree) ft.hits.toList}

TreeFilter (HOF)

new FilterTreeTraverser(x => p(x))new FilterTreeTraverser(x => isType)new FilterTreeTraverser(x => p(tree))new FilterTreeTraverser(x => new Wrapper(x).isType)new FilterTreeTraverser(x => p(new Wrapper(x).tree))

Page 12: Synthesizing and Repairing Expressions using Types and Weights

12

def filter(p: Tree => Boolean): List[Tree] = { val ft:FilterTreeTraverser = new FilterTreeTraverser(x => p(x)) ft.traverse(tree) ft.hits.toList}

TreeFilter (HOF)

Page 13: Synthesizing and Repairing Expressions using Types and Weights

13

def filter(p: Tree => Boolean): List[Tree] = { val ft:FilterTreeTraverser = new FilterTreeTraverser(x => p(x)) ft.traverse(tree) ft.hits.toList}

TreeFilter (HOF)

Imported over 4000 declarations

Executed in less than 300ms

Page 14: Synthesizing and Repairing Expressions using Types and Weights

14

COMPLETION = INHABITATION

Page 15: Synthesizing and Repairing Expressions using Types and Weights

15

COMPLETION = INHABITATION

val a: T = ?

def m1: T1

…def mn: Tn

Page 16: Synthesizing and Repairing Expressions using Types and Weights

16

COMPLETION = INHABITATION

val a: T = ?

def m1: T1

…def mn: Tn G={ m1: T1,…, mn: Tn}

Page 17: Synthesizing and Repairing Expressions using Types and Weights

17

COMPLETION = INHABITATION

val a: T = ?

def m1: T1

…def mn: Tn G={ m1: T1,…, mn: Tn}

ENVIRONMENT

Page 18: Synthesizing and Repairing Expressions using Types and Weights

18

COMPLETION = INHABITATION

val a: T = ? G ⊢ ? : T

def m1: T1

…def mn: Tn G={ m1: T1,…, mn: Tn}

ENVIRONMENT

Page 19: Synthesizing and Repairing Expressions using Types and Weights

19

COMPLETION = INHABITATION

val a: T = ? G ⊢ ? : T

def m1: T1

…def mn: Tn G={ m1: T1,…, mn: Tn}

DESIRED TYPE

ENVIRONMENT

Page 20: Synthesizing and Repairing Expressions using Types and Weights

20

Simply Typed Lambda Calculus

G ⊢ x : TAX

x : T G

G ⊢ e1(e2) : TAPP

G ⊢ e1 : T1T G e⊢ 2 : T1

G ⊢ λx.t : T1 TABS

G, x : T1 ⊢ t : T

Page 21: Synthesizing and Repairing Expressions using Types and Weights

21

Simply Typed Lambda Calculus

Page 22: Synthesizing and Repairing Expressions using Types and Weights

22

Simply Typed Lambda Calculus

G ⊢ ? : T

Page 23: Synthesizing and Repairing Expressions using Types and Weights

23

Simply Typed Lambda Calculus

G ⊢ ? : T

Backward Search

Page 24: Synthesizing and Repairing Expressions using Types and Weights

24

Simply Typed Lambda Calculus

G ⊢ ? : TAPP

G ⊢ ? : T1T G ⊢ ? : T1

Page 25: Synthesizing and Repairing Expressions using Types and Weights

25

Simply Typed Lambda Calculus

G ⊢ ? : TAPP

G ⊢ ? : T1T G ⊢ ? : T1

Infinitely many

Page 26: Synthesizing and Repairing Expressions using Types and Weights

26

Simply Typed Lambda Calculus

G ⊢ ? : TAPP

G ⊢ ? : T1T G ⊢ ? : T1

Infinitely many

No bound on types in derivation tree(s).

Page 27: Synthesizing and Repairing Expressions using Types and Weights

27

G ⊢ f(a1,…,an):TAPP

f : T1…TnT G G a⊢ 1: T1 … G a⊢ n: Tn

G ⊢ λ x1:T1 ,…, xn:Tn.t: T1 … Tn TABS

G, x1:T1 ,…, xn:Tn t: T⊢

Long Normal Form

Page 28: Synthesizing and Repairing Expressions using Types and Weights

28

G ⊢ f(a1,…,an):TAPP

f : T1…TnT G G a⊢ 1: T1 … G a⊢ n: Tn

G ⊢ e1(e2) : TAPP

G ⊢ e1 : T1T G e⊢ 2 : T1

Comparison between LNF and classic APPOLD

NEW

Page 29: Synthesizing and Repairing Expressions using Types and Weights

29

G ⊢ f(a1,…,an):TAPP

f : T1…TnT G G a⊢ 1: T1 … G a⊢ n: Tn

G ⊢ e1(e2) : TAPP

G ⊢ e1 : T1T G e⊢ 2 : T1

We derive EXPRESSION from G

Comparison between LNF and classic APP

Page 30: Synthesizing and Repairing Expressions using Types and Weights

30

G ⊢ f(a1,…,an):TAPP

f : T1…TnT G G a⊢ 1: T1 … G a⊢ n: Tn

G ⊢ e1(e2) : TAPP

G ⊢ e1 : T1T G e⊢ 2 : T1

We derive EXPRESSION from G

DECLARATION from G

Comparison between LNF and classic APP

Page 31: Synthesizing and Repairing Expressions using Types and Weights

31

Long Normal Form

Page 32: Synthesizing and Repairing Expressions using Types and Weights

32

Long Normal Form

G ⊢ ? :T

Page 33: Synthesizing and Repairing Expressions using Types and Weights

33

Long Normal Form

APPf : (T1 T2)T G G ⊢ ? : T1 T2

G ⊢ f(?):T

Page 34: Synthesizing and Repairing Expressions using Types and Weights

34

Long Normal Form

APPf : (T1 T2)T G G ⊢ ? : T1 T2

Only one

G ⊢ f(?):T

Narrows the search space

Page 35: Synthesizing and Repairing Expressions using Types and Weights

35

Long Normal Form

APPf : (T1 T2)T G G ⊢ λ x1:T1.? : T1 T2

G, x1:T1 ? : T⊢ 2

ABS

G ⊢ f(λ x1:T1.?):T

Page 36: Synthesizing and Repairing Expressions using Types and Weights

36

Long Normal Form

APPf : (T1 T2)T G G ⊢ λ x1:T1.e : T1 T2

G, x1:T1 e : T⊢ 2

. . . .

ABS

APP

G ⊢ f(λ x1:T1.e):T

Page 37: Synthesizing and Repairing Expressions using Types and Weights

37

Long Normal Form

APPf : (T1 T2)T G G ⊢ λ x1:T1.e : T1 T2

G, x1:T1 e : T⊢ 2

. . . .

ABS

APP

Finitely many types in derivation tree(s)

G ⊢ f(λ x1:T1.e):T

Page 38: Synthesizing and Repairing Expressions using Types and Weights

38

Algorithm• Algorithm builds finite graph (with cycles) that

• Represents all (infinitely many) solutions• Later we use it to construct expressions• Less than 10ms

• Algorithm Properties• Graph generation terminates

• Type inhabitation is decidable• Complete - generates all solutions• PSPACE-complete

• Techniques• Succinct type representation• Backward search• Weights mechanism

Page 39: Synthesizing and Repairing Expressions using Types and Weights

39

Weights and Corpus• Weight of a declaration based on:

• Frequency • Corpus based on 18 Scala projects (e.g. Scala compiler)• Over 7500 declarations, and over 90000 uses• Higher the frequency, lower the weight

• Proximity

Local symbolsMethod and field symbols

API symbols

Low High

Page 40: Synthesizing and Repairing Expressions using Types and Weights

40

Algorithm with Weights

APPf : (T1 T2)T G G ⊢ λ x1:T1.e : T1 T2

G, x1:T1 e : T⊢ 2

. . . .

ABS

APP

G ⊢ f(λ x1:T1.e):T

Page 41: Synthesizing and Repairing Expressions using Types and Weights

41

Algorithm with Weights

APPf : (T1 T2)T G G ⊢ λ x1:T1.e : T1 T2

G, x1:T1 e : T⊢ 2

. . . .

ABS

APP

G ⊢ f(λ x1:T1.e):T

Choice based on WEIGHT

Page 42: Synthesizing and Repairing Expressions using Types and Weights

42

Algorithm with Weights

APPf : (T1 T2)T G G ⊢ λ x1:T1.e : T1 T2

G, x1:T1 e : T⊢ 2

. . . .

ABS

APP

G ⊢ f(λ x1:T1.e):T

Choice based on WEIGHT

Ranking based on w(f(λ x1:T1.e)) = w(f) + w(x1) + w(e)

Page 43: Synthesizing and Repairing Expressions using Types and Weights

43

Benchmarks

• 50 Java examples translated into Scala• Illustrate correct usage of API functions

• We generalized the import statements • To include more declarations

• In every example:1. Arbitrarily chose some expression2. Removed it 3. Marked it as goal expression4. Measure whether InSynth can recover it

Page 44: Synthesizing and Repairing Expressions using Types and Weights

44

Results

• Without weights expected expression appears • Among top 10 suggestions in only 4 benchmarks (8%)

• With weights (only proximity)• Among top 10 suggestions in 48 benchmarks (96%)• As a top suggestion in 26 benchmarks (52%)

• With weights (proximity + frequency)• Among top 10 suggestions in 48 benchmarks (96%)• As a top suggestion in 32 benchmarks (64%)

• Average execution time 145ms

Page 45: Synthesizing and Repairing Expressions using Types and Weights

45

def main(args:Array[String]) = { var body:String = "email.txt" var sig:String = "signature.txt" var inStream:SeqInStr = …}

Sequence of Streams

Page 46: Synthesizing and Repairing Expressions using Types and Weights

46

def main(args:Array[String]) = { var body:String = "email.txt" var sig:String = "signature.txt" var inStream:SeqInStr = new SeqInStr( sig, body) …}

Sequence of Streams

Page 47: Synthesizing and Repairing Expressions using Types and Weights

47

def main(args:Array[String]) = { var body:String = "email.txt" var sig:String = "signature.txt" var inStream:SeqInStr = new SeqInStr( sig, body) …}

Sequence of StreamsUser Writes

Page 48: Synthesizing and Repairing Expressions using Types and Weights

48

def main(args:Array[String]) = { var body:String = "email.txt" var sig:String = "signature.txt" var inStream:SeqInStr = new SeqInStr( sig, body) …}

// new SeqInStr: FileInStr FileInStr SeqInStr

Sequence of Streams

Type Mismatch

Page 49: Synthesizing and Repairing Expressions using Types and Weights

49

def main(args:Array[String]) = { var body:String = "email.txt" var sig:String = "signature.txt" var inStream:SeqInStr = new SeqInStr( sig, body) …}

We propose polynomial algorithm that finds the best repair

// new SeqInStr: FileInStr FileInStr SeqInStr

Sequence of Streams

Type Mismatch

Page 50: Synthesizing and Repairing Expressions using Types and Weights

50

def main(args:Array[String]) = { var body:String = "email.txt" var sig:String = "signature.txt" var inStream:SeqInStr = new SeqInStr( sig, body) …}

// new SeqInStr: FileInStr FileInStr SeqInStr

Sequence of Streams

Backbone Expression

Page 51: Synthesizing and Repairing Expressions using Types and Weights

51

def main(args:Array[String]) = { var body:String = "email.txt" var sig:String = "signature.txt“ var inStream:SeqInStr = (?) new SeqInStr( (?) sig, (?) body) …}

// new SeqInStr: FileInStr FileInStr SeqInStr

Sequence of Streams

Page 52: Synthesizing and Repairing Expressions using Types and Weights

52

def main(args:Array[String]) = { var body:String = "email.txt" var sig:String = "signature.txt“ var inStream:SeqInStr = (?) new SeqInStr((x. new FileInStr(x)) sig, (?) body) …}

// new SeqInStr: FileInStr FileInStr SeqInStr

Sequence of Streams

Synthesize

Page 53: Synthesizing and Repairing Expressions using Types and Weights

53

def main(args:Array[String]) = { var body:String = "email.txt" var sig:String = "signature.txt“ var inStream:SeqInStr = (?) new SeqInStr((x. new FileInStr(x)) sig, (?) body) …}

Use G to synthesize function:(x:String. new FileInStr(x)) : String FileInStr

Constraint: Function “body” must contain exactly one variable “x”

// new SeqInStr: FileInStr FileInStr SeqInStr

Sequence of Streams

Page 54: Synthesizing and Repairing Expressions using Types and Weights

54

def main(args:Array[String]) = { var body:String = "email.txt" var sig:String = "signature.txt“ var inStream:SeqInStr = (?) new SeqInStr(new FileInStr(sig), (?) body) …}

Use G to synthesize function:(x:String. new FileInStr(x)) : String FileInStr

Constraint: Function “body” must contain exactly one variable “x”

// new SeqInStr: FileInStr FileInStr SeqInStr

Sequence of Streams

Page 55: Synthesizing and Repairing Expressions using Types and Weights

55

def main(args:Array[String]) = { var body:String = "email.txt" var sig:String = "signature.txt“ var inStream:SeqInStr = (?) new SeqInStr(new FileInStr(sig), (x. new FileInStr(x)) body) …}

// new SeqInStr: FileInStr FileInStr SeqInStr

Sequence of Streams

Page 56: Synthesizing and Repairing Expressions using Types and Weights

56

def main(args:Array[String]) = { var body:String = "email.txt" var sig:String = "signature.txt" var inStream:SeqInStr = (?) new SeqInStr(new FileInStr(sig), new FileInStr(body)) …}

// new SeqInStr: FileInStr FileInStr SeqInStr

Sequence of Streams

Page 57: Synthesizing and Repairing Expressions using Types and Weights

57

def main(args:Array[String]) = { var body:String = "email.txt" var sig:String = "signature.txt" var inStream:SeqInStr = (x. x) new SeqInStr(new FileInStr(sig), new FileInStr(body)) …}

// new SeqInStr: FileInStr FileInStr SeqInStr

Sequence of Streams

Page 58: Synthesizing and Repairing Expressions using Types and Weights

58

def main(args:Array[String]) = { var body:String = "email.txt" var sig:String = "signature.txt" var inStream:SeqInStr = new SeqInStr(new FileInStr(sig), new FileInStr(body)) …}

// new SeqInStr: FileInStr FileInStr SeqInStr

Sequence of Streams

Page 59: Synthesizing and Repairing Expressions using Types and Weights

59

def main(args:Array[String]) = { var off:Int = 8 var len:Int = 512 var size:Int = 1024 var b:Array[Byte] = args(0).getBytes()

var inStream:ByteArrayInStr = b …}

Byte Array Stream

Page 60: Synthesizing and Repairing Expressions using Types and Weights

60

def main(args:Array[String]) = { var off:Int = 8 var len:Int = 512 var size:Int = 1024 var b:Array[Byte] = args(0).getBytes()

var inStream:ByteArrayInStr = (?) b …}

Byte Array Stream

Page 61: Synthesizing and Repairing Expressions using Types and Weights

61

def main(args:Array[String]) = { var off:Int = 8 var len:Int = 512 var size:Int = 1024 var b:Array[Byte] = args(0).getBytes()

var inStream:ByteArrayInStr = (x. new ByteArrayInStr(x, off, len)) b …}

Byte Array Stream

Page 62: Synthesizing and Repairing Expressions using Types and Weights

62

def main(args:Array[String]) = { var off:Int = 8 var len:Int = 512 var size:Int = 1024 var b:Array[Byte] = args(0).getBytes()

var inStream:ByteArrayInStr = new ByteArrayInStr(b, off, len) …}

Byte Array Stream

Page 63: Synthesizing and Repairing Expressions using Types and Weights

63

Conclusion

• Code Completion = Type Inhabitation• InSynth: Interactive Synthesis of Code Snippets• Eclipse plugin (part of Scala IDE EcoSystem)• Website

http://lara.epfl.ch/w/insynth

• Repairing Code:• Polynomial Algorithm the finds the best solution

Page 64: Synthesizing and Repairing Expressions using Types and Weights

64

Thank you!