Код, который действует на код? Пожалуйста, расскажите мне больше
Как это называется, когда программа принимает исходный код в качестве входных данных, выплевывает новый исходный код и, возможно, немедленно запускает новый код?
Примеры:
- Автоматический рефакторинг
- Взятие функции и превращение ее в GUI (превращение входов функций в поля ввода)
- Добавление новых функций в функцию, например, кэширование результатов.
Самые простые языки для этого - это функциональные языки с простым синтаксисом, верно? (шепот, схема и т. д.)?
Но вы можете делать это с любым языком или между языками, если вы можете анализировать исходный код в дереве или другой структуре данных, верно? (Использование antlr или другого инструмента?)
Итак, как это называется? Каковы другие примеры, как большие, так и маленькие? Каковы некоторые общие инструменты? Пожалуйста, дайте мне отправную точку для полного понимания этого типа программирования.
(Я пытаюсь использовать то, что я, как один программист, могу сделать одной парой рук, написав код, который будет работать с моим кодом.)
1 ответ
Что вас интересует, так это системы преобразования программ "источник-источник".
Парсер необходим, но вряд ли достаточен. (На самом деле, необходим синтаксический анализатор для вашего диалекта языка, который вы используете... учитывая, что люди используют так много языков "программирования", это много парсеров, необходимых). Вам также необходимо захватить результат анализа (как правило, в виде дерева), иметь возможность каким-либо образом манипулировать этим деревом и затем восстановить действительный исходный код из дерева. Если вы хотите, чтобы этот исходный код был постоянным изменением исходного кода, запрограммированного вручную, комбинация синтаксический анализатор / дерево / непарсер должен сохранить форматирование кода и комментарии в максимально возможной степени.
Часто вы не можете реально преобразовать код, если значение идентификаторов не ясно; поэтому на практике вам нужно не только анализировать, но и создавать таблицы символов (на данный момент у вас есть то, что составляет внешний интерфейс компилятора, а не анализатор). Многие преобразования требуют отслеживания информационных потоков (поток управления, поток данных, точки, кто звонит,...). Без этих функций эти инструменты не очень эффективны для процедурных /OO-языков, которые составляют большую часть исходного кода. (Функциональные языки ребята могут обойтись с меньшим анализом потока, потому что все является выражением, но большая часть написанного кода не функциональна, так что это не имеет значения в практическом смысле).
Существует несколько систем преобразования источника в источник, некоторые из которых зависят от языка (например, JackPot для Java); некоторые из них параметризованы определениями языка (TXL, Stratego, DMS).
Некоторые из языков, специфичных для языка, предоставляют таблицы символов и анализ потока. Я знаю только одно преобразование, которое предоставляет эти возможности для ряда языков программирования, и это наш инструментарий реинжиниринга программного обеспечения DMS.
DMS предоставляет это для ряда реальных языков программирования и их общих диалектов, а не для игрушек: C, Java, COBOL.
DMS - одна из немногих систем преобразования программ от источника к источнику для C++; он был использован в гневе для внесения изменений в большие программы на C++. Clang довольно близок, я думаю, конечно, в амбициях; Компилятор Rose - другой, используемый в основном в суперкомпьютерных кругах, но оба они специфичны для C++ (возможно, с добавленным C).