Pull to refresh

Comments 70

Я, видимо, так и не смогу понять всей идеи до конца, без конкретного примера. Уж сколько читаю, много слов о том, как может быть улучшена разработка, чем лучше редактировать AST, но примера, наглядно показывающего, как можно получить результат с куда меньшими затратами, чем от обычного ЯПа, не видел.
Вы пользуетесь SQL или XPath? Теоретически, код на SQL, можно было бы заменить императивным кодом, который бы обращался к индексам базы данных, просматривал записи, итп, но в реальности никто этим практически не занимается (есть правда berkeley db, где можно все это сделать руками), тк SQL намного короче и понятней из-за близости к предметной области. Аналогичная ситуация с XPath.
Ну, я понимаю, зачем нужны DSL, я не понимаю, как MPS радикально упрощает их создание. Их вон что на лиспе, что на немерле, что на хаскеле клепают (и даже на C++), и текстовое представление вроде не было самой большой проблемой.

Попробую посмотреть презентацию.
Лисп решает проблему парсирования путем существенного ограничения синтаксиса, а это не всегда приемлемо. Например, сделать язык регулярных выражений чисто на s-выражениях, конечно, можно, но использовать это будет тяжело. Другая проблема это то, что лисп динамически типизированный язык, и поэтому сделать мощную IDE поддержку к нему тяжело.

Насчет хаскеля. То, что можно сделать на нем называется internal DSL-ями. Они возможны в принципе на любом языке, но более всего распостранены в питоне, руби итп. При этом подходе, конструкции основного языка используются для создания языка, но опять же, мы ограничены синтаксисом базового языка. Вставить, например, значок суммы, в язык мы не можем.

C немерле все хитрее. В немерле есть макры, но к сожалению, они позволяют добавлять только новые типы выражений, и имеют довольно ограниченный синтаксис. Туда нельзя вставить, например javascript, как мы постоянно делаем в charisma (посылаем javascript на клиент с сервера, чтобы его выполнить там). Вобщем, в немерле все лучше, чем в языках, где обычно делают internal DSL-и, но все равно далеко от идеала.
>> Туда нельзя вставить, например javascript, как мы постоянно делаем в charisma (посылаем javascript на клиент с сервера, чтобы его выполнить там).

о, восхитительно! тут теперь бы побольше подробностей… JS пишется прямо среди Java кода? захватывает переменные из окружающего java контекста?
Тогда такой вопрос в сторону… Предположим есть нужда поиграться с системой типов Java (добавить туда скажем value type) и сделать из него удобный язык системного программирования (нечто аналогичное тому, что делают в Jikes, см. например Demystifying Magic: High-level Low-level Programming...)… Поможет ли тут MPS или надо всё-таки пилить компилятор (e.g. javac)?
Это можно сделать и на MPS. Можно, разворачивать переменные valuet type-а на несколько локальных переменных.
а насколько это сложно вообще? т.е. если я хочу, чтобы для некоторого типа T выражение expr.f, где expr имеет тип T, преобразовывалось в Util.getWordAt (Util.address(expr), offset_of_f) на этапе компиляции/трансляции (где offset_of_f задаётся скажем аннотацией), много ли бы мне понадобилось кода написать?

а вообще я чувствую это прикольно, если бы я не уволился, то скорее всего постарался бы убедить коллег (и начальство) использовать MPS в нашем начинании… а то пилить javaс не так кошерно, как получить IDE поддержку сразу из коробки…

Для того, что вы описали, много кода не потребовалось бы. Простая замена вроде того, что вы описали, реализуется очень просто.
Правильно ли я понимаю, что при помощи MPS можно ввести в Java value types, которые будут размещаться не в куче, а на стеке (1), для которых будет автоматически осуществляться boxing/unboxing (2)?
Каким образом возможно реализовать данную функциональность, ведь для этого требуется серьезная модификация самой виртуальной машины и (возможно) байт-кода Явы?
Ну, например, если у нас value object на стеке, мы можем делать из него набор примитивных локальных переменных.

Например, был код

vector v =…

а мы сгенерировали из него

int _v_x =…
int _v_y =…

Тут, конечно, чтобы все это работало эффективно, придется ввести оптимизации и хитрые преобразования кода, но в принципе это возможно.

Таким образом, кстати, когда-то умел работать Microsoft JVM.
Хм… Таким образом все-таки получается, что ни один DSL, разработанный при помощи MPS, в реальности не может «выпрыгнуть» за пределы JVM и лишь является своего рода транслятором расширенного синтаксиса (представленного в виде семантического дерева) в Ява-код с последующих компилированием?

И еще вопрос: не является ли более разумным использование некоего валидатора различных DSL-расширений на предмет неоднозначности синтаксиса, чем использование специального редактора для ввода напрямую синтаксического дерева?
>Таким образом все-таки получается, что ни один DSL, разработанный при помощи MPS, в реальности не может «выпрыгнуть» за пределы JVM
Это не верно. MPS абсолютно language agnostic. У нас есть, например поддержка javascript. Генерить и расширять можно любой язык, если он реализован в MPS. С Java мы просто больше всего эксперементировали.

>И еще вопрос: не является ли более разумным использование некоего валидатора различных DSL-расширений на предмет неоднозначности синтаксиса, чем использование специального редактора для ввода напрямую синтаксического дерева?
Это плохое решение, по крайней мере для той задачи, которую мы решали, потому что мы не можем совмещать языки друг с другом, как мы могли бы делать с библиотеками.
Я немного запутался.
Наверное я не совсем правильно понял, в моем представлении MPS — это некий транслятор, позволяющий использовать произвольные расширения языка, которые потом транслируются либо в примитивы этого языка, либо в байт-код. Или у Вас MPS также выполняет роль виртуальной машины или статического компилятора?

Не совсем понятно, почему это «плохое решение». Какими критериями Вы руководствуетесь для его оценки? Я, честно скажу, пока не пробовал Ваше решение (а попробую я обязательно и с удовольствием, я собираюсь писать по DSL диплом), но мне вот так субъективно кажется, что вводить сразу конструкции в виде семантических деревьев, это как программировать использую Postfix-нотацию — привыкнуть да, можно, но все-равно неудобно. Нет?
если говорить про конкретно наши планы, то там предполагалась в том числе и модификации в нашем Java AOT-компиляторе, просто он принимает на вход не source code, а JBC, поэтому требовались протычке уже на этапе компиляции (в javac), ну и дополнительно хотелось сразу же на высокоуровневом представлении сделать проверки типов и другие радости (я даже помню воскресным вечерком накидал proof-of-concept плугины для Idea & Eclipse; хотя там и возникли потом проблемы с рефакторингом...).
О, как интересно!!!
Таким образом вы используете все эти расширения только при статической компиляции? Если нет, то какую JVM вы используете?
Кстати, ваш компилятор находится под какой лицензией?
я участвовал в обсуждении проекта (можно сказать, что я был одним из идеологов такой архитектуры), но уволился до того как проект начали реализовывать.

всё это планировалось делать в рамках Excelsior JET, на данный момент код его закрыт…
Вставить, например, значок суммы, в язык мы не можем

Если речь о юникоде, то вроде как можно, но думаю, что тут подразумевается что пошире. Однако это ведь вопрос представлений. Например, в хаскеле очень многое (в том числе автоматом) поддерживает класс Show и может быть выведено строкой. Формально, можно завести класс Edit, специальная реализация которой будет в вашем редакторе матрицу отображать матрицей и позволять её именно так редактировать. Однако это займет много времени, а толку мало.
Если я правильно понимаю, недостаток, например, compile-time преобразования строки (например, в TH или Nemerle) (а уж там можно назадавать любой синтаксис) в том, что это не будет поддерживается IDE?
А если хочется у суммы сабскрипт и суперскрипт поставить? Или хочется в код вставить диаграмму? Все это легко можно реализовать в MPS.

>Если я правильно понимаю, недостаток, например, compile-time преобразования строки (например, в TH или Nemerle) (а уж там можно назадавать любой синтаксис) в том, что это не будет поддерживается IDE?

Да нет, с этим все нормально, проблем нет. Например, IDEA, умеет понимать regexp-ы, когда они находятся в правильном контексте, и подсвечивать синтаксис внутри них.
Туда нельзя вставить, например javascript, как мы постоянно делаем в charisma


Вставить Javascript, чтобы послать с сервера на клиент, можно в любом языке, в котором поддерживаются строки:) Или вы написали расширение, которое отображается на Javascript? В таком случае, это можно сделать и на Nemerle: определить расширения синтаксиса языка, которые сами по себе не выполняют никаких действий, но выглядят так, что бы их комбинация походила на Javascript. Затем пишется макрос, который на вход принимает такой JS-like экспрешен анализирует его, так как у него есть доступ к AST и транслирует в JS. Можно вообще транслировать таким образом сам код Nemerle в JS.
Да, javascript у нас не обычный, а расширенный классами. А что с IDE поддержкой всего этого чуда?
Будет подсветка, если мапить код на Nemerle, то и Intellisence.
Вы про какой вариант? Про внутри строк? Или про трансляцию nemerle в javascript?
Про трансляцию Nemerle и/или расширении его новым синтаксисом.
Эффективная трансляция в javascript это очень непростая задача.
Подсветка будет, но про авто дополнение соврал — с макросами работаю мало: в текущем проекте парочка, что бы улучшить синтаксис (добавить flat map как оператор) и один посложнее, для преобразования AST.

Сейчас попробовал добавить поддержку вставки чего-то JS подобного в Nemerle:


Макрос javascript получает на вход Expression, который затем можно проанализировать и выполнять какие-либо действия на основе этого анализа. Кодируя вспомнил о том, что в Nemerle можно добавить только то, что выглядит похожим на Nemerle, например, скобки должны быть парными.

Из своего опыта разработки на Nemerle, понял, что добавление синтаксического сахара предоставляет некоторые удобства, но усложняют чтение кода по прошествии некоторого времени, так как нужно помнить, что же я имел ввиду этой закорючкой: "<+". Наиболее ощутимый результат дало применение макросов, которые сокращают рутинные шаблонные операции, например, объявление Dependency Properties при разработке интерфейсов или автоматическая реализация методов source.CopyTo(T target), где source имеет тип T. Но эти изменения происходят до предметной области — на уровне реализации. Отчасти это вызвано тем, что существует закон Мерфи: любая спецификация всегда изменяется, а из этого следует, что изменять каждый раз DSL в соответствии с изменениями в спецификации, вместо того, что бы писать код, устойчивый к ним, затратно.
Интеллектуальные IDE это не подсветкак синтаксиса с автодополнением. Это навигация, find usages, рефакторинги, подсветка ошибок и инспекции кода.

Но, вообще, прикольно. Способ решения проблемы поддержки языко-ориентированного программирования, не таким способом как у нас.
Отлично для новичков, жаль что я этот текст читал уже много раз (8
Это перевод моей статьи, да. Я его, правда, немного улучшил :)
>> Наша новая система учета ошибок, с кодовым именем Харизма, создана полностью на MPS, и это только начало.

о! это уже интересно. нельзя ли поподробней?

Харизму-то я давно видел… замечательная штука.

вы мне предлагаете изучить как MPS применяется в Харизме по ишуям? o_O
К сожалению, харизма сейчас коммерческий проект, так что сорцов мы не выложим. Но, вероятно, в ближайшем будущем языки, на которых сделана харизма будут сделаны публично доступными.
Да про сорцы мне тоже всё понятно было. Но ведь чтобы описать как там MPS применяется совсем не надо сорцов выкладывать.

Ну, например, можно было бы сказать, какие именно DSL там используются, для чего, чем это облегчило жизнь усталым пальцам программиста…

А вообще прикольная у вас контора, на острие прогресса так сказать…
Попробую в будущем что нибудь такое написать, где было бы видны плюсы мпса. Возможно, какие нибудь фрагменты кода из харизмы.
вы мне душу разбередили, теперь я борюсь соблазном не ждать, пока вы напишете статью, но зааплаится к вам… дабы посмотреть на всё это счастье своими глазами =)
Допустим, я хочу иметь сильно типизированный язык, с красивым синтаксисом, и хорошей IDE поддержкой. На scheme и lisp это плохо реализуется.
> сильно типизированный язык

Лиспов много.

> красивым синтаксисом

Синтаксис прикручивается любой.

> хорошей IDE поддержкой

emacs
зачем нужно Scheme, когда есть это?
можно подумать у вас тонко =)

зачем нужен mraleph, когда есть nikitad; зачем нужен nikitad, когда есть mraleph.
зачем нужно A, когда есть B?
зачем легион редакторов и еще больше языков программирования?

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

неужели это не прекрасно?
Судя по описанию это MPS по возможностям в плане разработки DSL есть неполноценные лиспы с визуальными свистоперделками. Но Сергей Дмитриев — молодец, берет деньги за то, что уже много лет существует бесплатно.
во-первых, как показывает жизнь визуальные свистоперделки иногда имеют значение.
во-вторых, MPS как таковая бесплатна, хотя нужно купить, наверное, идею…
MPS бесплатен, заопенсорсен, и более того, отлично работает без идеи.
неожиданно. я полагал, что это плугин к идее…
Он сделан на основе JetBrains IDE Framework. Этот фреймворк был выделен из IntelliJ IDEA, чтобы создавать новые IDE. Кроме MPS, есть наше Ruby IDE, RubyMine, и в ближайшем будущем будут еще IDE.
> во-первых, как показывает жизнь визуальные свистоперделки иногда имеют значение.

В данном случае они излишни. На лиспах можно спокойно за неделю наделать целую кучу микроязычков «для разработчика», с помощью которых сильно облегчить себе жизнь при разработке непосредственно самой программы. Можно встроить лиспы непосредственно в свою софтину и использовать их в качестве ДСЛ, и при этом продолжать испольвать Си или жабу или еще чего (так сделано в емаксе). При этом к языкам даже не обязательно прикручивать синтаксис — можно спокойно использовать синтаксис лиспа как представление АСД.

В случае с MPS разработчик во первых — привязан к языку, во вторых — привязан к «Идее».

ваш подход имеет право на существование.

но в случае больших проектов/консервативных сотрудников наличие IDE может играть существенную роль. я сам был участником группы, которая проектировала DSL, и пришлось пойти на ряд компромисов, чтобы не потерять поддержку в IDE.
А как вы интегрировали свой DSL в используемую IDE? В том же Емаксе это достаточно просто — тут и разукрашка синтаксиса будет, и автодополнение. Если постараться — то даже тегирование в ECB можно добавить и удобный рефакторинг.
пришлось сделать DSL синтаксически не отличающимся от Java.
ну и кстати: нужно вам расширить синтаксис Java, вы что будете делать? парсер Java на Lisp'е писать?

а нет! я знаю… вы на Lisp'e напишите конвертер Java-to-Lisp (и может даже Lisp-to-Java), а потом продолжите на Lisp'е колбасить =)
Нет, я возьму лисп, компилирующийся в байткод JVM, напишу что нужно, а потом буду вызывать это из самой основной программе на джаве.
ах, да… про всякие Closure я вечно забываю.
Про него как за не надо забывать, забывать надо Common Lisp, как устаревший и неудобный во многих случаях из-за недостатков стандарта, монстроузности, большой бедой с документацией в библиотекам, отсутствия нужных стандартизированных библиотек (например, для гуя), кривоватой реализацией модулей и пространств имен.
а как дела с системами контроля версий? и вообще что является результатом работы в «проекционном редакторе» и как в этом результате решается вопрос конфликта грамматик?
интересно былобы узнать подробней про «проекционный редактор»
Мы поддерживаем все version control системы, которые поддерживает IntelliJ IDEA. Единственное условие, для того, чтобы это все хорошо работало, все действия желательно делать из IDE. У нас есть и дифф и мерж. Более того, наш мерж может разрешить больше конфликтов, чем обычный текстовый мерж.

А что хочется узнать про проекционный редактор? Какая-то информация есть здесь: www.jetbrains.net/confluence/display/MPS/Editor Но, если вы хотите знать подробности, то советую скачать исходники, и посмотреть как он работает.
т.е. все файлы в итоге хранятся в спецформате (каком?) и дифф/патч реализуются «не стандартными» утилитами (собственно вашим редактором)?
формат закрытый?
кстати хабр схавал xml =)
Да нет не закрытый. Проект опен сорсный. В принципе, можно выдрать оттуда читалку/писалку, и использовать его в похожей системе.
а хотябы ссылочку на описание формата или название чтоб погуглить?
Ссылочки нигде нет. Единственный источник это исходники MPS-а (скачиваются с сайта).
А представление диффа и мержа, да на основе нашего редактора.
Все конечно очень классно, но порог входа для написания какого-нть Hello World под MPS, ИМХО, просто нереальный.

Подскажите, плиз - описали язык предметной области, а интеграция как происходит в проект? На примере самого простого примера (см. https://www.jetbrains.com/help/mps/shapes-an-introductory-mps-tutorial.html#goal) - могу ли я на вход дать текст вида:

Painting Test
circle x: 10 y: 10 radius: 30 Color: red
square x: 100 y: 200 size: 50 Color: green

чтобы получить картинку?

Sign up to leave a comment.

Articles