BACKGROUND

Computer software programming often requires developers to read and/or write source code (i.e., to program) in a specific higher-level programming language. Some non-limiting examples of higher-level programming languages include Java, C++, C, Python, Perl, etc.—each of which can have its own strengths, weaknesses, nuances, idiosyncrasies, etc.

Many programmers obtain at least a superficial understanding of multiple programming languages, but only master a few. Consequently, this can cause problems when an entity (e.g., a company) wants to translate code from a base higher-level programming language to a different target programming language. For example, existing programmers at the entity may lack expertise in the target programming language and be unable to manually translate the code and/or can be highly inefficient in doing so. The inefficiencies can lead to excess usage of client device resources utilized in translating the code. Put another way, the inefficiencies can result in a client device, being used in manually translating the code, to be on and/or in a higher-powered state for prolonged periods. Even if new programmer(s) familiar with the target language were brought in for the translating, manually translating is nonetheless still inefficient, at least due to the new programmers being unfamiliar with the semantics of the base code being translated. Even outside of the automatic translating context, excess usage of client device resources can also occur when programmers attempt to code in a new language with which they have lesser expertise relative to other language(s). This can be due to the programmers being slower when coding in the new language which, in turn, prolongs the duration that client device resource(s) need to be active when coding in the new language.

SUMMARY

Implementations disclosed herein relate to utilization of machine learning model(s) (e.g., neural network model(s)) in automatically translating source code in a “base” programming language to source code in another programming language, or “target” programming language. Implementations disclosed herein can enable automatic translation of source code from the base programming language to the target programming language, while mitigating the amount of programmer time (and corresponding client device usage) that is involved. For example, some or all snippets of source code can be translated from the base programming language to the target programming language, without requiring any human intervention. For instance, a translated target language snippet can optionally be presented to a programmer for review and potential editing, but the programmer will not be involved in the generation of the translated target language snippet.

As described herein, the machine learning model(s) that are utilized in translating base source code to target source code can be trained based on actual human-created code. As a result, generated target source code snippets can be more natural and, as a result, comprehensible by developers in a more efficient manner—which results in more efficient usage of client device resource(s) in reviewing and/or editing the target source code snippets. For example, generated target source code snippets can be more natural than those generated using only rules-based approaches.

Implementations disclosed herein can additionally or alternatively enable programmers who might be unfamiliar with a base programming language to nonetheless view and/or edit source code written in the base programming language by translating the source code to another programming language that is more familiar to the programmer.

Implementations disclosed herein can additionally or alternatively enable generating source code in a target language based on only a previously generated lower-level compiled representation. For example, the lower-level compiled representation can be assembly code or bytecode, and could have been previously generated by processing the corresponding base source code (in the target language or another language) using a compiler. Accordingly, those implementations enable generating the source code in the target language using the lower-level representation and without requiring any access to the base source code on which it is based.

In implementations that automatically translate a base source code snippet, programmed in a base programming language (e.g., C++), the base source code snippet can be compiled, using a compiler for the base programming language, to generate a lower-level compiled representation thereof. As used herein, the “lower-level compiled representation” can refer to bytecode, object code, binary code, assembly code, and/or any other representation of source code that is less human-readable than source code from which the low-level representation was generated.

The lower-level compiled representation can then be processed, using a “neural decompiler”. The neural decompiler can be a machine learning model trained to decompile lower-level representations to a target higher-level programming language (e.g., Python), to generate output(s). For example, the machine learning model can be a sequence-to-sequence neural network model that processes the lower-level compiled representation to generate a sequence of outputs, such as a sequence of outputs that each include a probability distribution over tokens. For instance, the neural network model can be a transformer or can be a recurrent neural network (RNN) encoder-decoder model that include memory layer(s) (e.g., long short-term (LSTM) layer(s). Each of the tokens can be a word, word piece, symbol, and/or other token, and the tokens can include those that form a lexicon of the target higher-level programming language, and optionally other tokens (e.g., end of code snippet symbols, canonical variables and/or other variables, etc.).

In various implementations, the machine learning model can be trained based on training instances that each include labeled training instance output of a target source code snippet that is in a target programming language, and training instance input that is a lower-level compiled representation of the target source code snippet. The training instances can be generated by identifying (e.g., from code repositories) target source code snippets, and compiling the target source code snippets using a compiler for the target higher-level programming language. Each training instance can include a target source code snippet (as output), and its corresponding lower-level compiled representation. As one example, all or portions of target source code, for a corresponding function of a program, can be compiled, using a compiler for the target source code, to generate a lower-level representation of the all or portions of the target source code. Further, metadata from the compiler can be utilized to determine correspondences between target source code snippets and corresponding snippets of the lower-level representation. Such correspondences can be used to generate pairing of target source code snippets and corresponding snippets of the lower-level representation. For example, the compiler metadata can indicate, for each line and/or expression (or even sub-expression) of the target source code, which line(s) of the lower-level representation correspond thereto. Accordingly, the compiler metadata can be used to generate training instances that each include corresponding line(s) and/or expression(s) (or sub-expression(s)) of the target source code and line(s) of the lower-level representation.

A target source code snippet, in the target language, can be generated by processing, using the neural decompiler, a lower-level compiled representation (e.g., a lower-level compiled representation of a base source code snippet) to generate output(s). For example, where the output(s) include a sequence of output(s), the target source code snippet can be generated, token-by-token, by selecting the highest probability token for each output of the sequence.

The generated target source code snippet can then be rendered as output of a software development application for optional review and/or editing by developer(s). For example, an entire program, or module, can be automatically translated from a base programming language (e.g., C++) to a target language (e.g., Python) by automatically translating snippets as described above. Each of the snippets can be, for example, a line of code, a portion of a line of code, multiple lines of code, and/or other contiguous portion of code.

In some implementations that translate a base source code snippet to a target source code snippet, the base source code snippet that is compiled can be a modified base source code snippet that is generated by replacing occurrences of each of any variables in the snippet, with a corresponding canonical representation selected from a closed set of canonical representations. For example, the base source code snippet “char a123=‘a’” can be modified by replacing the variable “a123” with the canonical representation “v1”, resulting in the modified base source code snippet “char v1=‘a’”. Accordingly, the lower-level compiled representation will be generated based on the canonical representation “v1” in lieu of the actual variable “a123”. It is noted that the canonical representation “v1” may or may not actually be present in the lower-level compiled representation but, nonetheless, the lower-level compiled representation will be influenced by inclusion of “v1” in lieu of “a123”.

Further, the training instances used in training the neural decompiler can additionally or alternatively be trained based on training instances that include similarly generated canonicalized target source code snippets and lower-level representations based on those canonicalized target source code snippets. The canonicalized target source code snippets can be generated by replacing occurrences of each of any variable, in an initial target source code snippet, with a corresponding canonical representation. The canonical representations used in replacing variables, in target source code snippets, in generating canonicalized target source code snippets for use in training instances, can also be selected from a closed set of canonical representations. That closed set can be the same as, or different from, the closed set used in generating the modified base source code snippets. As one example, assume a target source code snippet of “double add(height, height)”. A canonicalized target source code snippet of “double add(x1, x1)” can be generated that replaces the variable “height” with the canonicalized representation of “x1” (e.g., selected from a closed set of (x1, x2, . . . , x10). As another example, assume a target source code snippet of “double add(double height, double width)”. A canonicalized target source code snippet of “double add(double x1, double x2)” can be generated that replaces the variable “height” with the canonicalized representation of “x1” and that replaces the variable “width” with “x2”.

Accordingly, the neural decompiler can be trained to process lower-level code that is generated based on snippets that include the canonical representations (the same as or different from those used in modifying the base source code snippets) in lieu of actual variable names, and to generate target source code snippets that include the canonical representations in lieu of actual variable names. Training the neural decompiler based at least in part on (or even exclusively based on) canonicalized training instances can result in the neural decompiler being trained more efficiently (i.e., requiring fewer training instances) and/or can lead to the neural decompiler being more robust and/or more accurate. This can be due to the canonicalizations enabling training of the neural decompiler to focus on predicting the non-variable portions and only a closed set of a limited quantity (e.g., 20 or fewer, 10 or fewer) of canonical representations of variable(s) without needing to focus on predicting disparate variables. Further, this can also enable the output space (e.g., the quantity of tokens) of the neural decompiler to be more constrained as token(s) that may be present in initial variables, but are not included in the lexicon of the target programming language, need not be represented in the output space. For example, the neural decompiler can be trained exclusively based on canonicalized training instances and can include, in its lexicon, canonical representations of variables without including certain token(s) that would be needed to represent other variables. In addition to making the neural decompiler more compact, this can enable more efficient training of the neural decompiler and/or the neural decompiler to be more robust as it enables the neural decompiler to be trained and/or utilized independent of variable name choice.

Accordingly, training the neural decompiler based on canonical representations can result in predicted target source code snippets, generated using the neural decompiler, being more likely to include (or restricted to including) canonical representations to represent variable(s) in predicted target source code snippet(s). The canonical representation(s), present in the initial predicted target source code snippets generated using the trained neural decompiler, can then be replaced with the corresponding variable names from the base source code snippet—resulting in a modified target source code snippet. The modified target source code snippet can then be the one that is presented to developer(s) in a developer interface. In these and other manners, the viewed translated modified target source code snippets will be more intelligible when reviewed by developer(s) and, further, will maintain consistent variable names with other translated target source code snippets. Yet further, using the canonical representations, in lieu of the actual variable names, can enable the neural decompiler to be more robust and/or trained more quickly.

It is noted that, in various implementations, there will not be a strict 1:1 mapping between the canonical representation(s) of the base code snippet and the canonical representation(s) of the source code snippet. For example, assume canonical representations of “v1” for a first variable and “v2” for a second variable, in the base source code snippet. There may not be a guarantee that “v1” in the initial target source code snippet generated using the neural decompiler corresponds to “v1” in the base source code snippet and it may even be the case that “v1” is not even present in the initial target source code snippet. For example, “v3” or “x1” or other canonical representation may be present in the initial target source code snippet in lieu of “v1”. When there is only one variable in the base source code snippet, and only one canonical representation (matching or not) in the initial target source code snippet, it can easily be determined that the canonical representation in the initial target source snippet matches the variable of the base source code snippet. However, when multiple variables are present in the base source code snippet, it can be more difficult to match canonical representations of an initial predicted target source code snippet to corresponding variables in the base source code snippet.

In view of these and/or other considerations, one or more techniques can be utilized to ensure a “match” of canonical representations, of an initial target source code snippet, to variables of the base source code snippet, in generating the modified target source code snippet. This can include considering the sequential order of the variables in the base source code snippet and the sequential order of the canonical representations in the initial target source code snippet. This can additionally or alternatively include considering corresponding types assigned to the variables in the base source code snippet and types assigned to the canonical representations in the initial target source code snippet. This can additionally or alternatively include considering other portion(s) of code preceding and/or following the variables in the base source code snippet and other portion(s) of code preceding and/or following the canonical representations in the initial target source code snippet. This can additionally or alternatively include, for a given variable mapping in the target source code snippet (i.e., a given replacement of canonical representations with variables), generating output(s) that are each based on executing the target source code snippet (with the given variable mapping) with test input(s) (e.g., certain values for the variables). Output(s) can likewise be generated for the initial base source code snippet, using the same test input(s). The base output(s) generated for the base source code snippet can be compared to the target output(s) generated for the target source code snippet. If the base output(s) match the target output(s), this can indicate that the given variable mapping is correct—and it can be utilized.

In some additional or alternative implementations, where the output(s) from the neural decompiler include a sequence of output(s) and probability distributions, an additional target source code snippet can be at least selectively generated by selecting token(s) that are not the highest probability token for the output(s) of the sequence. For example, an additional target source code snippet can include one or more (e.g., a subset or all) of the second-highest probability tokens in lieu of the highest probability tokens.

In some of those implementations, the additional target source code snippet can be selectively utilized, in lieu of the higher probability target source code snippet that is based on the highest probability tokens. For example, the additional snippet can be utilized if it conforms more closely to syntax of the target programming language than does the initial target source code snippet. As another example, the additional snippet can be utilized if it can be compiled using compiler(s) for the target programming language whereas the initial target source code snippet cannot be compiled using the compiler(s) (e.g., it generates error(s)).

As yet another example, the base source code snippet can additionally or alternatively be executed (e.g., compiled then executed), with given value(s) for any variable(s), to generate base source code output. Further, the highest probability source code snippet can likewise be executed to generate first target output and the additional target source code snippet can likewise be executed to generate second target output. If the first target output fails to match the base source code output, but the second target output (for the additional target source code snippet) matches the base source code output (or matches it more closely), the additional source code snippet can be utilized in lieu of the highest probability source code snippet.

As yet another example, an embedding for the base source code snippet can additionally or alternatively be generated (e.g., using code2vec or other model(s)), and embeddings similarly generated for the initial target source code snippet and the additional target source code snippet. The additional target source code snippet can be utilized, in lieu of the initial target source code snippet, based on its embedding being closer (distance-wise in embedding space) to the base source code snippet than is the embedding for the initial target source code snippet. In these and other manners multiple candidate target snippets can be generated utilizing the neural decompiler, evaluated according to one or more criteria, and the best (according to the evaluation) target snippet selected for presentation in a developer interface. In some implementations the additional target source code snippet(s) are only generated and/or evaluated responsive to determining that the highest probability target source code snippet fails to satisfy one or more criteria.

The preceding is provided as an overview of only some implementations disclosed herein. These and other implementations are described in additional detail in the detailed description.

It should be appreciated that all combinations of the foregoing concepts and additional concepts described in greater detail herein are contemplated as being part of the subject matter disclosed herein. For example, all combinations of claimed subject matter appearing at the end of this disclosure are contemplated as being part of the subject matter disclosed herein.

