There are two general approaches to programming language implementation:[1] An interpreter is composed of two parts: a parser and an evaluator.
[4] To improve their efficiencies, many programming languages such as Java,[4] Python,[5] and C#[6] are compiled to bytecode before being interpreted.
Some virtual machines include a just-in-time (JIT) compiler to improve the efficiency of bytecode execution.
The optimizer improves the intermediate representation to increase the speed or reduce the size of the executable which is ultimately produced by the compiler.
[2] Many combinations of interpretation and compilation are possible, and many modern programming language implementations include elements of both.