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

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

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

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

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

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. Для каждой команды в интерпретаторе есть блок кода, который умеет такую команду исполнять.

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

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

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

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

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

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

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

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

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

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

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