# Компилятор и интерпретатор

> Два способа выполнять программы — заранее перевести исходный код в машинный (компиляция) или исполнять его по ходу (интерпретация); на практике языки сочетают оба подхода через байткод, виртуальные машины и JIT.

Источник: https://llmdocs.ru/wiki/compiler-interpreter/ · обновлено 2026-11-09 · лицензия CC BY-SA 4.0

- **Компилятор**: переводит программу целиком до запуска (AOT)
- **Интерпретатор**: исполняет программу по ходу чтения
- **Промежуточные формы**: AST, байткод, IR (LLVM IR, SSA)
- **Гибриды**: байткод + ВМ, JIT-компиляция
- **Примеры AOT**: C, C++, Rust, Go, Swift
- **Примеры ВМ и JIT**: JVM, .NET CLR, V8, PyPy, LuaJIT
**Компилятор** — программа, которая переводит исходный код целиком в другую форму, обычно в машинный код процессора, *до* запуска. **Интерпретатор** — программа, которая исполняет исходный код (или его промежуточное представление) *по ходу*, без создания отдельного исполняемого файла. Это два полюса; большинство современных языков сочетают оба подхода: компилируют исходник в байткод, а байткод интерпретируют и «на горячих участках» компилируют в машинный код прямо во время работы (JIT).[1][2]

## Этапы обработки программы

Независимо от подхода, обработка начинается одинаково:

1. **Лексический анализ** — текст разбивается на токены: ключевые слова, имена, числа, операторы. Часто для этого используются [регулярные выражения](https://llmdocs.ru/wiki/regex.md).
2. **Синтаксический анализ** — из токенов строится **абстрактное синтаксическое дерево** (AST) по грамматике языка (см. [Дерево и граф](https://llmdocs.ru/wiki/trees-graphs.md)).
3. **Семантический анализ** — разрешение имён (через таблицы символов — обычно [хеш-таблицы](https://llmdocs.ru/wiki/hash-table.md)), проверка типов, ошибки вида «переменная не объявлена».
4. **Промежуточное представление** (IR) — упрощённая форма, удобная для анализа: байткод, трёхадресный код, SSA-форма.
5. **Оптимизация** — свёртка констант, удаление мёртвого кода, встраивание функций, развёртка циклов, векторизация.
6. **Генерация кода** — машинные инструкции для конкретной архитектуры (x86-64, ARM64) или байткод для виртуальной машины; затем компоновка (linking) с библиотеками.

Первые три этапа — «фронтенд», последние — «бэкенд». Инфраструктура **LLVM** разделила их: фронтенды Clang (C/C++), [rustc](https://llmdocs.ru/wiki/rust.md), Swift, Zig выдают общий LLVM IR, а общий бэкенд оптимизирует его и генерирует код под десятки архитектур.[3]

## Компиляция заранее (AOT)

Языки C, C++, Rust, [Go](https://llmdocs.ru/wiki/go.md), Swift, Haskell компилируются *ahead-of-time*: на выходе — исполняемый файл с машинным кодом.[7]

- **Плюсы:** высокая скорость и предсказуемость, быстрый старт, ошибки типов находятся до запуска, не нужен интерпретатор на целевой машине (Go-программа — один статический бинарник).
- **Минусы:** время сборки, отдельная сборка для каждой ОС и архитектуры, оптимизатор не знает реальных данных, на которых будет работать программа.

## Интерпретация

Простейший интерпретатор обходит AST и выполняет узлы один за другим (tree-walking). Так работали ранние реализации многих языков; сегодня так делают учебные и встраиваемые интерпретаторы, а также оболочки вроде [Bash](https://llmdocs.ru/wiki/shell-bash.md).

- **Плюсы:** мгновенный запуск без сборки, интерактивный режим (REPL), переносимость, простота реализации, гибкость (`eval`, изменение кода на лету).
- **Минусы:** скорость в десятки раз ниже машинного кода, ошибки обнаруживаются только при выполнении строки.

## Байткод и виртуальные машины

Промежуточный путь — компилировать в **байткод**, компактные инструкции для виртуальной машины, и исполнять его интерпретатором ВМ. Так устроены [CPython](https://llmdocs.ru/wiki/cpython.md), Ruby (YARV), Lua, JVM и .NET. В CPython компиляция в байткод происходит незаметно при импорте, результат кэшируется в файлах `.pyc`:[4]

```python
import dis
dis.dis(lambda x: x + 1)
#  RESUME        0
#  LOAD_FAST     0 (x)
#  LOAD_CONST    1 (1)
#  BINARY_OP     0 (+)
#  RETURN_VALUE
```

Поэтому утверждение «Python — интерпретируемый язык» верно лишь отчасти: это свойство реализации, а не языка. Тот же Python исполняют PyPy (с JIT), а [WebAssembly](https://llmdocs.ru/wiki/webassembly.md) — переносимый байткод, который браузер компилирует в машинный код.

## JIT-компиляция

**JIT** (*just-in-time*) — компиляция во время выполнения. ВМ начинает с интерпретации, собирает профиль (какие функции горячие, какие типы реально приходят) и компилирует частые участки в машинный код с оптимизациями под фактическое поведение. Если предположение нарушилось (в функцию пришла строка вместо числа), выполняется *деоптимизация* — возврат в интерпретатор.

- **JVM HotSpot** и **.NET** — многоуровневая JIT-компиляция, сделавшая Java быстрой.
- **V8** (Chrome, [Node.js](https://llmdocs.ru/wiki/nodejs.md)) — интерпретатор Ignition и несколько уровней JIT, включая Maglev и TurboFan; благодаря им [JavaScript](https://llmdocs.ru/wiki/javascript.md) стал быстрым.[6]
- **PyPy** и **LuaJIT** — трассирующие JIT; в CPython 3.13 появился экспериментальный JIT (PEP 744).[5]

Цена JIT — время «прогрева», расход памяти и сложность реализации; поэтому для быстрого старта (serverless, CLI) иногда используют AOT-варианты: GraalVM Native Image, .NET Native AOT.

## Родственные понятия

- **Транспилятор** — компилятор из одного языка высокого уровня в другой: [TypeScript](https://llmdocs.ru/wiki/typescript.md) → JavaScript, Babel, Cython (Python → C).
- **Кросс-компиляция** — сборка под другую платформу (`GOOS=linux GOARCH=arm64 go build`).
- **Ассемблер** и **компоновщик** (linker) — завершающие этапы получения бинарника.

## Сравнение

| Подход | Старт | Пиковая скорость | Переносимость | Примеры |
|---|---|---|---|---|
| AOT | быстрый | высокая | сборка под каждую платформу | C, Rust, Go |
| Интерпретатор AST | быстрый | низкая | высокая | Bash, ранний Ruby |
| Байткод + ВМ | средний | средняя | высокая | CPython, Lua |
| Байткод + JIT | медленный прогрев | высокая | высокая | Java, C#, JavaScript |

## См. также

- [Python](https://llmdocs.ru/wiki/python.md)
- [Сборка мусора vs ручное управление памятью](https://llmdocs.ru/wiki/gc-vs-manual-memory.md)
- [WebAssembly](https://llmdocs.ru/wiki/webassembly.md)
- [Алгоритм и O-нотация](https://llmdocs.ru/wiki/big-o.md)

## Источники

1. [Aho, Lam, Sethi, Ullman — Compilers: Principles, Techniques, and Tools (2nd ed.)](https://suif.stanford.edu/dragonbook/)
2. [Robert Nystrom — Crafting Interpreters](https://craftinginterpreters.com/)
3. [LLVM Project — documentation](https://llvm.org/docs/)
4. [Python — dis: Disassembler for Python bytecode](https://docs.python.org/3/library/dis.html)
5. [PEP 744 — JIT Compilation](https://peps.python.org/pep-0744/)
6. [V8 — Maglev, V8's fastest optimizing JIT](https://v8.dev/blog/maglev)
7. [Go — Command compile](https://pkg.go.dev/cmd/compile)
