Как 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 (объявление функции - это один оператор). Таким образом, вы можете выполнять оператор-оператор за строкой в ​​интерпретаторе в основном так же, как в исходном файле.