- •Об авторе
- •О группе редакторов
- •Предисловие
- •Введение
- •Как использовать эту книгу
- •Загрузка исходного кода CPython
- •Что в исходном коде?
- •Настройка среды разработки
- •IDE или редактор?
- •Настройка Visual Studio
- •Настройка Visual Studio Code
- •Настройка Vim
- •Выводы
- •Компиляция CPython
- •Компиляция CPython на macOS
- •Компиляция CPython на Linux
- •Установка специализированной версии
- •Знакомство с Make
- •Make-цели CPython
- •Компиляция CPython на Windows
- •Профильная оптимизация
- •Выводы
- •Грамматика и язык Python
- •Спецификация языка Python
- •Генератор парсеров
- •Повторное генерирование грамматики
- •Выводы
- •Конфигурация и ввод
- •Конфигурация состояния
- •Структура данных конфигурации среды выполнения
- •Конфигурация сборки
- •Сборка модуля из входных данных
- •Выводы
- •Генерирование конкретного синтаксического дерева
- •Парсер/токенизатор CPython
- •Абстрактные синтаксические деревья
- •Важные термины
- •Пример: добавление оператора «почти равно»
- •Выводы
- •Компилятор
- •Исходные файлы
- •Важные термины
- •Создание экземпляра компилятора
- •Флаги будущей функциональности и флаги компилятора
- •Таблицы символических имен
- •Основная компиляция
- •Ассемблер
- •Создание объекта кода
- •Использование Instaviz для вывода объекта кода
- •Пример: реализация оператора «почти равно»
- •Выводы
- •Цикл вычисления
- •Исходные файлы
- •Важные термины
- •Построение состояния потока
- •Построение объектов кадров
- •Выполнение кадра
- •Стек значений
- •Пример: добавление элемента в список
- •Выводы
- •Управление памятью
- •Выделение памяти в C
- •Проектирование системы управления памятью Python
- •Аллокаторы памяти CPython
- •Область выделения объектной памяти и PyMem
- •Область выделения сырой памяти
- •Нестандартные области выделения памяти
- •Санитайзеры выделенной памяти
- •Арена памяти PyArena
- •Подсчет ссылок
- •Сборка мусора
- •Выводы
- •Параллелизм и конкурентность
- •Модели параллелизма и конкурентности
- •Структура процесса
- •Многопроцессорный параллелизм
- •Многопоточность
- •Асинхронное программирование
- •Генераторы
- •Сопрограммы
- •Асинхронные генераторы
- •Субинтерпретаторы
- •Выводы
- •Объекты и типы
- •Примеры этой главы
- •Встроенные типы
- •Типы объектов
- •Тип type
- •Типы bool и long
- •Тип строки Юникода
- •Словари
- •Выводы
- •Стандартная библиотека
- •Модули Python
- •Модули Python и C
- •Набор тестов
- •Запуск набора тестов в Windows
- •Запуск набора тестов в Linux или macOS
- •Флаги тестирования
- •Запуск конкретных тестов
- •Модули тестирования
- •Вспомогательные средства тестирования
- •Выводы
- •Отладка
- •Обработчик сбоев
- •Компиляция поддержки отладки
- •LLDB для macOS
- •Отладчик Visual Studio
- •Отладчик CLion
- •Выводы
- •Бенчмаркинг, профилирование и трассировка
- •Использование timeit для микробенчмарка
- •Использование набора тестов производительности Python
- •Профилирование кода Python с использованием cProfile
- •Выводы
- •Что дальше?
- •Создание расширений C для CPython
- •Улучшение приложений Python
- •Участие в проекте CPython
- •Дальнейшее обучение
- •Препроцессор C
- •Базовый синтаксис C
- •Выводы
- •Благодарности
Компилятор
После завершения задачи парсинга у интерпретатора имеется дерево AST с операциями, функциями, классами и пространствами имен Python-кода.
Задача компилятора — преобразование AST в инструкции, понятные для процессора:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/ |
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Взадаче компиляции участвуют два компонента:
1.Компилятор: обходит AST и создает граф потока управления (CFG, Control Flow Graph), представляющий логическую последовательность выполнения.
2.Ассемблер: преобразует узлы CFG в последовательность выполняемых команд, называемую байт-кодом.
Наглядное представление процесса компиляции:
|
AST |
|
CFG |
|
- |
|
|
|
|
||||
|
|
|
|
|
|
|
Книги для программистов: https://t.me/booksforits
Важные термины 111
ВАЖНО
Важно помнить,что единицей компиляции для CPython являетсямодуль. Шаги компиляции ипроцесс,описанный вэтой главе,выполняются одно кратно для каждого модуля в вашем проекте.
В этой главе мы сосредоточимся на компиляции модуля AST в объект кода.
Функция PyAST_CompileObject() — главная точка входа компилятора CPython. Она получает в качестве основного аргумента модуль Python AST; также передается имя файла, глобальные и локальные переменные и PyArena — все эти данные должны быть созданы ранее в процессе работы интерпретатора.
ПРИМЕЧАНИЕ
Теперь вы начинаете углубляться во внутреннее устройство компилятора CPython,за которым лежат десятилетия разработки и развития computer science.Непугайтесьегоразмеровисложности.Еслиразбитькомпилятор на логические шаги, понять его будет не так сложно.
ИСХОДНЫЕ ФАЙЛЫ
Ниже перечислены исходные файлы, относящиеся к компилятору:
ФАЙЛ |
НАЗНАЧЕНИЕ |
Python compile.c |
Реализация компилятора |
Include compile.h |
API и определения типов компилятора |
ВАЖНЫЕ ТЕРМИНЫ
Ниже перечислены некоторые ключевые термины, которые вам могут быть пока незнакомы:
zz Состояние компилятора реализуется как тип контейнера, содержащий одну таблицу символических имен.
Книги для программистов: https://t.me/booksforits
112 Компилятор
zz Таблица символических имен содержит имена переменных, также в ней могут дополнительно находиться дочерние таблицы символических имен.
zz Состояние компилятора включает в себя несколько единиц компиляции.
zz Каждая единица компиляции может содержать множество имен, имен переменных, констант и сегментных переменных.
zz Единица компиляции содержит несколько базовых блоков. zz Базовые блоки содержат множество инструкций байт-кода.
Контейнер состояния компилятора и его компоненты можно наглядно представить в следующем виде:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
||||||||||
|
|
|
|
|
|
|
|
|
|
|||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
• |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
СОЗДАНИЕ ЭКЗЕМПЛЯРА КОМПИЛЯТОРА
Перед запуском компилятора создается глобальное состояние компилятора. Структура состояния компилятора (тип compiler) содержит свойства, используемые компилятором: флаги компилятора, стек и PyArena. Также она содержит ссылки на другие структуры данных, такие как таблица символических имен.
Книги для программистов: https://t.me/booksforits
Создание экземпляра компилятора 113
Поля состояния компилятора:
ПОЛЕ |
ТИП |
НАЗНАЧЕНИЕ |
c_arena |
PyArena * |
Указатель на арену выделения |
|
|
памяти |
c_const_cache |
PyObject * (dict) |
Словарь Python (dict) со всеми |
|
|
константами, включая кортеж |
|
|
names |
c_do_not_emit_bytecode |
int |
Флаг отключения компиляции |
|
|
байт-кода |
c_filename |
PyObject * (str) |
Имя компилируемого файла |
c_flags |
PyCompilerFlags * |
Унаследованные флаги компиля- |
|
|
тора (см. раздел «Флаги компиля- |
|
|
тора») |
c_future |
PyFutureFeatures * |
Указатель на __future__ модуля |
c_interactive |
int |
Флаг интерактивного режима |
c_nestlevel |
int |
Текущий уровень вложенности |
c_optimize |
int |
Уровень оптимизации |
c_st |
symtable * |
Таблица символических имен ком- |
|
|
пилятора |
c_stack |
PyObject * (list) |
Список Python (list), содержащий |
|
|
указатели compiler_unit |
ucompiler_unit* Состояние компилятора для теку-
щего блока
Экземпляр состояния компилятора создается внутри PyAST_CompileObject():
zz Если модуль не содержит строку документации (__doc__), в этой точке создается пустая строка, как и в свойстве __annotations__.
zz PyAST_CompileObject() задает переданное значение как имя файла состояния компилятора, которое используется для трассировки стека и обработки исключений.
Книги для программистов: https://t.me/booksforits