Страницы

Поиск по вопросам

пятница, 14 декабря 2018 г.

Автогенерация кода

Подскажите, пожалуйста, на каком из языков программирования можно написать программу, которая способна создать другую программу, а так же полностью изменить себя? Какие способы есть для этого, макросы, метапрограммирование? Чем тогда отличаются макросы ассемблера от макросов Lisp?


Ответ

Подскажите пожалуйста на каком из языков программирования можно написать программу которая способна создать другую программу, а так же полностью изменить себя? Для использования возможностей метапрограммирования достаточно наличия в языке eval. Возможность построить и выполнить произвольный код который будет влиять на текущий контекст — мощное средство с помощью которого можно писать программы, пишущие программы. Чтобы "изменять себя" достаточно переопределять существующий код в рантайме. Это можно сделать много где: Smalltalk, Python, Ruby, JavaScript. Иногда много средств для изменения кода на лету доступно из без eval, когда среда поддерживает рефлексию. (Smalltalk) Какие способы есть для этого, макросы, метапрограммирование? Чем тогда отличаются макросы ассемблера от макросов Lisp? Макросы Lisp — это просто удобное средство для преобразования AST перед компиляцией ничего больше. Разница в том, что макросы asm и C-предпроцессора оперируют кусками текста. Макросы Lisp оперируют выражениями. Кроме того, макросы в Lisp -- полноценные программы, и с помощью них можно строить весьма сложные выражения. UPD eval — это процедура которая принимает исходный код в виде данных (просто строку или AST) и выполняет его. Например в JavaScript можно написать так: eval("function some_func() { return 1; }") Здесь код передан как простой текст, но после выполнения будет объявлена функция some_func в текущем контексте, и мы сможем ею оперировать. some_func() // вернёт 1 Так как передаётся простой текст, то мы можем его преобразовывать любыми способами, и в итоге выполнить произвольный код в рантайме. AST — abstract syntax tree, такая структура данных (дерево) в которую преобразуется исходный код какого-либо языка после парсинга. После того как получено AST обычно над ним производят ряд преобразований (оптимизаций), а потом компилируют в машинный код. В случае Lisp из-за простоты синтаксиса AST будет обычный линейный список, например код: (some-construction (for i 0) ((i) exit)) В виде списка (AST) будет почти так же: (list 'some-construcion (list 'for 'i 0) (list (list 'i) 'exit)) ;; Или достаточно закавычить, чтобы получить тот же список '(some-construction (for i 0) ((i) exit)) Макросы — просто программы которые оперируют этой структурой данных, уже после того как код был прочтён, но ещё не оптимизирован и не скомпилирован. Они позволяют легко встраивать новые конструкции в язык, которые потом преобразуются в какие-то стандартные конструкции. Полезно взглянуть на язык Nemerle, который также поддерживает макросы, но не является лиспоподобным.

Комментариев нет:

Отправить комментарий