Code Basics logo

Что такое интерпретатор?

В этом гайде разберемся, что такое интерпретатор, для чего он нужен и как работает. Этот материал поможет понять, как компьютер выполняет программы.

Зачем нужен интерпретатор

В переводе с английского языка компьютер — вычислитель. Мы привыкли пользоваться компьютером для подготовки документы, чтения новостей и просмотра фильмов. В повседневной жизни производить вычисления приходится крайне редко, поэтому такое определение может показаться странным.

Вместе с тем, это название очень точно отражает природу компьютера. Мы этого не видим, но на самом деле компьютер умеет работать только с числами: документы, и новости, и фильмы выглядят для компьютера как наборы чисел. То же самое касается программ, которые он выполняет.

Каждая команда имеет свой числовой — машинный — код: благодаря ему компьютер без труда понимает, что нужно делать. Человеку трудно писать программы в машинных кодах, однако на заре компьютерной эры программисты писали именно так. Вот так выглядели их программы:

102 184 0 0
102 185 100 0
102 1 200
102 73
102 131 249 0
117 245

Пытаясь облегчить себе работу, программисты придумали языки программирования: они понятнее человеку, поэтому писать программы на них проще. На этом этапе возникла проблема: если компьютер понимает команды только в виде чисел, как он будет выполнять команды, написанные на языке программирования?

Есть два вида программ, которые помогают решить эту проблему — интерпретаторы и компиляторы. Про компилятор можно почитать здесь, в этом тексте мы остановимся только на интерпретаторах.

Вкратце, интерпретатор — это программа, которая выполняет команды, написанные на каком-то языке программирования. Например, интерпретатор Python понимает команды языка Python, а интерпретатор JavaScript — команды языка JavaScript.

Экскурс в историю

Lisp оказался удачным изобретением. За прошедшие годы люди изобрели множество языков, которые оказались никому не нужны. Этого нельзя сказать о Lisp, который развивается до сих пор. Уточню, что разработкой интерпретаторов Lisp занимались разные команды, поэтому у них получались разные версии языка. Такие версии языка называют диалектами. Кроме Emacs Lisp, вы могли слышать о ClojureScript — диалекте LISP, который иногда используют вместо JavaScript при разработке фронтенда

Рассмотрим пример программы на Lisp для понимания разницы между машинным кодом и «почти человеческим языком»:

(defun sum (n)
    (if (= n 0)
        0
        (+ n (sum (- n 1)))))

(sum 100)

Необязательно знать Lisp, чтобы увидеть, что в программе есть структура, и понять отдельные ее части. Доступность для понимания — выгодное преимущество языков программирования перед машинным кодом.

Есть интерпретаторы для таких популярных языков программирования, как Python и JavaScript. Они хорошо подходят и для работы, и для изучения программирования. Важную роль в этом играет то, что для них существует интерпретаторы, и чуть позже мы узнаем, почему это так.

Пример интерпретатора Python

Разберем в деталях работу интерпретатора — для этого напишем несложную программу, которая будет вычислять суммы чисел от 1 до 100:

sum = 0
for i in range(1, 101):
  sum = sum + i
print(sum) # => 5050

Запустим интерпретатор python и построчно введем программу.

Пример работы интерпретатора Python

Мы видим, что начале каждой строки интерпретатор выводит подсказку >>>. Когда мы вводим команду for, состоящую из двух строк, подсказка меняется на троеточие ....

Выполняя команду print(sum), интерпретатор печатает результат — число 5050. Если мы допустим ошибку, интерпретатор подскажет нам, где она находится.

Пример ошибки в программе

В примере выше мы забыли поставить двоеточие после инструкции for, о чем интерпретатор и сообщает.

Немедленный отклик интерпретатора очень важен при изучении языка. Новички, видя сообщениях об ошибках и пробуя разные варианты, быстро осваивают незнакомый синтаксис. Именно поэтому Python и JavaScript часто используют для обучения.

Опытные программисты также ценят такой — интерактивный — способ разработки, потому что он помогает быстро проверять свои идеи.

Кроме того, интерпретируемые языки часто используют для разработки прототипов больших программ. В интерактивном режиме он постоянно выполняет одни и те же действия: читает команду программиста, выполняет ее и печатает результат. Такой режим называют Циклом Чтения-Выполнения-Печати, или, по-английски Read-Evaluate-Print Loop. Обычно это название сокращают до аббревиатуры REPL.

Цикл Чтения-Выполнения-Печати

Пример интерпретатора JavaScript

Интерпретатор JavaScript встроен прямо в браузер. Посмотрим, как он работает, на примере браузера Chrome.

В правом верхнем углу есть три вертикальные точки, которые вызывают меню браузера. Нажмите и выберите пункт меню Дополнительные инструменты, а затем Инструменты разработчика.

Инструменты разработчика Chrome

Вы увидите новое окно, заполненное вкладками. Все эти инструменты полезны и их стоит освоить. Но сейчас нам нужна одна вкладка — Console. В консоли мы можем набирать команды языка JavaScript и сразу видеть отклик интерпретатора.

a = 1; // => 1
b = 2; // => 2
3 * (a + b); // => 9

Интерпретатор сохранит переменные a и b со значениями 1 и 2, затем вычислит значение 3 * (a + b) и напечатает результат 9.

Консоль Chrome

Выполнение программы

Цикл REPL помогает разрабатывать программу, но вводить каждую команду по отдельности не удобно: куда быстрее ввести их один раз, а затем запустить готовую программу. Для этого создадим текстовый файл sum.py и запишем там команды:

sum = 0

for i in range(1, 101):
  sum = sum + i

print(sum)

Чтобы выполнить программу, достаточно запустить интерпретатор Python, указав имя файла в параметрах:

> python sum.py
5050

Интерпретатор выполняет команды одну за одной и в конце завершает свою работу. Такой режим работы интерпретатора называют пакетным.

Таким образом, интерпретатор может работать в двух режимах. Интерактивный режим (REPL) помогает нам проверять идеи и придумывать решение задач. Пакетный режим выполняет готовую программу.

Устройство интерпретатора

Есть много способов написать интерпретатор. Не будем рассматривать все возможные варианты, а остановимся на устройстве интерпретаторов в целом. Обычный язык программирования содержит несколько десятков команд.

В программе на Python, которую мы обсуждали выше есть операторы присваивания, цикл for и вызов функции print. Все это — команды, которые понимает интерпретатор Python. Для каждой команды в интерпретаторе есть блок кода, который умеет такую команду исполнять.

Вторая важная составляющая интерпретатора — анализатор текста. Когда программист вводит текст, анализатор разбирает его на составные части и понимает, о какой команде идет речь. После этого он передает управление блоку, отвечающему за выполнение этой команды.

Так — в цикле — интерпретатор и работает. Анализирует введенную команду, затем выполняет, снова анализирует и снова выполняет. Анализ текста это, конечно, не тривиальная задача, но и не слишком трудная, так что интерпретаторы на самом деле не такие сложные программы.

Как работает интерпретатор

Достоинства и недостатки

Достоинства интерпретаторов:

  • Простота изучения. REPL помогает проверять, как работают незнакомые конструкции и быстро осваивать синтаксис языка.

  • Простота программирования. Как и компилятор, интерпретатор избавляет от необходимости писать программы в машинных кодах.

  • Кроссплатформенность. Интерпретаторы разработаны для разных платформ — Mac, Windows, Linux, поэтому написанная нами программа будет работать на всех платформах.

  • Улучшение программы за счет интерпретатора. Скорость программ зависит не только от качества кода, но и от того, насколько быстро работает интерпретатор. Например, программисты Google постоянно улучшают интерпретатор JavaScript, который работает в браузере Chrome. Если мы написали программу на JavaScript, с каждой новой версией Chrome она работает быстрее, даже если мы ничего в ней не меняем.

Недостатки интерпретаторов:

  • Низкая скорость. Интерпретируемые программы работают медленнее, чем программы в машинных кодах. Это происходит потому, что интерпретатор должен сначала проанализировать текст команды, и лишь потом выполнить ее. Программа в машинных кодах сразу понятна компьютеру.

  • Зависимость от интерпретатора. Интерпретируемой программе нужен интерпретатор. В Windows программы в машинных кодах имеют расширение .exe. Такую программу, скажем, архиватор 7-zip можно просто запустить. А для того, чтобы выполнить программу на языке Python, нужен интерпретатор python.

  • Доступность исходного кода. Исходный код на интерпретируемом языке доступен пользователю программы. Пользователь может подсмотреть в программе то, что ее автор хотел бы скрыть, например, способ шифрования пароля или уникальный алгоритм.

  • Позднее обнаружение ошибок. Интерпретаторы выполняют программы по одной команде. Если в синтаксисе команды допущена ошибка, интерпретатор не сможет об этом узнать, пока не приступит к ее анализу. В больших программах есть куски, которые выполняются реже других и, возможно, там есть ошибки, про которые программист не знает. Чтобы избежать ошибок, которые увидит пользователь программы, приходится тестировать её гораздо тщательней.

Выводы и рекомендации

Интерпретатор языка программирования — это программа, выполняющая команды, написанные на этом языке. Мы, например, говорим интерпретатор Python или интерпретатор JavaScript.

Интерактивный режим (REPL) помогает программистам изучать синтаксис языка и проверять свои идеи.

Интерпретатор состоит из анализатора текста и исполнителей отдельных команд языка, таких как цикл for, проверка if, вызов функции print, и других.

К достоинствам интерпретируемых языков относят простоту изучения. Именно поэтому программирование начинают изучать с таких языков, как Python и JavaScript.

Исходный код (github)
Марк Шевченко
comments powered by Disqus