DSL'и и инструменты для них
От: alex_public  
Дата: 17.07.15 11:09
Оценка: 30 (3)
В начале хотел отписаться в соседней темке, но потом понял, что не укладываюсь в её направление, так что сделаю отдельную. Да, и сразу хочу сказать, что вопросы платформ тут обсуждать не хочу — на этот предмет я уже полностью высказался в соседних темах. Т.е. понятно, что, если какой-то инструмент будет реализован скажем только под какой-нибудь там .net, то он будет отброшен из рассмотрения ещё до оценки его "dsl возможностей". Но здесь мы это обсуждать не будем — можно пока условно считать, что все инструменты реализованы под все платформы.

И так DSL. На мой взгляд вся эта область делится на две принципиально разных части: dsl исполняемые в процессе разработки ПО и dsl исполняемые в процессе работы ПО. Рассмотрим по отдельности.

1. DSL исполняемые в процессе работы ПО.

Речь о так называемых встроенных скриптах. Даже не буду приводить примеры — используется почти во всём сложном ПО. Гораздо интереснее рассмотреть способы реализации:

А. В большинстве случаев наиболее логичным и эффективным способом является встраивание какого-то из интерпретируемых языков общего назначения, с добавлением набора специфических для предметной области функций. Чаще всего это Lua, Python, JavaScript, но может быть и Lisp, Prolog и т.п. Конкретная реализация тривиальна: подключаем библиотеку языка, регистрируем свои предметные функции в движке; если требуется редактирование скриптов пользователем в самом приложение, то берём что-нибудь вроде QScintilla(там даже некое автодополнение работать будет). Данный подход позволяет не только получить "на халяву" готовый отлаженный интерпретатор, но и что самое главное, вылизанный годами эволюции синтаксис языка. Обычно разница с велосипедами очевидна (например достаточно взглянуть на убогий вид cmake скриптов в сравнение с scons/waf(использующие Python)). Но не всегда...

Б. В некоторых случаях всё же лучше разработать свой язык. Как успешный пример, используемый лично мною, могу назвать скажем OpenSCAD. Здесь, на мой взгляд, самым сложным является именно проектирование удобного непротиворечивого языка. И я не представляю какие инструменты (кроме ручки, бумаги и мозгов) могут помочь в этом. Так же очень важно хорошее знание предметной области. Однако после придумывания языка уже никаких особых проблем не возникает. Мы записываем формальную грамматику, берём какой-нибудь flex+bizon (или их аналоги для других платформ) и получаем готовый парсер. Интерпретатор же синтаксического дерева в таких случая обычно является просто исполнителем функций предметной области. В общем всё просто и уже давно разработано. Ну можно ещё добавить синтаксический модуль для нового языка в QScintilla, если требуется редактирование в самом приложение (как в том же OpenSCAD).

2. DSL исполняемые в процессе разработки ПО.

Обычно применяются для повышения эффективности работы программиста на каком-то языке общего назначения. Соответственно реализация очень сильно зависит от возможностей этого языка:

А. Реализация DSL через различные препроцессоры. В принципе не сложная вещь, применяемая обычно для мелких расширений базового языка. Соответственно это наиболее актуально для всяких там слабых языков (а зачем нам такие?). Хотя и в том же C++ есть свои известные вариации: moc (из Qt), ODB, AspectC++ и т.п. Однако для сильных развивающихся языков (а в особенности с наличием метапрограммирования) данный подход на мой взгляд является тупиковым. К примеру moc можно было давным давно выкинуть из Qt, а ODB после выхода нового стандарта. Ну и плюс надо отметить, что у этого подхода обычно большие проблемы с редакторами кода.

Б. Реализация DSL средствами самого языка (EDSL). Понятно, что в первую очередь тут идёт речь об использование метапрограммирования, причём только времени компиляции. Большинство динамических языков обладают базовой возможностью метапрограммирования, но т.к. оно отрабатывает только во время исполнения программы, то к повышению эффективности работы программиста это имеет слабое отношение (максимум синтаксический сахар). Т.е. в итоге сюда попадает один мейнстрим язык и несколько языков второго эшелона. В общем случае разработка EDSL вдвойне сложная задача, т.к. требуется одновременно и разработать удобный новый язык и как-то вместить его в синтаксис базового. Однако на моей практике я чаще всего встречался с EDSL, являющимися встроенными реализациями каких-то уже готовых известных языков, так что авторам оставалась только половина проблемы. Как примеры для C++: регулярные выражения — Boost.Xpressive, грамматики — Boost.Spirit, SQL — sqlpp11. Ещё бывает просто прямое отображение предметной области типа Boost.Unit — физические размерности. Или более сложный пример из D: html шаблонизатор в vibe.d, поддерживающий вставки нативного кода, является реализацией синтаксиса jade (а те утащили его у Haml). Кстати, с возможностями нового стандарта C++ можно попробовать замахнуться на подобные вещи и уж точно можно переписать указанные выше библиотеки вообще без синтаксического шума (задавать DSL конструкции обычными строками, но при этом разбираемыми во время компиляции). В целом с выходом нового стандарта и появлением в boost'е набора библиотек поддержки, метапрограммирование на том самом мейнстрим языке перестаёт быть таким уж диким кактусом, как было когда-то. Что довольно печально для языков второго эшелона, главным преимуществом которых является развитое метапрограммирование. Хотя до реального удобства конечно же ещё очень далеко. Ну и отдельно можно заметить, что данный подход не приносит никаких проблем с редакторами кода. Правда и автодополнения по EDSL языку тут получиться не удастся.

Подводя итоги.

Если мы говорим о каких-то инновационных инструментах для работы с DSL (Nemerle, Nitra и т.п.), то как я понял (поправьте, если что), они могут относиться только к пункту 2.Б. А что у нас тут может быть инновационного? Поддержка каких-то очень сложных EDSL? Сомнительно... Кстати, а хотя бы поддержка тех, что есть у мейнстрим языка имеется? Т.е. могу я скачать готовые к продакшену EDSL библиотеки работы с sql, регулярными выражениями, физическими размерностями, html-шаблонизатор с нативными вставками и т.п? Ну и даже если могу, то всё равно этого мало — новому языку надо быть заметно лучше мейнстрима, чтобы были какие-то шансы. Насколько я помню у Nemerle тут была одна потенциальная киллер-фича — автодополнение по EDSL. Но она же вроде только для одной сомнительной IDE, что опять же вычёркивает это преимущество для очень многих пользователей. И вряд ли есть путь, как расширить это на все редакторы. В итоге я пока так и не понял, что в принципе инновационного могут принести эти решения в работу с DSL. Даже если бы они были реализованы под все платформы, а не только под .net.

P.S. Оффтопик. Написал всё это и увидел, что в принципе в выборе .net'a есть определённый смысл: 1. там нет никаких конкурентов по МП, 2. там общепринята та самая IDE. В итоге при таком раскладе уже появляются определённые шансы... Конечно при условии, что многим .net программистам интересны подобные сложные темы (про это я уже высказывал большие сомнения).
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.