Ответ 1
Процесс перевода PyPy на самом деле гораздо менее концептуально рекурсивный, чем кажется.
В действительности все это программа Python, которая обрабатывает функции/класс/другие объекты Python ( не исходный код Python) и выводит код C. Но, конечно, он не обрабатывает только любые объекты Python; он может обрабатывать только определенные формы, которые вы получаете, если вы пишете свой переведенный код в RPython.
Так как инструментальная цепочка перевода является программой Python, вы можете запустить ее поверх любого интерпретатора Python, который, очевидно, включает в себя PyPy-интерпретатор python. Так что ничего особенного.
Так как он переводит объекты RPython, вы можете использовать его для перевода PyPy-интерпретатора python, который написан в RPython.
Но вы не можете запустить его в самой структуре перевода, которая является не RPython. Только PyPy python-интерпретатор - это RPython.
Все становится интересным, потому что код на RPython также является кодом Python (но не наоборот), а потому, что RPython никогда не "действительно существует" в исходных файлах, а только в памяти внутри рабочего процесса Python, который обязательно включает в себя другие, -RPython (нет имен импорта или функций 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 превращаются во вход для остальной части процесса перевода.
Так как обычная вещь, которая переводится с процессом перевода, является интерпретатором PyPy Python, она действительно "интерпретирует себя" с пространством объектов потока. Но все, что на самом деле означает, это то, что у вас есть программа Python, которая обрабатывает функции Python, включая те, которые выполняют обработку. Сам по себе он не является более гибким, чем применение декоратора к себе или наличие класса-оболочки обертывает сам экземпляр (или обертывает сам класс).
Ум, это немного рассердилось. Надеюсь, в любом случае это поможет, и я надеюсь, что я ничего не сказал неточно; пожалуйста, поправьте меня, если у меня есть.