Grade by Grade
C. Computer Environments and Systems · Computer Environments and Systems

Interpreters and Compilers

C3.4 C3.3About 65 minutes
Learning goals
  • I can explain the difference between an interpreter and a compiler.
  • I can compare them for speed, error reporting, distribution and ease of testing.
  • I can explain how Python and Java combine both ideas using bytecode and a virtual machine.
  • I can use evidence from running programs to show when Python finds syntax errors and when it finds run-time errors.

Words to know

translator
A program that turns source code into a form the computer can run: a compiler, an interpreter or an assembler.
compiler
A translator that converts the whole program into machine code (or bytecode) before it runs, producing a file that can be run many times.
interpreter
A translator that reads and carries out a program one statement at a time, every time it runs.
syntax error
Code that breaks the language's grammar rules, such as a missing bracket or colon.
run-time error
An error that happens while the program is running, such as dividing by zero.
virtual machine
A program that acts like a pretend computer and runs bytecode, such as the Java Virtual Machine or the Python virtual machine.
JIT (just-in-time) compilation
Compiling parts of a program to machine code while it runs, to speed it up.

Translating a book, or translating live?

When a French-language novel from Québec is published in English, a translator works through the whole book, checks it, and produces a finished English version that anyone can read later without the translator. In the House of Commons, interpreters translate speeches between English and French live, sentence by sentence, as members speak; when the speech is over, there is no separate translated book.

Computers have both kinds of translators. A compiler is like the book translator. An interpreter is like the live interpreter. In the last lesson you saw that source code must be translated into machine code; this lesson is about the two ways of doing it.

Compilers

A compiler translates the entire program into machine code before it runs, and saves it as an executable file (such as a .exe on Windows).

  • Errors: it checks the whole program first and lists syntax (and many other) errors before anything runs.
  • Speed: compiled programs usually run fast, because translation was done ahead of time and the compiler can optimize the machine code.
  • Distribution: you can give people the executable. They do not need the compiler or your source code.
  • Downsides: after every change you must compile again, and the executable only runs on the processor type and operating system it was compiled for.
  • Examples: C, C++, Rust, Go and Swift are usually compiled.

Interpreters

An interpreter reads the source code and carries it out one statement at a time, every time the program runs.

  • Errors: a problem may only show up when the interpreter reaches that line.
  • Speed: usually slower than compiled machine code, because translation happens during every run.
  • Testing: very quick to try ideas: change a line and run it again, or type one line at a time into a shell.
  • Distribution: users need the interpreter installed, and they get the source code (or bytecode).
  • Examples: Python, JavaScript, Ruby and PHP are usually interpreted (often with tricks to speed them up).
COMPILER: translate everything first, run latersource codegame.ccompilerwhole programexecutable filemachine codeCPU runs it(again & again)errors listed before it runsno compiler needed to runINTERPRETER: translate and run one statement at a time, every runsource codegame.pyinterpreterreads a statement → runs it→ next statement...output appearsas the program goesan error appears only when its line is reached
A compiler translates the whole program once and saves an executable. An interpreter translates and runs statement by statement, every time.
CompilerInterpreter
When translation happensonce, before the program runsduring every run, statement by statement
Output of translationan executable file of machine codeno separate file; results appear as it runs
Error reportingall syntax errors listed before runningerrors appear when their line is reached
Running speedusually fasterusually slower
Change and re-testmust recompile after each changejust run again
What users needonly the executable (for their platform)the interpreter plus the source code
Typical languagesC, C++, Rust, GoPython, JavaScript, Ruby
Comparing compilers and interpreters.

The middle ground: bytecode and virtual machines

Many modern languages mix the two ideas:

  • Java source code is compiled into bytecode (.class files). The Java Virtual Machine (JVM) on each computer runs the bytecode, and uses just-in-time (JIT) compilation to turn frequently used parts into fast machine code. The same bytecode runs on any computer with a JVM.
  • Python (the standard version, CPython) first compiles the whole file to bytecode. Then the Python virtual machine interprets the bytecode instruction by instruction. For modules you import, Python saves the bytecode in a __pycache__ folder as .pyc files so it can skip the compile step next time.
  • JavaScript in web browsers is interpreted at first and JIT-compiled as it runs.

So "compiled versus interpreted" describes how a language is usually run, not a fixed property of the language.

game.pysource code1. compilewhole file tobytecodebytecode(imports savedas .pyc files)2. Python virtualmachine runs itstep by stepSyntaxError found here:nothing runs at allZeroDivisionError here:earlier lines already ranCPython: a compile step, then an interpreter
How standard Python runs a file: a compile step for the whole file, then an interpreter for the bytecode. This explains the two experiments below.
print("Line 1 runs")
print("Line 2 runs")
print(10 / 0)
print("Line 4 never runs")

Experiment 1: a run-time error. The output is shown first, then the error message (shown in the shell after the output): ZeroDivisionError: division by zero. Lines 1 and 2 ran before the problem line was reached, just as an interpreter would behave. Output (one line each): Line 1 runs / Line 2 runs

print("Line 1 runs")
print("Line 2 runs")
print(10 / 2)
print("Line 4 has a typo"

Experiment 2: a syntax error on the last line. Nothing is printed, not even line 1. The shell shows only SyntaxError: '(' was never closed (wording varies a little between Python versions). Python compiled the whole file first and stopped at the syntax error, the way a compiler would.

Worked example

Example 1: Choose the translator

For each situation, would a compiled language or an interpreted language suit better? Explain.

(a) A company sells a video game and wants it to run as fast as possible without giving away its source code. (b) A student is experimenting with a short program, changing a line and re-running it dozens of times. (c) A web page needs code that runs on every visitor's browser, whatever their computer.

  1. (a) Compiled. Compiled machine code runs fast, and the company can ship the executable without the source code.
  2. (b) Interpreted. No compile step after each change; a shell even lets you test single lines.
  3. (c) Interpreted (JavaScript in the browser, with JIT). Every browser includes the interpreter, so the same code runs on any computer, phone or tablet.

(a) compiled; (b) interpreted; (c) interpreted (with JIT in the browser).

Worked example

Example 2: Predict the output

What does each program print before stopping? Explain using how Python translates code.

Program P:

  1. print("start")
  2. total = 5 + "5"
  3. print("end")

Program Q:

  1. print("start")
  2. if 5 > 3
  3.     print("yes")
  1. Program P is syntactically correct (adding a number and a string follows the grammar), so Python compiles it and starts running. Line 1 prints start. On line 2, the interpreter tries to add 5 and "5" and raises a TypeError (a run-time error). Line 3 never runs.
  2. Program Q has a syntax error on line 2 (the if line is missing its colon). Python's compile step rejects the whole file, so nothing prints, not even start.

P prints start and then stops with a TypeError; Q prints nothing and shows a SyntaxError.

Just for fun

A compiler and an interpreter go to a restaurant. The compiler reads the entire menu, checks every dish for problems, and then orders everything at once. The interpreter orders the first item before reading the second line, and only finds out the kitchen is out of poutine when it gets there.

Hands-on activity

Prove how Python translates

You need: a computer with Python.

  1. Run Experiment 1 and Experiment 2 above. Record exactly what appears.
  2. Move the syntax error in Experiment 2 to line 1 and then to the middle. Does anything print in either case? Explain.
  3. Create a file helper.py containing def hello(): / print("hi from helper"). In the same folder, create main.py with import helper / helper.hello(). Run main.py, then look in the folder: a __pycache__ folder with a .pyc file has appeared. What is in it, and why did Python save it?
  4. Write a short paragraph explaining, with evidence from your experiments, why people say standard Python is "compiled to bytecode, then interpreted."

What to look for: a syntax error anywhere stops the whole file before anything prints; a run-time error lets earlier lines run. The .pyc file holds the compiled bytecode of helper.py, saved so Python can skip the compile step next time. The paragraph should connect each experiment to one step of Python's process.

Your turn

1

What is the main difference between a compiler and an interpreter?

2

Which usually runs faster: compiled machine code or interpreted code? Why?

3

Give one advantage of an interpreter for a beginner.

4

What does a user need to run a compiled program? An interpreted one?

5

In Experiment 1, why did lines 1 and 2 print?

6

In Experiment 2, why did nothing print?

7

What is a .pyc file?

More practice: warm-up

1

Name two languages that are usually compiled.

2

Name two languages that are usually interpreted.

3

What does JIT stand for?

4

What does the Java compiler produce?

5

Is a missing colon a syntax error or a run-time error?

More practice: on your own

1

What does this print before it stops? print("A") / x = int("seven") / print("B")

2

Why must a compiled C program be recompiled to run on an ARM computer, while a Python script does not need any change?

3

A game company ships updates often. Explain one advantage and one disadvantage of using a compiled language for the game.

4

Explain the book-translator and House of Commons analogy for compilers and interpreters in your own words.

5

Is this statement true? "Python is purely interpreted." Explain.

Challenge

1

A Python program has a bug in a function that is only called on February 29. Explain why testing on other days might never reveal it, and how a compiler might have helped (or not).

2

Explain how the JVM's JIT compilation tries to get the best of both worlds.

3

Predict the output and explain:

  1. def f():
  2.     return 1 / 0
  3. print("before")
  4. print("still fine")
Check your understanding

Quiz

1.

Which translator converts the whole program to machine code before it runs and produces an executable file?

2.

Which is usually an advantage of an interpreter?

3.

A Python file has a syntax error on its last line. What happens when you run it?

4.

print("A") then print(1/0) then print("B"). What appears?

5.

Java source code is compiled into...

6.

Why might a company prefer to ship a compiled program?

For parents and teachers

Big idea: Expectation C3.4 asks students to explain the difference between an interpreter and a compiler. The two experiments give evidence, which is stronger than a memorized definition: Python compiles a whole file to bytecode (so syntax errors stop everything) and then interprets it (so run-time errors appear only when reached).

How to help: Ask your teen to explain the book-translator and House of Commons analogy to you, then show you the two experiments. Ask, "If I gave you a program with a typo on the last line, what would happen?"

Common difficulties:

  • Saying a language is compiled or interpreted; it is really about how it is usually run.
  • Thinking Python is purely interpreted (the syntax-error experiment shows the compile step).
  • Mixing up syntax errors (grammar, found before running) and run-time errors (found while running).