No Man is an Island: Towards Fully Automatic Programming by Code Search, Code Generation and Program Repair
Quanjun Zhang Chunrong Fang Ye Shang Tongke Zhang Shengcheng Yu Zhenyu Chen



 
0000-0002-2495-3805
quanjun.zhang@smail.nju.edu.cn

 
0000-0002-9930-7111
fangchunrong@nju.edu.cn

 
0000-0002-2495-3805
201250032@smail.nju.edu.cn

 
0000-0002-2495-3805
201250032@smail.nju.edu.cn

 
0000-0002-2495-3805
201250032@smail.nju.edu.cn


zychen@nju.edu.cn
0000-0002-9592-7022


  State Key Laboratory for Novel Software Technology, Nanjing University
  Nanjing
  Jiangsu
  China



§ ABSTRACT 



Automatic programming attempts to minimize human intervention in the generation of executable code, and has been a long-standing challenge in the software engineering community.
To advance automatic programming, researchers are focusing on three primary directions:
(1) code search that reuses existing code snippets from external databases;
(2) code generation that produces new code snippets from natural language;
and (3) program repair that refines existing code snippets by fixing detected bugs.
Despite significant advancements, the effectiveness of state-of-the-art techniques is still limited, such as the usability of searched code and the correctness of generated code.

Motivated by the real-world programming process, where developers usually use various external tools to aid their coding processes, such as code search engines and code testing tools,
in this work, we propose , an automatic programming framework that leverages recent large language models (LLMs) to integrate the three research areas to address their inherent limitations.
Our insight is that the integration of three research areas can overcome their inherent limitations:
the code generator can benefit from the valuable information retrieved by the code searcher, while the code repairer can refine the quality of the generated code with external feedback.
In particular, our framework first leverages different code search strategies to retrieve similar code snippets, which are then used to further guide the code generation process of LLMs.
Our framework further validates the quality of generated code by compilers and test cases, and constructs repair prompts to query LLMs for generating correct patches.
We conduct preliminary experiments to demonstrate the potential of our framework, helping CodeLlama solve 267 programming problems with an improvement of 62.53%.
As a generic framework,  can integrate various code search, generation, and repair tools, combining these three research areas together for the first time.
More importantly, it demonstrates the potential of using traditional SE tools to enhance the usability of LLMs in automatic programming.








<ccs2012>
	<concept>
	<concept_id>10011007.10011074.10011099.10011102.10011103</concept_id>
	<concept_desc>Software and its engineering Software testing and debugging</concept_desc>
	<concept_significance>500</concept_significance>
	</concept>
</ccs2012>


[500]Software and its engineering Software testing and debugging



No Man is an Island: Towards Fully Automatic Programming by Code Search, Code Generation and Program Repair
    Zhenyu Chen
    September 5, 2024
===========================================================================================================












§ INTRODUCTION

Software automation has long been a vision of Software Engineering (SE), with one of the significant challenges being the task of automatic programming <cit.>.
Automatic programming attempts to handle high-level specifications (natural language and test cases) into correct source code without direct human intervention <cit.>.
It effectively reduces manual coding effort, improves efficiency, and minimizes programming errors, thus enabling a more robust software development pipeline.
Besides, it democratizes programming by making it accessible to individuals with varying levels of programming expertise.
This is particularly significant as software permeates various industries in modern society, allowing domain-specific experts, who may not be proficient in programming, to undertake programming tasks tailored to their specific needs, such as AI applications in Science <cit.>.

In the SE literature, to advance automatic programming effectively, researchers are focusing on three primary directions:


    
  * Code Search.
    This task <cit.> involves developing sophisticated algorithms to search and retrieve existing code snippets from vast databases or the internet. 
    Code search is able to accelerate development and promote best practices by enabling the reuse of code.
    
    
  * Code Generation.
    This task <cit.> explores the automatic creation of code based on high-level specifications or requirements. It harnesses advanced machine learning models and artificial intelligence to translate human intentions into functional programs.
    
    
  * Program Repair. <cit.>
    This task involves fixing bugs or vulnerabilities in existing code during the software maintenance phase.
    Program repair can be seen as automatic code generation at a micro-scale by generating correct code from buggy code.
    



Over the last decade, considerable research efforts have been devoted to advancing the state-of-the-art in the three areas.
Despite being promising, existing research in these domains still suffers from several limitations.
First, prior studies <cit.> find that code snippets retrieved by code search techniques cannot be directly reused and require manual adaptation, consuming a significant amount of time.
Second, code generation techniques often struggle to produce syntactically and semantically correct code that can pass both the compiler and test cases.
Recent studies <cit.> show that even the latest Large Language Models (LLMs) still tend to generate code that contains errors and vulnerabilities.
Third, research on program repair <cit.> is mostly confined to semantic bugs introduced by developers, while overlooking the rapidly emerging field of auto-generated code <cit.>.
Therefore, addressing the aforementioned issues can help enhance the effectiveness and usability of code search, code generation, and program repair tools when applied in real-world automatic programming scenarios.

To that end, our insights come from the limitations of existing techniques:


    
  * Limitation of Code Search.
Code search is an effective method for finding usable code from external codebases.
However, the retrieved code typically cannot be deployed directly due to several reasons, such as project context, software bugs, and library dependencies <cit.>.
Thus, developers need to adapt retrieved code to specific requirements, including adjusting variable names, optimizing performance or efficiency, fixing bugs or securities, and including necessary dependencies.
When applied in practice, although code search tools can significantly accelerate development by providing useful code snippets, developers will often expend considerable effort to customize and validate the retrieved code before integrating it into their projects.
To address this issue, a feasible direction is to refine the retrieved code to meet certain requirements automatically.
In this regard, program repair is promising to adapt the code retrieved by code search tools with minor modifications, as the retrieved code may already be very similar to the desired output.



  * Limitation of Code Generation.
Code generation is the focus of LLMs in the SE community, and has achieved continuous progress.
However, LLMs are trained on vast datasets up to a certain cutoff point, making it difficult to acquire and update up-to-date knowledge.
Although fine-tuning remains a possible solution, it is impractical to frequently update LLMs with the latest information due to the vast number of model parameters and computational resources.
Thus, when generating code, LLMs may suffer from outdated knowledge and project-specific context.
Particularly, LLMs are unaware of new knowledge (such as libraries or frameworks) after the last training update, and fail to incorporate information about project-specific requirements, dependencies, or evolving codebases, thus limiting the effectiveness of code generation.
To address this issue, a viable approach is to dynamically search for valuable information to augment the code generator.
In this regard, code search can provide useful hints, which can guide LLMs to avoid invalid results during code generation.


  * Limitation of Program Repair.
As a crucial phase of automatic programming, program repair has achieved significant progress in terms of the number of correctly-fixed bugs <cit.>.
However, existing repair research is mainly limited to fixing bugs detected by functional test cases from well-constructed benchmarks <cit.>.
Recently, LLMs have demonstrated impressive capabilities in automatically generating source code. 
However, the reliability and quality of auto-generated code are usually imperfect <cit.>, making it difficult to deploy such code directly into projects.
In fact, LLMs may generate source code with syntax and semantic errors as the generation process is static without external validation tools, such as compilers.
This concern raises a significant question: can we automatically refine the code generated by LLMs to make it sufficiently trusted for integration into software systems?
Therefore, combining test-driven repair with LLMs can provide dynamic feedback, allowing LLMs to iteratively generate accurate code.
In this regard, program repair is promising to help LLMs perform self-debugging with test-driven feedback during the code generation phase.





Our analysis motivates us to leverage the complementary strengths of code search, code generation, and program repair techniques to achieve mutual improvement.
In real-world programming scenarios, as shown in Fig. <ref>, developers typically follow a three-step process.
First, they construct an appropriate search query (such as natural language descriptions) and use search engines (such as GitHub) to find similar code.
Second, they generate their own code by imitating the retrieved code instead of coding from scratch.
Third, they validate the generated code through a compiler to ensure it meets specifications, such as test cases.
Taking inspiration from the developer practice, we can integrate the three research areas into the programming process, code search retrieves similar code for code generation, and program repair provides dynamic feedback to refine the generated code.
However, the key challenge lies in emulating the human developer role to seamlessly connect the three steps, how to integrate retrieved code for generation and how to refine generated code based on test feedback.
Fortunately, thanks to the powerful natural language and programming language understanding capabilities of LLMs, we can fully automate this process through prompt engineering.
Prior studies demonstrate that LLMs can perform code-related tasks in a manner similar to human conversation, and thus, we are motivated to leverage such capabilities of LLMs to connect code search, code generation, and program repair in a unified programming pipeline.



This Work.
We propose a framework , which leverages code searCh, code geneRation, and program repAir to push forward the boundaries of automatic progrAMming in the ear of LLMs.
Our work is motivated by the potential to automatically emulate the common developer practice with the help of LLMs' powerful natural language understanding and programming language generation capabilities.
Particularly, given a programming requirement,  follows three steps:
(1) code search: an information retrieval (IR) or deep learning (DL)-based technique searches for relevant code from an external database of previous code snippets that may fit the programming context.
(2) code generation: an LLM-based code generator synthesizes a ranked list of code candidates based on both the programming requirement and the retrieved external code knowledge.
(3) program repair: an LLM-based code repairer slightly refines the token sequence of generated code from the previous step by constructing dynamic prompts with test case feedback.
This framework attempts to integrate three well-known research domains that are often developed in isolation, so as to benefit the whole programming pipeline.
More importantly, the integration not only broadens the application scope of these three research areas but also boosts the capabilities of recent LLMs in resolving programming problems effectively.

Preliminary Results.
We conduct a preliminary experiment to evaluate the effectiveness of  by implementing it with two retrieval strategies as the code searcher and an open-source LLM CodeLLama with 7 billion parameters as the code generator and program repairer.
The experimental results on the MBPP benchmark demonstrate that 
(1)  is able to help CodeLLama in solving programming problems significantly, generating 267 correct solutions with an improvement of 32.18%;
(2) the three phases positively contribute to the performance of , code search and program repair improves CodeLlama by 24.75% and 14.85%, respectively.
To evaluate the potential of  in a more real-world programming scenario, we illustrate several case studies from the CoderEval benchmark by utilizing GitHub Search API to search for relevant code and a black-box LLM ChatGPT to generate and repair code.



To sum up, the contributions of this paper are as follows:

  
  
  * New Dimension.
  We open a new direction for integrating LLMs with traditional SE research areas for more powerful automatic programming.
  To the best of our knowledge, this is the first work to reveal the potential of LLMs in bridging the gap between three long-standing yet studied-separately research topics, code search, program repair and program repair.  


  
  * Novel Framework.
  We propose , a three-stage automatic programming framework built on top of LLMs with code search, code generation, and program repair. 
   is a conceptually generic framework that can be easily integrated with various LLMs, code search, generation and repair tools.  


  
  * Preliminary Evaluation.
  We demonstrate 's ability to generate correct solutions for competitive programming problems.
  Besides, we present case studies to indicate the potential of  in real-world programming scenarios.
    


  


§ BACKGROUND & RELATED WORK





 §.§ Large Language Models

In recent years, LLMs have attracted increasing attention from the industry and academia for their impressive capability of processing natural and programming languages <cit.>. 
LLMs are generally based on the Transformer architecture that has two key components: the encoder and the decoder.
The former encodes the input into a vector representation for the model to understand the input, while the latter transforms the encoded representation to the output sequence.
Such LLMs have shown outstanding performance in code-related tasks, such as program repair and code generation <cit.>.
For example, ChatGPT <cit.> and GPT-4 <cit.> released by OpenAI are known for their ability of conducting dialogues with human beings. 
They can take prompts in natural language and generate relevant code accordingly.
CodeLlama <cit.> is a family of open-source LLMs specifically trained for source code, and can solve programming problems in a zero-shot situation.
Details about the application of LLMs in SE can be found in recent survey papers <cit.>.
However, when programming, such LLMs typically struggle to learn the latest knowledge and interact with external coding tools.
In this work, we aim to improve the programming capabilities of off-the-shelf LLMs by integrating them with code search, code generation, and program repair techniques.
 




 §.§ Code Search

A common action that developers take while programming is searching for existing code with similar requirements to reuse.
A variety of code search techniques have been proposed to facilitate the retrieval process, and they can be generally classified into two types: IR-based and DL-based <cit.>.
IR-based code search techniques usually involve indexing the codebases and using scoring algorithms to calculate the similarity between the query and the target code. 
For example, Lucene <cit.> is a typical IR-based search engine whose default scoring algorithm is BM25, which considers the word frequency and the lengths of documents to rank candidates in the retrieval corpus.
DL-based techniques leverage deep learning models to encode code snippets into vectors, and retrieve similar code based on the cosine similarity between the vectors.
For example, GraphSearchNet <cit.> is a neural network framework based on bidirectional GGNN to map queries and source code by learning the structural information from them.
For a more comprehensive study on code search, please refer to the work of Sun  <cit.>.
In this work, we implement  with two simple yet effective code searchers, IR-based and DL-based sterategies.




 §.§ Code Generation


Code generation is a popular task that LLMs are applied to because of its great potential to improve the coding efficiency of developers.
For example, AceCoder <cit.> retrieves similar code and remove redundant retrieval results to boost the effectiveness of code generation.
SkCoder <cit.> simulates developers' coding behavior by constructing code sketches from the retrieved similar code and turning the sketch into complete code with an encoder-decoder model.
CodeAgent <cit.> proposes a novel repo-level code generation framework that integrates different programming tools including information retrieval tools with the purpose of gathering relevant resources so that LLMs can better understand the problems.
Please refer to the of Jiang  <cit.> for a more comprehensive survey.
In this work, we construct prompts augmented by the code searcher to query CodeLlama and ChatGPT as the code generator.  



 §.§ Program Repair


Program repair aims to automatically fix software bugs, thereby reducing the efforts for manual debugging <cit.>. 
Existing repair techniques can be broadly categorized into traditional and learning-based ones. 
Traditional program repair approaches include heuristic-based, constraint-based, and template-based techniques. 
With recent advancements in DL, a variety of learning-based repair approaches have been proposed <cit.>.
Such learning-based techniques leverage Neural Machine Translation (NMT) models to understand the semantics of the bugs and transform them into the correct code.
For example, CoCoNut <cit.> utilizes a context-aware NMT architecture to represent the buggy source code and its surrounding context separately.

Recently, LLMs are increasingly being utilized for repair tasks <cit.>.
For example, Zhang  <cit.> investigate the potential of fine-tuning LLMs in repairing security vulnerabilities.
Xia  <cit.> evaluate the fixing capabilities of LLMs for Java single-hunk semantic bugs.
Detailed summarization of program repair studies can be found in recent work <cit.>.
However, unlike traditional repair techniques, LLMs' powerful natural language capabilities enable them to incorporate external runtime information, thus facilitating iterative patch generation <cit.>.
In this work, motivated by the self-critical capability of LLMs, we leverage execution feedback to integrate program repair into the programming process.






§ FRAMEWORK AND IMPLEMENTATION







 §.§ Overview

 

 takes a programming requirement and external codebases as inputs, and automatically returns source code that meets the requirements.
<ref> illustrates an overview of , which is divided into three phases: code search, code generation, and program repair.

    
  * In the code search phase, given the input as a query,  searches a database of source code to find similar code applied previously in a similar context.
    This phase is motivated by the redundancy assumption <cit.> that the required code can be found or refactored from other projects with similar contexts.
    In the motivating example in Fig. <ref>, given the programming requirement “” as query,  retrieves a code snippet that addresses a similar programming problem from the codebase: “”.
    
    
  * In the code generation phase, we first concatenate the retrieved code along with the original programming requirement to construct an augmented input.
    We then query off-the-shelf LLMs, as mentioned in Section <ref>, to generate code. 
    Fig. <ref> illustrates the generation phase that produces a token sequence for “”, which is close to the intended code.
    However, as LLMs generate code tokens from a probabilistic perspective without the ability to dynamically execute and validate the generated code, the generated code may still be imperfect.
    For example, in Fig. <ref>, the generated code lacks a return statement, resulting in output values that do not match the expected results and failing to pass the test cases.
    Although the generated code can be quite similar to the intended output, developers still need to spend manual efforts to inspect and modify the generated code.

    
  * In the program repair phase, we attempt to capture the minor modifications and further refine the generated code with dynamic test feedback.
    Our key insight is that, due to the powerful code generation capabilities of LLMs, the code returned in the last phase is already close to perfect, which can naturally be seen as a program repair task.
    In particular, we utilize the self-critical ability of LLMs by compiling and executing the generated code, then returning the error information to LLMs to guide them in generating more accurate code.
    In the case of Fig <ref>, this step explicitly adds the lacked returned statment “”, resulting in the correct patch







 §.§ Code Search

In this phase, given a program specification that needs to be implemented as a query,  retrieves relevant code snippets from external databases that are applied before in a similar code context.
 utilizes two types of retrieval strategies: an IR-based retriever and a DL-based retriever, to consider the lexical and semantic similarity, respectively.





  §.§.§ IR-based Retriever

 employs the sparse strategy IR as the token-based retriever, to search for a code snippet that is similar to the query programming requirement based on lexical matching.
Suppose 𝒟 = (r_i, c_i)^|𝒟|_i=1 be an external retrieval database consisting of |𝒟| previous code pairs, where r_i is the i-th program specification and c_i is its corresponding source code.
Given a query requirement q,  tokenizes all requirements in the retrieval dataset 𝒟 and the query, and removes duplicate tokens for an efficient retrieval process.
 then calculates the lexical similarity between q with all requirements in 𝒟 based on the Jaccard coefficient.
Jaccard is a widely-used similarity coefficient, to measure the similarity between two sparse vector representations based on their overlapping and unique tokens.
Formula <ref> defines the calculation of Jaccard similarity, where S(q) and S(r_i) are the sets of code tokens of two requirements q and r_i, respectively.
The value varies from 0% to 100%, and a higher value indicates a higher similarity.
In this work, considering that all requirements are natural language descriptions, we adopt space to tokenize each requirement instead of a sub-word level tokenizer.


    Jaccard(q, r_i) = |S(q) ∩ S(r_i) |/|S(q) ∪ S(r_i) |





  §.§.§ DL-based Retriever

 employs the pre-trained CodeBERT <cit.> as the embedding-based retriever to search for similar code snippets based on semantic similarity.
In particular,  first splits all requirements in 𝒟 and the query q into a list of tokens and exploits CodeBERT to transform the tokenized tokens into vector representations.
CodeBERT  prepends a special token of [CLS] into its tokenized sequence, and calculates the final layer hidden state of the [CLS] token as the contextual embedding.
 then calculates the Cosine similarity between the embeddings of two requirements to measure their semantic relevance.
Cosine similarity is widely adopted in previous studies to measure the semantic relevance of two dense vectors.
Given two vectors, Cosine similarity is calculated based on the cosine of the angle between them, which is the dot product of the vectors divided by the product of their lengths.
Formula <ref> defines the calculation of Cosine similarity, where E(q) and E(r_i) denote the embeddings of two requirements q and r_i.

    Cosine(q, r_i) = E(q) · E(r_i)/ E(q)E(r_i)








Algorithm <ref> presents the detailed workflow of the search strategy in our work.
The algorithm starts by taking three inputs: a query representing the program specification to be implemented (), an external database containing code snippets (𝒟), and the number of similar code snippets to be retrieved (top-k).
The algorithm initializes an empty list called “similarityList” to store the similarity scores between the query and each code requirement in the database (Line <ref>). 
For each code requirement in the database, the algorithm calculates the similarity score between the query and the code requirement using a function named calculateSimilarity (Line <ref>). 
This function extracts tokens or embeddings from both the query and the code requirement, then calculates the similarity score using either Jaccard similarity for tokens or cosine similarity for embeddings (Line <ref>∼<ref>). 
The resulting similarity score, along with the corresponding code requirement and code snippet, is appended to the “similarityList” (Line <ref>).
Once all similarity scores are calculated, the algorithm sorts “similarityList” in descending order based on the similarity scores using a function named customSort (Line <ref>). 
This function employs a bubble sort algorithm to ensure the list is ordered from the highest to the lowest similarity score (Line <ref>∼<ref>).
After sorting, the algorithm extracts the top-k most similar code snippets from the sorted list and stores them in “retrievedResult” (Line <ref>). 
Finally, the algorithm returns “retrievedResult” as the output, which contains the code snippets that are most similar to the given query (Line <ref>). 
Through this systematic approach, the algorithm effectively retrieves the most relevant code snippets from an external database based on the provided query.






 §.§ Code Generation


In the code generation phase, we leverage LLMs to generate code based on the programming requirement and the retrieved programming solutions.
Particularly, we build a prompt by composing (a) relevant code demonstrations,  (b) the programming query, and (c) natural language instructions. 
To select demonstrations, we take examples from the demonstration retriever component. 
Then we select a task-specific template and combine these three elements to build the final prompt.

Fig. <ref> illustrates a prompt template for code generation. 
The input prompt mainly contains two sections: code demonstrations, and the query.
Each code demonstration section consists of the programming requirement, its test cases, and the expected code. 
The query section contains the natural language instruction beginning with  in the template, followed by the test cases. 
As it is an autocomplete task, the comment  is used to signal the model to generate a correct code snippet.
Finally, the expected output for a given prompt is a multi-line code snippet passing the test cases.





 §.§ Program Repair


After obtaining generated code snippets by LLMs, this phase attempts to refine them further by fixing syntax and semantic errors.
Particularly, we compile the programs and dynamically execute them against all available test cases.
The test cases provide valuable information about the correctness of the generated code, associated with the error messages if the code does not pass the tests. 
For the failing functions, we input them to the LLMs again together with their requirements and error messages in an attempt to have them fixed. 
To this end, we conduct a dynamic prompt for LLMs in the program repair stage, as shown in Fig. <ref>.
The prompt 
The input prompt contains two sections: the programming requirement. its test cases, the generated code, and the failure information.
Each section is denoted by a natural language description that begins with the comment symbol  in the template.
The query contains the context of test execution followed by the instruction. 
This is essentially an auto-complete task where the query is an incomplete example used to prompt the model. 
Finally, the expected output for a given prompt is a fixed version that addresses the reported failure.








§ PRELIMINARY RESULTS



We conduct two preliminary experiments to evaluate the performance of our search-generation-repair framework for automatic programming.
We first investigate the performance of  in solving competitive programming problems.
We then explore the potential of  in solving real-world programming problems.

 
 


 §.§ Evaluation 1: The Effectiveness of Three Phases in Solving Competitive Programming Problems



Experimental Design.
In this RQ, we investigate the effectiveness of the code search, code generation, and program repair phases in our automatic programming framework.

We choose Mostly Basic Programming Problems (MBPP) released by Austin  <cit.> as the benchmark. 
It contains 974 easy Python programming problems, their test cases and code solutions obtained from crowdsourcing.
There is also a sanitized version of MBPP with 427 programming problems manually verified and extracted from the full dataset.
We focus on the sanitized MBPP and investigate how effective our framework is in solving problems in it. 
We use the same dataset for code retrieval (except the query) since the coding styles within the same dataset are similar, which helps LLMs better learn what the target code looks like.

We choose CodeLlama as the researched LLM in this RQ and use it to generate Python code for 427 programming problems from the MBPP dataset. CodeLlama is a series of large language models for code generation, and we select the CodeLlama-7b-hf model, which is one of the foundation models with 7B parameters.


We conduct experiments under programming four scenarios to explore how each phase influences the correctness of the generated code:


    
  * Only code generation.
    We construct basic prompts only with programming problem descriptions and test cases, and query LLMs to generate Python functions to solve the problems.
    
  * Code search + code generation. 
    When using LLMs to generate code, we not only provide basic information of the programming problems, but also additional functions with similar requirements that are retrieved from the same dataset.
    
  * Code generation + program repair. 
    We generate code with the basic prompts, and then we use LLMs again to fix the incorrect code it generates.
    
  * Code search + code generation + program repair (). 
    We combine all the phases by retrieving similar code, generating code according to the programming requirements as well as the similar code, and repairing the code that does not pass all the tests.



Results.
Fig. <ref> presents the number of problems that CodeLlama successfully solves under four different scenarios.
In Fig. <ref>, “search (IR)” and “search (EM)” denote the IR and embedding retrievers, respectively.
When CodeLlama directly performs the code generation task, 202 out of 427 generated solutions are correct, resulting in a correctness rate of 47.31
Besides, when integrating program repair, code search-IR, and code search-embedding into the programming process, 31, 28, and 50 additional correct solutions are generated, respectively.
Finally, CodeLlama achieves the best performance when code search, code generation and program repair are combined, producing 248 (IR retriever) and 251 (embedding retriever) correct solutions.
The improvement against the code generation-only scenario yields 58.08% and 62.53%, respectively.
These results demonstrate that the three-phase pipeline—comprising searching, coding, and repairing—continuously enhances the programming capabilities of LLMs.




 §.§ Evaluation 2: The Potential of Three Phases in Solving Real-world Programming Problems



Experimental Design.
In RQ1, we investigate the performance of  in generating functions for competitive programming problems. 
In this RQ, we further explore how effective our approach is in a real-world programming scenario. 

We select CoderEval <cit.>. Compared to MBPP and other popular code generation benchmarks which only include standalone functions, CoderEval contains programming tasks extracted from real-world projects as well as separate platforms to execute them, so we can evaluate our automatic programming approach in a real-world scenario.

We simulate real programming scenarios by selecting three functions that need to be implemented from the dataset. First, we use the GitHub search engine to find similar code, then call ChatGPT to generate the code, providing feedback on the test results for corrections.
In the following, we present three real-world examples to illustrate the search-generation-repair capabilities of .
For all three examples, ChatGPT fails to directly generate correct code based solely on their specifications, docstring.
However,  successfully queries ChatGPT to produce the correct code for the first example with code search, the second example with program repair, and the third example with both code search and program repair. 









Case 1.
Fig. <ref> illustrates an example that is not correctly generated by ChatGPT, but correct code can be produced by providing relevant information from code search.
This example attempts to identify whether a given string starts with a specified case-insensitive prefix, as shown in the blue part of Fig. <ref>.
ChatGPT first attempts to generate the solution directly, which ignores some boundary conditions and leads to a `NullPointerException` if either “str” or “prefix” is null.
 then retrieves a similar solution that provides additional context and correct implementation details, with which ChatGPT properly handles “null” values and checks the length of the strings before performing the comparison, thus avoiding the “NullPointerException”.
Overall, with the guidance of retrieved code, LLMs produce higher-quality code that adheres to best practices and avoids common pitfalls. 

Case 2.
Fig. <ref> illustrates an example that fails in the generation-only scenario but succeeds after program repair.
This example requires completing the logic to call “String.trim()” on each element in a given string array.
Similar to the generate-with-retrieval case, CHatGPT overlooks boundary conditions and fails the null-input test case. 
When provided with the dynamic error message, ChatGPT fixes the bug related to missing boundary checks and passes all test cases.

Case 3.
Fig. <ref> illustrates an example only generated corrected with code search and program repair.
This example involves implementing logic that returns true when the given value is “true”, returns false when the given value is “false”, and otherwise returns a specified default value. 
ChatGPT first attempts to generate the solution while ignoring the possibility of a null input, thus causing a NullPointerException. 
After retrieving the reference code, ChatGPT identifies the error and corrects the faulty logic. 
However, it encounters a new issue where it fails to return the correct value in the “false” condition for the same reason. 
Finally equipped with program repair, ChatGPT generates the correct code and finally passes the test.




§ DISCUSSION AND FUTURE WORK


The primary technical innovation in this work is the introduction of a unified automatic programming paradigm that leverages advanced LLMs to integrate three long-explored research areas, code search code generation and program repair.
The preliminary experiments highlight the potential of  in competitive programming problems and real-world programming scenarios.
Particularly, we demonstrate that (1) code search can help code generators produce more accurate code; (2) program repair serves as an effective post-processing step, even after retrieval-augmented code generation; (3) a unified programming pipeline, incorporating the above three phases together, is highly effective in generating code, especially when equipped with LLMs.

As a unified programming pipeline, we believe  has significant potential for the SE community, and can be extended in the following aspects.

Deployment Scenarios.
It is promising to adapt  to more programming scenarios during deployment.
First, there are some domain-specific areas that require developers to possess both programming skills and domain expert knowledge, such as hardware code <cit.>.
 can fully automate such programming process by retrieving similar code within the domain and iteratively refining it, thereby reducing the programming barrier for developers.
Second,  takes natural language descriptions as inputs currently, but it can be implemented with other query formats, such as test cases.
Considering that  treats queries as tokens or embeddings without taking any specific code features into account,  can be applied to the other input formats in a drop-in fashion.
For example, the potential of  in the well-known test-driven development <cit.> is worth investigating, , retrieving similar solutions based on test cases.
Third,  is generic to other code-related tasks, such as test generation, code translation and program repair.


Technical Designs.
The effectiveness of  can be further optimized by improving the quality of retrieved code and refining the prompt engineering for program repair.
First,  employs a straightforward retriever that can be either token-based or embedding-based, depending on whether it focuses on syntax or semantics.
Given the rapid advancements in code search, optimizing these retrieval strategies for greater efficiency is essential.
Second,  directly appends error messages to the generated code as prompts and then queries LLMs for repair. 
In the future, more advanced prompt engineering techniques, such as chain-of-thought, can be utilized.


Evaluation Experiments.
In this study, preliminary experiments demonstrate the effectiveness of .
We only conduct case studies in Section <ref> due to the limitation of real-world programming datasets and retrieval corpora.
Large-scale evaluations with quantitative analysis are necessary in the future.
Besides, the opinions and experiences of developers are crucial for assessing the utility of such programming tools.
We plan to conduct user studies to evaluate  in real-world programming scenarios.
Furthermore, the experiments can be extended in the future with more studied LLMs, benchmarks, and programming languages.






§ CONCLUSION


In this paper, we propose a novel automatic programming framework, , which leverages advanced large language models (LLMs) to integrate three well-established areas: code search, code generation, and program repair. 
Preliminary experiments indicate the potential of our framework to enhance the problem-solving capabilities of existing LLMs in programming tasks. 
Besides, our framework demonstrates the preliminary benefits of combining LLMs with traditional software engineering (SE) areas. 
In the future, more advanced technologies, such as intelligent agents, can be employed to further integrate various SE techniques within the programming framework more effectively.





ACM-Reference-Format



