Complete Completion using Types and Weights Tihomir Gvero, Viktor - - PowerPoint PPT Presentation

complete completion using types and weights
SMART_READER_LITE
LIVE PREVIEW

Complete Completion using Types and Weights Tihomir Gvero, Viktor - - PowerPoint PPT Presentation

Complete Completion using Types and Weights Tihomir Gvero, Viktor Kuncak, Ivan Kuraj and Ruzica Piskac 1 Motivation Large APIs and libraries ~4000 classes in Java 6.0 standard library Using those APIs (for the first time) can be


slide-1
SLIDE 1

Complete Completion using Types and Weights

Tihomir Gvero, Viktor Kuncak, Ivan Kuraj and Ruzica Piskac

1

slide-2
SLIDE 2

Motivation

  • Large APIs and libraries

~4000 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

2

slide-3
SLIDE 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

3

slide-4
SLIDE 4

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

Sequence of Streams

4

slide-5
SLIDE 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)

5

slide-6
SLIDE 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)

6

slide-7
SLIDE 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

7

slide-8
SLIDE 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

8

slide-9
SLIDE 9

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

TreeFilter (HOF)

9

slide-10
SLIDE 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))

10

slide-11
SLIDE 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))

11

slide-12
SLIDE 12

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

TreeFilter (HOF)

12

slide-13
SLIDE 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

13

slide-14
SLIDE 14

COMPLETION = INHABITATION

14

slide-15
SLIDE 15

COMPLETION = INHABITATION

val a: T = ? def m1: T1 … def mn: Tn

15

slide-16
SLIDE 16

COMPLETION = INHABITATION

val a: T = ? def m1: T1 … def mn: Tn ={ m1: T1,…, mn: Tn}

16

slide-17
SLIDE 17

COMPLETION = INHABITATION

val a: T = ? def m1: T1 … def mn: Tn ={ m1: T1,…, mn: Tn} ENVIRONMENT

17

slide-18
SLIDE 18

COMPLETION = INHABITATION

val a: T = ?  ? : T def m1: T1 … def mn: Tn ={ m1: T1,…, mn: Tn} ENVIRONMENT

18

slide-19
SLIDE 19

COMPLETION = INHABITATION

val a: T = ?  ? : T def m1: T1 … def mn: Tn ={ m1: T1,…, mn: Tn} DESIRED TYPE ENVIRONMENT

19

slide-20
SLIDE 20

Simply Typed Lambda Calculus

 ⊢ x : T AX x : T    ⊢ e1(e2) : T APP  ⊢ e1 : T1T  ⊢ e2 : T1  ⊢ λx.t : T1  T ABS , x : T1 ⊢ t : T

20

slide-21
SLIDE 21

Simply Typed Lambda Calculus

21

slide-22
SLIDE 22

Simply Typed Lambda Calculus

 ⊢ ? : T

22

slide-23
SLIDE 23

Simply Typed Lambda Calculus

 ⊢ ? : T

23

Backward Search

slide-24
SLIDE 24

Simply Typed Lambda Calculus

 ⊢ ? : T APP  ⊢ ? : T1T  ⊢ ? : T1

24

slide-25
SLIDE 25

Simply Typed Lambda Calculus

 ⊢ ? : T APP  ⊢ ? : T1T  ⊢ ? : T1

Infinitely many

25

slide-26
SLIDE 26

Simply Typed Lambda Calculus

 ⊢ ? : T APP  ⊢ ? : T1T  ⊢ ? : T1

Infinitely many No bound on types in derivation tree(s).

26

slide-27
SLIDE 27

 ⊢ f(a1,…,an):T APP f : T1…TnT ∈   ⊢ a1: T1 …  ⊢ an: Tn  ⊢ λ x1:T1 ,…, xn:Tn.t: T1 … Tn  T

ABS

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

27

Long Normal Form

slide-28
SLIDE 28

 ⊢ f(a1,…,an):T APP f : T1…TnT ∈   ⊢ a1: T1 …  ⊢ an: Tn

28

 ⊢ e1(e2) : T APP  ⊢ e1 : T1T  ⊢ e2 : T1

Comparison between LNF and classic APP

OLD NEW

slide-29
SLIDE 29

 ⊢ f(a1,…,an):T APP f : T1…TnT ∈   ⊢ a1: T1 …  ⊢ an: Tn

29

 ⊢ e1(e2) : T APP  ⊢ e1 : T1T  ⊢ e2 : T1

We derive EXPRESSION from 

Comparison between LNF and classic APP

slide-30
SLIDE 30

 ⊢ f(a1,…,an):T APP f : T1…TnT ∈   ⊢ a1: T1 …  ⊢ an: Tn

30

 ⊢ e1(e2) : T APP  ⊢ e1 : T1T  ⊢ e2 : T1

We derive EXPRESSION from  DECLARATION from 

Comparison between LNF and classic APP

slide-31
SLIDE 31

Long Normal Form

31

slide-32
SLIDE 32

Long Normal Form

 ⊢ ? :T

32

slide-33
SLIDE 33

Long Normal Form

APP f : (T1 T2)T ∈   ⊢ ? : T1 T2  ⊢ f(?):T

33

slide-34
SLIDE 34

Long Normal Form

APP f : (T1 T2)T ∈   ⊢ ? : T1 T2

Only one

 ⊢ f(?):T

34

Narrows the search space

slide-35
SLIDE 35

Long Normal Form

APP f : (T1 T2)T ∈   ⊢ λ x1:T1.? : T1 T2 , x1:T1 ⊢ ? : T2 ABS  ⊢ f(λ x1:T1.?):T

35

slide-36
SLIDE 36

Long Normal Form

APP f : (T1 T2)T ∈   ⊢ λ x1:T1.e : T1 T2 , x1:T1 ⊢ e : T2 . . . . ABS APP  ⊢ f(λ x1:T1.e):T

36

slide-37
SLIDE 37

Long Normal Form

APP f : (T1 T2)T ∈   ⊢ λ x1:T1.e : T1 T2 , x1:T1 ⊢ e : T2 . . . . ABS APP

Finitely many types in derivation tree(s)

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

37

slide-38
SLIDE 38

Algorithm

  • Algorithm builds finite graph (with cycles) that
  • Represents all (infinitely many) solutions
  • Later we use it to construct expressions
  • Algorithm Properties
  • Graph generation terminates
  • Type inhabitation is decidable
  • Complete ‐ generates all solutions
  • PSPACE‐complete

38

slide-39
SLIDE 39

Subtyping

Classic

A <: B

39

slide-40
SLIDE 40

Subtyping

Classic

A <: B

Coercion

coerc: A  B

40

slide-41
SLIDE 41

Subtyping

Classic

A <: B class FileInStr extends InStr {…}

Coercion

coerc: A  B coerc: FileInStr  InStr

41

slide-42
SLIDE 42

Subtyping

Classic

A <: B class FileInStr extends InStr {…}

Coercion

coerc: A  B coerc: FileInStr  InStr new SeqInStr(coerc(new FileInStr(sig)), coerc(new FileInStr(body)))

42

slide-43
SLIDE 43

Subtyping

Classic

A <: B class FileInStr extends InStr {…}

Coercion

coerc: A  B coerc: FileInStr  InStr new SeqInStr(new FileInStr(sig), new FileInStr(body))

43

slide-44
SLIDE 44

Types

Classic Types

  • Simple

Int, Bool, String, List[Int]

44

slide-45
SLIDE 45

Types

Classic Types

  • Simple

Int, Bool, String, List[Int]

Succinct types

  • Simple

Int, Bool, String, List[Int]

45

slide-46
SLIDE 46

Types

Classic Types

  • Simple

Int, Bool, String, List[Int]

  • Function
  • Preserves argument duplicates
  • Preserves argument order

Int  Int  Bool  Long

Succinct types

  • Simple

Int, Bool, String, List[Int]

46

slide-47
SLIDE 47

Types

Classic Types

  • Simple

Int, Bool, String, List[Int]

  • Function
  • Preserves argument duplicates
  • Preserves argument order

Int  Int  Bool  Long

Succinct types

  • Simple

Int, Bool, String, List[Int]

  • Function
  • No duplicates
  • No order

{Int, Bool}  Long

47

slide-48
SLIDE 48

Environment

  • Classical environment
  • Declarations
  • Classic Types
  • Succinct environment
  • Only succinct types
  • Environment Translation
  • Shrinks environment
  • e.g. 3300 declarations to 1780 succinct types
  • We generate the graph on average in 10ms
  • Reduces the search space

48

slide-49
SLIDE 49

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 symbols Method and field symbols API symbols

Low High

49

slide-50
SLIDE 50

Algorithm with Weights

APP f : (T1 T2)T ∈   ⊢ λ x1:T1.e : T1 T2 , x1:T1 ⊢ e : T2 . . . . ABS APP  ⊢ f(λ x1:T1.e):T

50

slide-51
SLIDE 51

Algorithm with Weights

APP f : (T1 T2)T ∈   ⊢ λ x1:T1.e : T1 T2 , x1:T1 ⊢ e : T2 . . . . ABS APP  ⊢ f(λ x1:T1.e):T

Choice based on WEIGHT

51

slide-52
SLIDE 52

Algorithm with Weights

APP f : (T1 T2)T ∈   ⊢ λ x1:T1.e : T1 T2 , x1:T1 ⊢ e : T2 . . . . ABS APP  ⊢ f(λ x1:T1.e):T

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

52

slide-53
SLIDE 53

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 expression
  • 2. Removed it
  • 3. Marked it as goal expression
  • 4. Measure whether InSynth can recover it

53

slide-54
SLIDE 54

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

54

slide-55
SLIDE 55

A Sample of State of the Art

  • Code completion in IDEs (Eclipse, Visual Studio, IntelliJ)
  • Mostly single declarations
  • Simple expressions
  • M. Mezini et al (FSE ’09): Code recommenders
  • Suggests: Declarations based on API call statistics
  • T. Xie et al (ASE ’07): PARSEWeb
  • Query: Source and Desired type
  • Suggests: Code examples based on corpus
  • E. Yahav et al (OOPSLA ‘12): Prime
  • Query: Partial program
  • Suggests: Code snippets based on temporal specifications
  • S. Gulwani et al (PLDI ’12): Type‐directed completion of

partial expressions.

  • Query: Partial Expression
  • Suggests: Complete expressions based on type similarity metrics

55

slide-56
SLIDE 56

Conclusion

  • Code Completion = Type Inhabitation
  • InSynth: Interactive Synthesis of Code Snippets
  • Our synthesis algorithm is:
  • Complete
  • Efficiency
  • Effective
  • Eclipse plugin (part of Scala IDE EcoSystem)
  • Website

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

56

slide-57
SLIDE 57

Thank you!

57

slide-58
SLIDE 58

 ⊢ @{T1,…,Tn}:T APP {T1,…,Tn}  T ∈   ⊢ T1 …  ⊢ Tn  ⊢ S  T

ABS

 ∪ S ⊢ t: T

58

Succinct Calculus