Расширяемое программирование - это термин, используемый в информатике для описания стиля компьютерного программирования, ориентированного на о механизмах расширения языка программирования, компилятора и среды выполнения. Расширяемые языки программирования, поддерживающие этот стиль программирования, были активной областью работы в 1960-х годах, но в 1970-х годах это движение было маргинализовано. Расширяемое программирование стало темой возобновления интереса в 21 веке.
Первой статьей, обычно связанной с движением расширяемых языков программирования, является M. Статья Дугласа Макилроя 1960 г. о макросах для языков программирования более высокого уровня. Еще одно раннее описание принципа расширяемости содержится в статье Брукера и Морриса 1960 г. о компиляторе-компиляторе. Пик движения был отмечен двумя академическими симпозиумами в 1969 и 1971 годах. К 1975 году обзорная статья Томаса А. Стэндиша о движении была по существу посмертной. Язык программирования Forth был исключением, но, по сути, незамеченным.
Как обычно предполагалось, расширяемый язык программирования состоял из базового языка, обеспечивающего элементарные вычислительные возможности, и метаязыка, способного изменять базовый язык. Тогда программа состояла из модификаций метаязыка и кода на модифицированном базовом языке.
Самой известной техникой расширения языка, использованной в движении, были макроопределения. Модификация грамматики также была тесно связана с движением, что в конечном итоге привело к развитию адаптивных грамматических формализмов. Сообщество языков Лисп оставалось отдельным от сообщества расширяемых языков, по-видимому, потому, что, как заметил один исследователь,
любой язык программирования, на котором программы и данные по существу взаимозаменяемы, может рассматриваться как расширяемый [sic] язык.... это очень легко увидеть из того факта, что Lisp уже много лет используется как расширяемый язык.
На конференции 1969 года Simula был представлен как расширяемый язык программирования.
Стэндиш описал три класса языковых расширений, которые он назвал парафразом, ортофразой и метафразой (иначе парафраз и метафраза являются переводом терминами).
Стэндиш объяснил неудачу движения расширяемости трудностью программирования последовательных расширений. Обычный программист мог бы построить единую оболочку макросов вокруг базового языка, но если бы вторая оболочка макросов была построена вокруг этого, программист должен был бы хорошо знать как базовый язык, так и первую оболочку; третья оболочка потребует знакомства с основанием, а также с первой и второй оболочками; и так далее. (Обратите внимание, что защита программиста от подробностей более низкого уровня является целью движения абстракции, которое вытеснило движение расширяемости.)
Несмотря на более раннее представление Simula как расширяемой, к 1975 г. Обзор, похоже, на практике не включал новые технологии, основанные на абстракции (хотя он использовал очень общее определение расширяемости, которое технически могло бы включить их). В истории абстракции программирования 1978 года от изобретения компьютера до (тогда) настоящего времени не упоминались макросы и не дало никаких намеков на то, что движение расширяемых языков когда-либо происходило. Макросы были предварительно допущены к абстракции к концу 1980-х (возможно, из-за появления гигиенических макросов ), получив псевдоним синтаксических абстракций.
В современном смысле система, поддерживающая расширяемое программирование, будет предоставлять все функции, описанные ниже.
Это просто означает, что исходный язык (и) для компиляции не должен быть закрытым, фиксированным или статическим. Должна быть возможность добавлять новые ключевые слова, концепции и структуры к исходному языку (языкам). Языки, которые позволяют добавлять конструкции с пользовательским синтаксисом, включают Camlp4, Seed7, Red, Rebol и. Хотя допустимо, чтобы некоторые фундаментальные и внутренние языковые функции были неизменными, система не должна полагаться исключительно на эти языковые функции. Должна быть возможность добавлять новые.
В расширяемом программировании компилятор не является монолитной программой, которая преобразует входной исходный код в двоичный исполняемый выход. Сам компилятор должен быть расширяемым до такой степени, что это действительно набор подключаемых модулей, которые помогают переводить вводимые данные исходного языка во что угодно. Например, расширяемый компилятор будет поддерживать создание объектного кода, документации кода, переформатированного исходного кода или любого другого желаемого результата. Архитектура компилятора должна позволять пользователям «проникнуть внутрь» процесса компиляции и предоставлять альтернативные задачи обработки на каждом разумном этапе процесса компиляции.
Для задачи преобразования исходного кода во что-то, что может быть выполнено на компьютере, расширяемый компилятор должен:
Во время выполнения расширяемые системы программирования должны разрешать языкам расширять набор операций, которые они разрешают. Например, если в системе используется интерпретатор байт-кода , он должен позволять определять новые значения байт-кода. Как и в случае с расширяемым синтаксисом, допустимо наличие некоторого (небольшого) набора фундаментальных или внутренних операций, которые являются неизменяемыми. Однако должна быть возможность перегрузить или дополнить эти внутренние операции, чтобы можно было поддерживать новое или дополнительное поведение.
Расширяемые системы программирования должны рассматривать программы как данные, подлежащие обработке. Эти программы не должны содержать никакой информации о форматировании. Визуальное отображение и редактирование программ для пользователей должно быть функцией перевода, поддерживаемой расширяемым компилятором, который переводит данные программы в формы, более подходящие для просмотра или редактирования. Естественно, это должен быть двусторонний перевод. Это важно, потому что должна быть возможность легко обрабатывать расширяемые программы различными способами. Недопустимо, чтобы ввод на исходном языке использовался только для редактирования, просмотра и перевода в машинный код. Произвольная обработка программ облегчается за счет отделения входных данных источника от спецификаций того, как они должны обрабатываться (форматироваться, сохраняться, отображаться, редактироваться и т. Д.).
Расширяемые системы программирования должны поддерживать отладку программ с использованием конструкций исходного исходного языка независимо от расширений или преобразований, которым подверглась программа, чтобы сделать ее исполняемой. В частности, нельзя предполагать, что единственный способ отображать данные времени выполнения - это структуры или массивы. Отладчик, или, точнее, «инспектор программ», должен разрешать отображение данных времени выполнения в формах, подходящих для исходного языка. Например, если язык поддерживает структуру данных для бизнес-процесса или рабочего потока, отладчик должен иметь возможность отображать эту структуру данных в виде диаграммы рыбьей кости или в другой форме, предоставляемой плагином.