Я делал проект в команде с Юрой Каменевым и Кириллом Карташевым. Он заключается в реализации механизма REPL (интерактивного интерпретатора) для языка C++. Идея для проекта возникла, когда я делал домашнее задание по плюсам, и мне захотелось иметь такой механизм, который позволил бы что-то проверить, над чем-то поэкспериментировать.
Как известно, C++ – компилируемый язык. А это означает, что разработчикам необходимо писать целые готовые программы, чтобы их запустить. То есть сначала будет происходить процесс компиляции, а только потом исполнения. С другой стороны, часто в разработке возникает необходимость провести какой-то эксперимент, оценку параметров, проверить, как работает тот или иной метод стандартной библиотеки, просто провести локальный дебаг. Для этого очень удобным оказывается механизм REPL, который реализован в интерпретируемых языках, например, на Python. Но в тех языках это происходит более-менее естественным образом. А в случае C++ есть определенные вызовы и сложности – как минимум, изначальная его компилируемая природа.
У нас были задачи минимум и те, что стали для нас значительными челенджами. Задача минимум – заставить наш механизм работать так, чтобы при получении каждой новой строчки кода от пользователя, он просто его исполнял. Наивное решение этой задачи может привести к повторению на каждом шаге уже произведенных вычислений. Этого, конечно же, хочется избежать из-за возможных сайд эффектов, например, повторной записи в файл. В идеале, хотелось также позволять пользователю переопределять уже объявленные сущности, такие как функции, переменные, классы и структуры.
В итоге нам удалось добиться того, чтобы каждая новая строка кода от пользователя выполнялась отдельно, не повторяя предыдущих вычислений. Таким образом мы получаем отсутствие сайд-эффектов. Также мы поддержали переопределение сущностей. Например, можно заново написать уже объявленную функцию, и ее прежняя реализация будет обновлена. Такой же механизм работает и для классов, но для них существуют ограничения, в частности, связанные с наследованием. Самой нетривиальной задачей оказалось сохранение состояния памяти между шагами исполнения. Мы решили это, работая с памятью из динамических библиотек, однако такой подход не поддерживает указателей. Нам известны альтернативные способы работы с состоянием памяти, которые можно будет реализовать в будущем.
Конечно, на рынке существуют аналогичные решения для C++, в частности, от ЦЕРН. Но я посчитал, что ничего плохого не будет, если мы предложим альтернативу. Мы не пытались создать заявку на конкуренцию за четыре дня, но какой-то свой прототип всегда сделать неплохо.
Видео с демонстрацией работы Ссылка на GitHub