Процесс перевода PyPy на самом деле гораздо менее концептуально рекурсивен, чем кажется.
На самом деле все это программа Python, которая обрабатывает функции / классы / другие объекты Python ( не исходный код Python) и выводит код C. Но, конечно, он не обрабатывает только любых объектов Python; он может обрабатывать только определенные формы, которые вы получите, если напишите свой переводимый код в RPython.
Поскольку инструментарий перевода - это программа на Python, вы можете запустить ее поверх любого интерпретатора Python, который, очевидно, включает в себя интерпретатор PyPy Python. Так что в этом нет ничего особенного.
Поскольку он переводит объекты RPython, вы можете использовать его для перевода Python-интерпретатора Python, который написан на RPython.
Но вы не можете запустить его на самой платформе перевода, которая не RPython. Только PyPy-интерпретатор Python сам является RPython.
Вещи становятся интересными только потому, что код RPython также является кодом Python (но не наоборот), и потому что RPython никогда "не существует" в исходных файлах, но только в памяти внутри рабочего процесса Python, который обязательно включает в себя другие -RPython code (нет импорта или определения функций "pure-RPython", например, потому что транслятор работает с функциями, которые уже были определены и импортированы).
Помните, что цепочка инструментов перевода работает с объектами кода Python в памяти. Модель исполнения Python означает, что эти не существуют до того, как какой-то код Python будет выполняться . Вы можете себе представить, что запуск процесса перевода выглядит примерно так, если сильно упростить его:
from my_interpreter import main
from pypy import translate
translate(main)
Как мы все знаем, простой импорт main
приведет к запуску большого количества кода Python, включая все другие модули my_interpreter
import. Но процесс перевода начинает анализировать функциональный объект main
; он никогда не видит и не заботится о том, какой код был выполнен для получения main
.
Одним из способов думать об этом является то, что «программирование на RPython» означает «написание программы на Python, которая генерирует программу RPython и затем передает ее в процесс перевода». Это относительно просто для понимания и похоже на то, как работает много других компиляторов (например, один из способов думать о программировании на C - это то, что вы, по сути, пишете программу препроцессора C, которая генерирует программу C, которая затем подается на C компилятор).
Ситуация запутывается только в случае PyPy, поскольку все 3 компонента (программа Python, которая генерирует программу RPython, программу RPython и процесс перевода) загружаются в того же интерпретатора Python . Это означает, что вполне возможно иметь функции RPython при вызове с некоторыми аргументами, а не при вызове с другими аргументами, для вызова вспомогательных функций из среды перевода как части генерации вашей программы RPython и множества других странных вещей. Таким образом, ситуация становится довольно размытой по краям, и вы не можете четко разделить строки исходного текста на «RPython для перевода», «Python, генерирующий мою программу RPython» и «передачу программы RPython в среду перевода».
Интерпретатор PyPy, работающий поверх CPython, выполняет частично
интерпретировать себя
Я думаю, вы намекаете на то, что PyPy использует пространство объекта потока во время перевода, чтобы сделать абстрактную интерпретацию. Даже это не так сумасшедший и изнурительный, как кажется на первый взгляд. Я гораздо менее информирован об этой части PyPy, но, насколько я понимаю,
PyPy реализует все операции интерпретатора Python, делегируя их «объектному пространству», которое содержит реализацию всех основных встроенных операций.Но вы можете подключить разные объектные пространства, чтобы получить разные эффекты, и до тех пор, пока они реализуют один и тот же интерфейс «объектного пространства», интерпретатор все равно сможет «выполнять» код Python.
Объекты кода RPython, которыепроцессы цепочки инструментов перевода PyPy - это код Python, который может быть выполнен интерпретатором.Таким образом, PyPy повторно использует часть своего интерпретатора Python как часть цепочки инструментов перевода, подключая пространство объекта потока.При «выполнении» кода с этим пространством объектов интерпретатор фактически не выполняет операций кода, вместо этого он создает потоковые графы, которые аналогичны видам промежуточного представления, используемым многими другими компиляторами;это просто простое машинно-управляемое представление кода для дальнейшей обработки.Вот как обычные (R) объекты кода Python превращаются во входные данные для остальной части процесса перевода.
Так как обычная вещь, которая переводится в процессе перевода, это Python-интерпретатор Python, он действительно "интерпретирует себя"."с потоком объекта пространства.Но все, что на самом деле означает, что у вас есть программа на Python, которая обрабатывает функции Python, включая те, которые выполняют обработку.Само по себе это не более изнурительно, чем применение декоратора к себе или создание класса-обертки для обертывания экземпляра самого себя (или обертывания самого класса).
Гм, чтонемного болтовниНадеюсь, это поможет, во всяком случае, и надеюсь, что не сказал ничего неточного;пожалуйста, поправьте меня, если у меня есть.