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 • Tedious • Time consuming • Developers should focus on solving creative tasks • Manual Solution • Read Documentation • Inspect Examples • Automation = Code synthesis + Code completion 2
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
Sequence of Streams def main(args:Array[String]) = { var body:String = "email.txt" var sig:String = "signature.txt" var inStream:SeqInStr = … } 4
Sequence of Streams 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(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
Sequence of Streams 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(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
Sequence of Streams 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)) … } 7
Sequence of Streams 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)) … } Imported over 3300 declarations Executed in less than 250ms 8
TreeFilter (HOF) def filter(p: Tree => Boolean): List[Tree] = { val ft:FilterTreeTraverser = ft.traverse(tree) ft.hits.toList } 9
TreeFilter (HOF) def filter(p: Tree => Boolean): List[Tree] = { val ft:FilterTreeTraverser = new FilterTreeTraverser(x => p(x)) new FilterTreeTraverser(x => isType) ft.traverse(tree) new FilterTreeTraverser(x => p(tree)) ft.hits.toList new FilterTreeTraverser(x => new Wrapper(x).isType) } new FilterTreeTraverser(x => p(new Wrapper(x).tree)) 10
TreeFilter (HOF) def filter(p: Tree => Boolean): List[Tree] = { val ft:FilterTreeTraverser = new FilterTreeTraverser(x => p(x)) new FilterTreeTraverser(x => isType) ft.traverse(tree) new FilterTreeTraverser(x => p(tree)) ft.hits.toList new FilterTreeTraverser(x => new Wrapper(x).isType) } new FilterTreeTraverser(x => p(new Wrapper(x).tree)) 11
TreeFilter (HOF) def filter(p: Tree => Boolean): List[Tree] = { val ft:FilterTreeTraverser = new FilterTreeTraverser(x => p(x)) ft.traverse(tree) ft.hits.toList } 12
TreeFilter (HOF) def filter(p: Tree => Boolean): List[Tree] = { val ft:FilterTreeTraverser = new FilterTreeTraverser(x => p(x)) ft.traverse(tree) ft.hits.toList } Imported over 4000 declarations Executed in less than 300ms 13
COMPLETION = INHABITATION 14
COMPLETION = INHABITATION def m 1 : T 1 … def m n : T n val a: T = ? 15
COMPLETION = INHABITATION def m 1 : T 1 … ={ m 1 : T 1 ,…, m n : T n } def m n : T n val a: T = ? 16
COMPLETION = INHABITATION ENVIRONMENT def m 1 : T 1 … ={ m 1 : T 1 ,…, m n : T n } def m n : T n val a: T = ? 17
COMPLETION = INHABITATION ENVIRONMENT def m 1 : T 1 … ={ m 1 : T 1 ,…, m n : T n } def m n : T n val a: T = ? ? : T 18
COMPLETION = INHABITATION ENVIRONMENT def m 1 : T 1 … ={ m 1 : T 1 ,…, m n : T n } def m n : T n val a: T = ? ? : T DESIRED TYPE 19
Simply Typed Lambda Calculus x : T AX ⊢ x : T , x : T 1 ⊢ t : T ABS ⊢ λ x.t : T 1 T ⊢ e 1 : T 1 T ⊢ e 2 : T 1 APP ⊢ e 1 (e 2 ) : T 20
Simply Typed Lambda Calculus 21
Simply Typed Lambda Calculus ⊢ ? : T 22
Simply Typed Lambda Calculus Backward Search ⊢ ? : T 23
Simply Typed Lambda Calculus ⊢ ? : T 1 ⊢ ? : T 1 T APP ⊢ ? : T 24
Simply Typed Lambda Calculus ⊢ ? : T 1 ⊢ ? : T 1 T APP ⊢ ? : T Infinitely many 25
Simply Typed Lambda Calculus No bound on types in derivation tree(s). ⊢ ? : T 1 ⊢ ? : T 1 T APP ⊢ ? : T Infinitely many 26
Long Normal Form , x 1 :T 1 ,…, x n :T n ⊢ t: T ABS ⊢ λ x 1 :T 1 ,…, x n :T n .t: T 1 … T n T f : T 1 … T n T ∈ ⊢ a 1 : T 1 … ⊢ a n : T n APP ⊢ f(a 1 ,…,a n ):T 27
Comparison between LNF and classic APP OLD ⊢ e 1 : T 1 T ⊢ e 2 : T 1 APP ⊢ e 1 (e 2 ) : T f : T 1 … T n T ∈ ⊢ a 1 : T 1 … ⊢ a n : T n APP ⊢ f(a 1 ,…,a n ):T NEW 28
Comparison between LNF and classic APP We derive EXPRESSION from ⊢ e 1 : T 1 T ⊢ e 2 : T 1 APP ⊢ e 1 (e 2 ) : T f : T 1 … T n T ∈ ⊢ a 1 : T 1 … ⊢ a n : T n APP ⊢ f(a 1 ,…,a n ):T 29
Comparison between LNF and classic APP We derive EXPRESSION from ⊢ e 1 : T 1 T ⊢ e 2 : T 1 APP ⊢ e 1 (e 2 ) : T f : T 1 … T n T ∈ ⊢ a 1 : T 1 … ⊢ a n : T n APP ⊢ f(a 1 ,…,a n ):T DECLARATION from 30
Long Normal Form 31
Long Normal Form ⊢ ? :T 32
Long Normal Form ⊢ ? : T 1 T 2 f : (T 1 T 2 ) T ∈ APP ⊢ f(?):T 33
Long Normal Form ⊢ ? : T 1 T 2 f : (T 1 T 2 ) T ∈ APP ⊢ f(?):T Only one Narrows the search space 34
Long Normal Form , x 1 :T 1 ⊢ ? : T 2 ABS ⊢ λ x 1 :T 1 .? : T 1 T 2 f : (T 1 T 2 ) T ∈ APP ⊢ f( λ x 1 :T 1 .?):T 35
Long Normal Form . . . . APP , x 1 :T 1 ⊢ e : T 2 ABS ⊢ λ x 1 :T 1 .e : T 1 T 2 f : (T 1 T 2 ) T ∈ APP ⊢ f( λ x 1 :T 1 .e):T 36
Long Normal Form Finitely many types in derivation tree(s) . . . . APP , x 1 :T 1 ⊢ e : T 2 ABS ⊢ λ x 1 :T 1 .e : T 1 T 2 f : (T 1 T 2 ) T ∈ APP ⊢ f( λ x 1 :T 1 .e):T 37
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 ‐ g enerates all solutions • PSPACE ‐ complete 38
Subtyping Classic A <: B 39
Subtyping Classic Coercion coerc: A B A <: B 40
Subtyping Classic Coercion coerc: A B A <: B coerc: FileInStr InStr class FileInStr extends InStr {…} 41
Subtyping Classic Coercion coerc: A B A <: B coerc: FileInStr InStr class FileInStr extends InStr {…} new SeqInStr(coerc( new FileInStr(sig)), coerc( new FileInStr(body))) 42
Subtyping Classic Coercion coerc: A B A <: B coerc: FileInStr InStr class FileInStr extends InStr {…} new SeqInStr( new FileInStr(sig), new FileInStr(body)) 43
Types Classic Types • Simple Int, Bool, String, List[Int] 44
Types Classic Types Succinct types • Simple • Simple Int, Bool, String, List[Int] Int, Bool, String, List[Int] 45
Types Classic Types Succinct types • Simple • Simple Int, Bool, String, List[Int] Int, Bool, String, List[Int] • Function • Preserves argument duplicates • Preserves argument order Int Int Bool Long 46
Types Classic Types Succinct types • Simple • Simple Int, Bool, String, List[Int] Int, Bool, String, List[Int] • Function • Function • Preserves argument duplicates • No duplicates • Preserves argument order • No order {Int, Bool} Long Int Int Bool Long 47
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
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 Low High Method and field symbols Local symbols API symbols 49
Recommend
More recommend