Как Ruby и Python реализуют свои интерактивные консоли?
При внедрении интерпретатора для моего языка программирования я сначала подумал о простом окне консоли, которое позволяет пользователю вводить некоторый код, который затем выполняется как отдельная программа в качестве оболочки.
Но есть серьезные проблемы: если каждая строка кода, которую вводит пользователь, обрабатывается как отдельная программа, она должна пройти через токенизатор и парсер, а затем просто выполняется интерпретатором - а что же тогда с функциями?
- Как интерактивные консоли Python/Ruby (IDLE, irb) "разделяют" код? Как обрабатывается код?
Пример:
>> def x:
>> print("Blah")
>>
>> x()
Где хранится функция, чтобы ее можно было вызвать в любое время снова?
Как интерактивная консоль может принимать все, как очевидно, одну программу, не выполняя все снова и снова?
Ответы
Ответ 1
Для Python выражение не будет завершено до тех пор, пока все круглые скобки, скобки и т.д. не совпадут. Это довольно легко обнаружить. Определение функции/класса не завершено до тех пор, пока не будет введена полная пустая строка. Затем компилятор компилирует введенное выражение или определение и запускает его.
Как нормальная функция, класс, модуль и т.д., REPL имеет свою собственную локальную область. Эта область, которая используется для переменных и определений, введенных в REPL.
Ответ 2
Подробнее о интерактивной консоли Python вы можете узнать, прочитав документацию для модуля кода:
Модуль кода предоставляет средства для реализации циклов чтения-eval-print в Python. Включены два класса и удобные функции, которые могут быть использованы для создания приложений, которые предоставляют приглашение интерактивного интерпретатора.
http://docs.python.org/library/code.html
Ответ 3
В большинстве этих языков используется синтаксический анализатор, который имеет своего рода "токен-поток", то есть парсер продолжает принимать токены (строку, символ, оператор и т.д.) из входного потока, пока он не будет иметь полное выражение, то он возвращает это разобранное выражение, где он может быть скомпилирован в байт-код или иначе выполнен. Цикл REPL относительно прост в обработке, учитывая эту структуру, поскольку синтаксический анализатор в основном запрашивает больше ввода, и вы даете пользователю приглашение и пользователь вводит больше ввода. Возможно, вам понадобится немного общения от анализатора для читателя, чтобы он отображал такие вещи, как подсказки продолжения.
Python и Ruby выполняют операторы сразу, in-order (объявление функции - это один оператор). Таким образом, вы можете выполнять оператор-оператор за строкой в интерпретаторе в основном так же, как в исходном файле.