Translation
IB Syllabus: A1.4.1 (HL) – Evaluate the translation processes of interpreters and compilers
HL Only: This page covers content assessed only at Higher Level.
Table of Contents
- Key Concepts
- Worked Examples
- Quick Check
- Trace Exercise
- Spot the Error
- Fill in the Blanks
- Scenario Check
- Practice Exercises
- Connections
Key Concepts
What is Translation? (A1.4.1)
Computers can only execute machine code – binary instructions specific to a particular processor. But programmers write in high-level languages (Java, Python, C) that are readable by humans. A translator is software that converts source code into a form the computer can execute.
There are three types of translator:
| Translator | Input | Output | How it works |
|---|---|---|---|
| Compiler | High-level source code | Machine code (object code) | Translates the entire program before execution |
| Interpreter | High-level source code | Executes directly | Translates and executes one line at a time |
| Assembler | Assembly language | Machine code | One-to-one translation of mnemonics to binary |
Compilers
A compiler translates the entire source code into machine code (object code) all at once, before the program runs.
- The programmer writes source code (e.g.,
program.c) - The compiler translates the entire file, checking for syntax errors
- If errors are found, it produces an error report listing all detected errors – the program is not compiled
- If successful, it produces an executable file (object code) that can run independently
- The executable can be distributed and run without the compiler or source code
Key characteristics:
- Errors are detected before the program runs (at compile time)
- The compiled executable runs fast because translation is already done
- Must recompile after every change to the source code
- The executable is platform-specific – compiled for one type of processor/OS
Languages that use compilation: C, C++, Rust, Go
Interpreters
An interpreter translates and executes source code one line at a time, without producing a separate executable file.
- The interpreter reads the first line of source code
- It translates that line to machine code and executes it immediately
- If an error is found on that line, execution stops and the error is reported
- If no error, it moves to the next line
- This repeats until the program ends or an error is encountered
Key characteristics:
- Errors are detected during execution (at runtime) – the program runs until it hits a problem
- No executable is produced – the source code must be interpreted every time the program runs
- Changes take effect immediately – no recompilation needed
- Execution is slower because translation happens every time
- The interpreter must be installed on any machine that runs the program
Languages that use interpretation: Python, Ruby, PHP, JavaScript (traditionally)
Compiler vs Interpreter Comparison
| Feature | Compiler | Interpreter |
|---|---|---|
| Translation | Whole program at once | Line by line |
| Speed of execution | Fast (already translated) | Slower (translates each time) |
| Error detection | All errors reported before running | Stops at the first error encountered |
| Output | Executable file (object code) | No executable produced |
| Debugging | Harder – errors listed after full compile | Easier – error points to the exact line |
| Distribution | Can share executable without source | Must share source code + interpreter |
| After changes | Must recompile | Runs immediately |
| Portability | Platform-specific executable | Runs anywhere the interpreter is installed |
A retro animated introduction to how interpreters and compilers translate programs. (3:35)
Just-In-Time (JIT) Compilation
Some modern systems use JIT compilation, a hybrid approach that combines aspects of both compilation and interpretation.
- Source code is first compiled to an intermediate form (bytecode) – not full machine code
- At runtime, a JIT compiler translates frequently-used sections of bytecode into native machine code
- These compiled sections are cached so they do not need to be recompiled on subsequent calls
- Less frequently-used code may continue to be interpreted
Why JIT? It aims to combine the portability of interpretation with the speed of compilation. The first run is slower (translation overhead), but performance improves as more code is JIT-compiled.
Example: Modern JavaScript engines (V8 in Chrome, SpiderMonkey in Firefox) use JIT compilation. JavaScript code is initially interpreted, but “hot” functions that run frequently are compiled to optimized machine code at runtime.
Bytecode Interpreters and the JVM
Bytecode is an intermediate representation that sits between high-level source code and machine code. It is designed to be executed by a virtual machine rather than directly by hardware.
The most well-known example is Java and the Java Virtual Machine (JVM):
Your Code (.java) --> Compiler (javac) --> Bytecode (.class) --> JVM --> Output
- The Java compiler (
javac) compiles source code into bytecode (.classfiles) - Bytecode is platform-independent – it is not specific to any processor
- The JVM reads the bytecode and executes it on the local machine
- Modern JVMs include a JIT compiler that compiles frequently-used bytecode into native machine code for speed
Why two steps? Different machines have different instruction sets (recall CPU Architecture). By compiling to bytecode first, Java achieves “write once, run anywhere” – the same .class file runs on Windows, macOS, or Linux, as long as a JVM is installed.
You saw this in action when you first set up Java in Programming Fundamentals – the javac command compiled your .java files, and the java command launched the JVM to execute the bytecode.
Choosing a Translation Method: Three Scenarios
The IB syllabus requires you to evaluate which translation method fits specific scenarios. Consider these three:
Scenario 1: Rapid Development and Testing
Best fit: Interpreter (or interpreted language)
When developing and testing frequently, the edit-run cycle matters most. Interpreters allow programmers to make a change and see the result immediately without waiting for compilation. This is why data scientists use Python – they can test snippets interactively and see results line by line.
Real-world example: Katie Bouman’s team used Python to develop the algorithm that produced the first image of a black hole. The interpreted nature of Python allowed rapid experimentation and testing with different approaches.
Scenario 2: Performance-Critical Applications
Best fit: Compiler (or compiled language)
When execution speed is the priority, compiled code wins. The translation is done once, and the resulting executable runs at native speed without any translation overhead. Operating systems, game engines, and embedded systems are typically written in compiled languages.
Real-world example: The Linux kernel is written in C and compiled for each target platform. The compiled machine code executes with minimal overhead, which is essential for an operating system handling thousands of tasks per second.
Scenario 3: Cross-Platform Development
Best fit: Bytecode + Virtual Machine (hybrid approach)
When the same program needs to run on multiple platforms, a bytecode-based approach avoids compiling separate executables for each platform. The bytecode is portable; only the virtual machine needs to be platform-specific.
Real-world example: Java applications run on Windows, macOS, Linux, and Android via the JVM. Enterprise software often uses Java precisely because it does not need to be recompiled for each customer’s platform.
Worked Examples
Example 1: Matching Translation to Scenario
Problem: A game studio is developing a 3D game engine that must process millions of polygons per frame at 60 FPS. Which translation approach should they use? Justify your answer.
Show answer
Answer: They should use a compiled language (such as C++). The game engine is performance-critical – it needs to execute as fast as possible with minimal overhead. A compiler translates the code once into optimized machine code that runs at native speed. An interpreter would add translation overhead on every frame, making 60 FPS unachievable. While this means recompiling after changes (slower development), the execution performance is essential for the final product.
Example 2: Evaluating Trade-offs
Problem: A university wants students on different operating systems (Windows, macOS, Linux) to run the same programming assignments. Evaluate whether they should use a compiled, interpreted, or bytecode-based language.
Show answer
Answer:
- Compiled (e.g., C): Students would need to compile separately on each OS. Different compilers may produce different results. Distribution and setup is complex. Not ideal.
- Interpreted (e.g., Python): Students install the Python interpreter on their OS. The same
.pyfiles run everywhere. Easy to set up. However, execution is slower. Good fit for educational purposes where speed is not critical. - Bytecode + VM (e.g., Java): Students install the JVM. The same
.classfiles run on all platforms. Execution is faster than pure interpretation due to JIT. Setup is more complex than Python. Also a good fit, especially if performance matters.
Recommendation: Either interpreted (Python) or bytecode (Java) would work well. The choice depends on whether the course prioritizes ease of setup (Python) or performance and industry relevance (Java).
Example 3: Error Detection Comparison
Problem: A programmer writes a 500-line program with syntax errors on lines 120 and 380. Compare how a compiler and an interpreter would handle these errors.
Show answer
Answer:
- Compiler: The compiler scans the entire program before execution. It detects both syntax errors (line 120 and line 380) and reports them together in an error list. The program does not run at all until both errors are fixed and the code is recompiled.
- Interpreter: The program starts executing from line 1. Lines 1-119 run successfully. When the interpreter reaches line 120, it stops and reports the first syntax error. The programmer fixes it and re-runs the program. This time, lines 1-379 run before the interpreter stops at line 380 and reports the second error. Two separate runs are needed to find both errors.
Key difference: The compiler catches all syntax errors upfront in one pass. The interpreter reveals them one at a time across multiple runs.
Quick Check
Q1. What is the main difference between a compiler and an interpreter?
Q2. What does JIT (Just-In-Time) compilation do?
Q3. A program has errors on lines 10 and 50. When using an interpreter, what happens?
Q4. Why is Java described as "write once, run anywhere"?
Q5. Which is a disadvantage of using an interpreter?
Q6. Which translation method is best suited for rapid development and testing?
Trace Exercise
A Java program goes through several translation stages. Trace the translation pipeline by identifying the translator and its output at each stage.
| Stage | Input | Translator | Output |
|---|---|---|---|
| 1 | HelloWorld.java (source code) | (.class file) | |
| 2 | HelloWorld.class (bytecode) | (platform-specific) |
Spot the Error
A student wrote the following description of how a compiler works. Click the line with the error, then pick the fix.
Pick the correct fix for this line:
Fill in the Blanks
Complete the following statements about translation processes:
Translation Types
=================
A translates the entire program before execution.
An translates and executes one line at a time.
Java Translation Pipeline
=========================
javac compiles .java files into (.class files).
The executes bytecode on any platform.
Hybrid Translation
==================
Java compiles source code to bytecode first, then the JVM translates it further at .
This hybrid approach is called (Just-In-Time) compilation. Scenario Check
Q7. Why is bytecode described as platform-independent?
Q8. A company wants one version of their software to run on Windows, macOS, and Linux. Which approach best supports this?
Practice Exercises
Core
-
Define and compare – State two differences between a compiler and an interpreter. For each difference, explain which approach is better and why.
- Translation matching – For each scenario, state whether a compiler, interpreter, or bytecode+VM approach would be most suitable. Justify each answer:
- A bank deploying the same server software on Windows and Linux machines
- A student learning to code who wants to test small snippets quickly
- A company writing firmware for a medical device where execution speed is critical
- Java pipeline – Draw a diagram showing the stages of Java translation from
.javafile to program output. Label each stage and name the tool or component responsible.
Extension
-
JIT evaluation – Explain how JIT compilation aims to provide “the best of both worlds” between compilation and interpretation. What are the trade-offs compared to pure compilation?
-
Error detection essay – A 200-line program has syntax errors on lines 50 and 150. Compare and contrast how a compiler and an interpreter would handle these errors. Which approach would help the programmer fix the code more efficiently? Justify your answer.
-
Portability argument – A company distributes compiled C++ executables for Windows. They now want to support macOS and Linux as well. Evaluate three possible solutions: (a) compile separately for each platform, (b) rewrite in Python, (c) rewrite in Java. Discuss the trade-offs of each approach.
Challenge
-
Translation in practice – Research one real programming language that uses each translation method: (a) purely compiled, (b) purely interpreted, (c) bytecode + JIT. For each, explain how the translation method influences the language’s typical use cases, performance characteristics, and developer experience.
-
Evaluate the statement: “Modern languages make the distinction between compilers and interpreters obsolete.” To what extent do you agree? Reference JIT compilation, bytecode interpreters, and specific language implementations in your answer.
Connections
- You already know this: In Programming Fundamentals, you used
javacto compile Java source code to bytecode and the JVM to execute it – this is the bytecode + VM approach in action - Related: CPU Architecture – the CPU executes the native machine code that translators ultimately produce; different CPU architectures need different machine code, which is why portability matters
- Related: OS Fundamentals – the operating system manages execution of translated programs, loading executables into memory and scheduling them for the CPU
- Forward: Debugging (Programming Fundamentals: Debugging) – understanding when errors are detected (compile-time vs runtime) directly relates to how compilers and interpreters handle errors differently