Let's introduce at this point some concepts of execution of programs written in high level programming languages. As we have already seen, the only language that a computer can understand is the so called machine language. These languages are composed of a set of basic operations whose execution is implemented in the hardware of the processor. We have also seen that high level programming languages provide a machine-independent level of abstraction that is higher than the machine language. Therefore, they are more adapted to a human-machine interaction. But this also implies that there is a sort of translator between the high level programming language and the machine languages. There exists two sorts of translators:
An Interpreter is a program that implements or simulates a virtual machine using the base set of instructions of a programming language as its machine language.
You can also think of an Interpreter as a program that implements a library containing the implementation of the basic instruction set of a programming language in machine language.
An Interpreter reads the statements of a program, analyzes them and then executes them on the virtual machine by calling the corresponding instructions of the library.
Interactive interpreter session
During an interactive interpreter session the statements are not only read, analyzed and executed but the result of the evaluation of an expression is also printed. This is also called a READ - EVAL - PRINT loop.
A Compiler is a program that translates code of a programming language in machine code, also called object code. The object code can be executed directly on the machine where it was compiled.
Figure 5.1 compares the usage of interpreters and compilers.
So using a compiler separates translation and execution of a program. In contrast of an interpreted program the source code is translated only once.
The object code is machine-dependent meaning that the compiled program can only be executed on a machine for which it has been compiled, whereas an interpreted program is not machine-dependent because the machine-dependent part is in the interpreter itself.
Figure 5.2 illustrates another concept of program execution that tries to combine the advantage of more effective execution of compiled code and the advantage of machine-independence of interpreted code. This concept is used by the JAVA programming language for example and in a more subtle way by Python.
In this case the source code is translated by a compiler in a sort of object code, also called byte code that is then executed by an interpreter implementing a virtual machine using this byte code. The execution of the byte code is faster than the interpretation of the source code, because the major part of the analysis and verification of the source code is done during the compilation step. But the byte code is still machine-independent because the machine-dependent part is implemented in the virtual machine. We will see later how this concept is used in Python (Section 14.1).