There are generally two types of programming languages: interpreted and compiled.
There is little difference in terms of the possibilities of the language used, because “compiled programming language” and “interpreted programming language” are not in themselves meaningful word constructs. Any programming language can be interpreted or compiled in principle. Interpretation and compilation are thus rather implementation techniques than characteristics of languages.
Interpretation During Runtime
Interpretation is when another program, the interpreter, executes operations based on your code to be interpreted at runtime.
Imagine being able to read a program using a note sheet to step by step capture the instructions of the source code and translate it into more detailed operations. These operations are then ultimately implemented outside your field of vision and the result is returned to you. This roughly corresponds to the way an interpreter works. Accordingly, an interpreter is also able to monitor programs during their run, and force compliance with higher-level security guidelines.
Compiling: Translating into a “Target Language”
Compiling is a technique whereby a program written in one source language is translated into a multi-equivalent program in another language (the “target language”) and, ideally, in all relevant cases, inevitably produces the same expected results like the source program.
During translation, it is common that the compiler also tries to transform the program in a way that the code in the target language can be executed as efficiently as possible. This may mean that, for example, object-oriented source code is optimized with regard to its execution speed – but without changing its meaning.
In an object-oriented context, significant benefits can be achieved because the OOP concept includes much implicit functionality that is essential at design time but can be greatly compressed after development is complete.
Interpreted and Compiled Programming Complements Eachother
Given the above definitions, it is not difficult to guess that these two implementation techniques are not mutually exclusive – and may even be complementary.
Traditionally, the target language of a compiler was machine code or something similar. Machine language has become established as a generic term for any number of machine-level programming languages that can be executed by the CPU. The machine code would then run “on the hardware” – although on closer inspection one could see that the “hardware” in many ways also works like an interpreter.
An increasingly popular approach is to use a compiler to translate programs into a target language in which they are then to be interpreted – Java, for example, only knew this concept until not so long ago.
Static and Dynamic Programming Languages
There are two types of languages, static and dynamic. In principle, all languages can either be interpreted or compiled, although in everyday work they are often inaccurately referred to as “interpreted language” or “compiled language”.
Compilation can generate native binary or IL bytecode. IL stands for Intermediate Language, which means something like “intermediate language”, which compiles a VM into native code at runtime. This “compile at runtime” is referred to as just-in-time (jit) compiling, as opposed to AOT (ahead-of-time) compilation, which occurs before the program is executed.
In terms of the translation process, JITing is theoretically faster than AOT (which converts to native binary) because more optimizations can still be done at runtime. However, this requires bytecode rather than plain text (like js, which has to be interpreted row by row, as it is dynamic and not strongly typed and thus could not be well optimized, even if it were compiled).
JIT Compilation (Dynamic Translation)
Just-in-time (JIT) compilation, also referred to as dynamic translation, compiles while a program is running – at runtime – rather than before execution.
In many cases, this translation is done in a machine code target language that can be executed directly. A system that implements a JIT compiler typically analyzes the executed code continuously and identifies portions of the code where the compile-time acceleration would outweigh the overhead of compiling that code.
JIT compilation is a combination of the two traditional approaches to machine code translation – namely AOT (Ahead Compilation) and Interpretation – and combines some advantages and disadvantages of both. Roughly speaking, JIT compilation combines the speed advantage of executing compiled code with the inherent flexibility of interpretation – and consistently with the combined overhead of an interpreter and compiler.
It is a form of dynamic compilation that allows for adaptive optimization, such as dynamic recompilation. Therefore, JIT compilation can theoretically achieve faster execution than static compilation. Interpretation and JIT compilation are especially useful for dynamic programming languages because the runtime system can process late-bound data types and enforce security guarantees.
What is an Interpreter?
An interpreter in computer science is a computer program that directly executes instructions written in a programming or scripting language, without first compiling it into a machine language program. An interpreter generally uses one of the following program execution strategies:
- Parse source code and execute it directly
- Translate source code into an efficient intermediate language and execute it immediately.
- Explicitly precompiled and stored code previously generated by a compiler that is part of the interpreter system.
Early versions of the programming languages Lsp and Dartmouth BASIC would be examples of the former type.
Perl, Python, MATLAB, and Ruby are examples of the second, while UCSD Pascal is an example of the third type.
Source programs are pre-compiled and stored as machine-independent code, which is then linked at runtime and executed by an interpreter and / or compiler (for JIT systems).
When designing an application, you may need to decide whether you want to use a compiled language or interpreted language for the source code of your software.
Both types of languages have their own strengths and weaknesses. In general, the decision to use an interpreted language is based on time constraints in development or to make future changes to the program easier.
When using an interpreted language compromises have to be made. Higher development speed and maintenance efficiency are offset by higher execution costs. Since every statement of an interpreted program must be translated at each execution, the effort and thus the hunger for resources is higher than with a compiled program.
Advantages of Compiled Languages
Many common programming languages such as assembler, COBOL, PL / I, C / C ++ – to name but a few – are translated by running the source code through a compiler. This results in very efficient, translated code that can be executed any number of times. The overhead for the translation only occurs once when the source is compiled; after that, the program only has to be loaded and executed.
On the other hand, interpreted languages must be parsed, interpreted, and executed each time the program is executed, which greatly increases the cost of running the program. Because of this, interpreted programs tend to be less efficient than compiled programs.
Some programming languages, such as REXX and Java can either be interpreted or compiled.
Advantages of Interpreted Languages
There are good reasons for using compiled languages as well as reasons for using interpreted languages. There is no simple or even universal answer to the question of which type of language is “better” – it depends essentially on the application.
Even within an application or software project, we could use many different languages of different types.
One of the strengths of a language such as CLIST is that it is really easy to program, test and implement changes. However, the result will often be less efficient at runtime. A compromise here means balancing the use of machine resources against the development time.
In light of this, it may be useful to use a compiled language for the resource-intensive parts of an application, while interfaces (calling the application) and less resource-heavy parts could be written in an interpreted language. An interpreted language might also be suitable for ad-hoc requests or even for prototyping an application.
One of the tasks of a developer is to weigh the strengths and weaknesses of each candidate language and then decide which part of an application is best served by a particular language.
I hope that the differences, advantages and disadvantages of compiled and interpreted programming languages have become clearer.