Re[4]: [Nitra] Пример простого языка вычисляющего выражения
От: VladD2 Российская Империя www.nemerle.org
Дата: 09.12.15 21:05
Оценка:
Здравствуйте, Kolesiki, Вы писали:

K>1. После ПЕГ пугает введение излишеств вроде "keyword regex". Я боюсь, что подобный "неявный помощник" заложит таймбомбу, что потом не разберёшься, почему один токен работает, а другой — нет.


Для "keyword regex" можно ввести дефолтную реализацию, которая будет использоваться, если он не задан явно.
В общем, учтем критику.

K>2. "...по_этому идентификатор разделяется на правило объявляющее имя символа (в данном случае "Name") и правило описывающее ссылку на имя" — когда и зачем это применять?


Для связывания имен. Нитра же не просто парсер. Она предоставляет законченное решение по типизации. Этот пример довольно простой, но и в нем есть объявление переменных и ссылки на них. Вот Name надо использовать там где вводится имя переменной, а Reference там где на это имя ссылаются из выражения.

K>Почему я не могу просто поставить какой-нибудь крючочек и конструктор сам догадается что нужно делать?


Нитре нужно показать где идентификатор используется как имя, а где как ссылка на него.

Почти любой компьютерный язык — это нечто вроде реляционной БД или объектной модели где есть записи/объекты и ссылки на них.

K>3. Каша из keyword, regex, token, syntax — у меня уже голова кругом.


Вот это уже не конструктивная критика. Любой серьезный генератор парсеров отличает лексерные правила (лексемы или токены) и рекурсивные. У нас есть всего лишь одно расширение лексемы могут быть token или regex. Причем regex — это оптимизация позволяющая уменьшить расход памяти и ускорить парсин. Освоить это можно за пять минут. "keyword" — это наверно от keyword regex. Это как раз средство упростить работу с PEG-ом. Вместо того чтобы в каждом правиле расставлять пробельные подправила нужно всего лишь один раз описать keyword regex и Нитра сама расставит пробельные правила во всей грамматике (где не указано, что этого не нужно делать). Я уже понял, что это дело по началу пугает. Мы спрячем это дело, так чтобы его нужно было использовать только в особых случаях. Все равно он в 99% случаев получается одинаковым.

K>Далее идёт отдельно три объявления syntax, а потом внутри syntax Expression ещё куча подправил. Как всё это разруливать?


Прочесть описание.

K>ПЕГ предлагает простую модель: терминалы и правила. Можно в Нитре оставаться в рамках модели ПЕГ?


ПЕГ довольно убог и ПЕГ это не более чем нотация. Алгоритм там Пакратом называется. Для применения в реальном мире его пришлось сильно докрутить. Для того же восстановления после ошибок нужно рабтать на уровне лексем.

K>4. Ладно, синтаксис описали — зачем ещё один Sample-Language.nitra? (причём в примере с NitraLanguage.nitra там ещё и цвета зачем-то захардкожены) Вроде б мы уже имеем "подсветку и претипринт", так мы ещё раз приседаем для какой-то другой утилиты?


А как ты предлагаешь сказать Нитре, что, скажем, переменные и ссылки на них нужно отдельными цветами выделять?

Сам language нужен чтобы определить данные для плагина к IDE и указать какое расширение будут иметь файлы твоего языка. Если ты расширяешь язык, то language вообще не обязателен. Описывать цвета тоже не обязательно. Но это же пример! Он демонстрирует разные аспекты.

K>5. Далее АСТ: вообще весь файл ни о чём, кроме знакомых строк, которые я уже как бы описал в SampleSyntax:

K>"ast Sum : Binary { Result = Expression1.Result + Expression2.Result; }"

Как раз этот весь файл о самом важном. Там декларативно описана семантика языка. Этот синтаксис не так важен, на самом деле. А семантика — это соль языка. Куда важнее какого-то там сложения то, что объявляется область видимости и в ней декларируются переменные. В более серьезном языке и области видимости будут намного сложнее и деклараций больше.

Весь смысл примера как раз дать примитивный пример областей видимости и деклараций.

K>Все эти ContainingTable, stage 1, Reference — это, вероятно, какие-то чертовски важные детали, но которые со стороны выглядят как лапша, торчащая из коллайдера.


Ну, дык может стоит сначала прочитать описание
Автор(ы):
?

K>У нас простой язык: список присвоений, переменные, арифм.выражения, числа, операторы, скобки. Они структурированы в дерево. Всё. Но никакого дерева в Sample-Ast.nitra я не вижу — тону в дебрях.


У нас нет цели создать простой язык. Его и вручную можно создать. У нас цель продемонстрировать те самые средства, которые тебе пока непонятны. Просто это минимальный пример на котором они вообще имеют смысл.

K>6. Отображение — тут выглядит всё просто, но опять же — из-за простоты и дублирования кажется, будто делаешь одну и ту же работу трижды.


Вот тут согласен. Более того в сложных случаях отображение еще и не так очевидно как кажется на первый взгляд. Возможно стоит покапать в сторону выражения синтаксиса через АСТ. Но это серьезное исследование которое придется оставить на будущее.

K>Здесь всё понятно, кроме одного — что, все эти пляски с АСТ создавались из-за одной единственной фигни под названием partial class? Повторюсь, мне кажется можно взять простое дерево разбора и запрашивать у него инфу через хелперы (которые, никто не запрещает, могут построить некий внутренний АСТ для ускорения работы).


Не "из-за", а "в том числе из-за". За АСТ много аргументов. Просто для их понимания опять таки требуется погружение в детали.

K>7. Ну и довершает пасквиль на могиле моего понимания "последний штрих" обвязочного кода, потому что мы и так уже предостаточно наописывали для АСТ, чтоб теперь ещё и приседать вокруг него.


Этот код не айс и позже мы его задслим. Но он необходим, если мы хотим рабоать не с одним файлом, а с целым проектом (где таких файлов может быть много). Опять таки это пример. Нам важно показать что нужно сделать для поддержки реального языка. Этот код будет почти идентичен как для вот такой малютки, так и для огромного C#-а. В нем нужно связать асты всех файлов в единое пространство вычислений.

K>Громоздко, загромождено деталями, непонятно — вот так для меня выглядит ещё простой! язык арифметики. Видимо, Нитра будет инструментом для ооочень избранных головастиков, я такой "упрощающий инструмент" едва ли постигну.


Ну, вот тут рядом novitk попытался реализовать этот же простой пример на самом продвинутом в мире (по его мнению) языке — Скале. Можешь поглядеть как у него все просто получилось. И это при условии, что он не реализовал тучу всего, что предоставляет Нитра из коробки за бесплатно.

Будем шлифовать. Что-то можно сделать по умолчанию. Что-то запихнуть в библиотеки. С маппингом нужно серьезно подумать. Но в целом, скорее всего, сказывается просто непонимание синтаксиса и того, что получается в результате. Попробуй сначала прочесть описание, а потом взглянуть еще раз.

Ну, и нужно понимать, что Нитра не создавалась для подобных простых языков. Она рассчитана на создание расширяемых C# и Nemerle 2. Код их компиляторов сложнее в тысячи раз, а поддержка IDE захардкожена и содержит много букв. Тут же ты предоставляешь описание и получаешь все в автомате (и поддержку IDE, и связывание/резолв имен, и произвольные расчеты независящие от порядка их описания).

Я понимаю, что это трудно оценить по достоинству без погружения. Но оно того стоит. Так же надо понимать, что это примеры создания языка с нуля. А для реального использования это не особо нужно. Большинству людей будет нужно создать мелкое расширение с нуля или тупо взять за основу язык и на его основе написать свой, похожий.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: [Nitra] Пример простого языка вычисляющего выражения
От: xvost Германия http://www.jetbrains.com/company/people/Pasynkov_Eugene.html
Дата: 09.12.15 21:08
Оценка:
Здравствуйте, VladD2, Вы писали:

А когда парсер С# в РеШарпере будет написан на Nitra вместо PsiGen'а?
С уважением, Евгений
JetBrains, Inc. "Develop with pleasure!"
Re[13]: [Nitra] Пример простого языка вычисляющего выражения
От: novitk США  
Дата: 09.12.15 21:19
Оценка: :)
Здравствуйте, _NN_, Вы писали:

_NN>А как хочется наблюдать ?

_NN>Неужели визуализатора и работы в VS недостаточно ?

Визуализатор? Полезная штука для отладки. В ANTLR он тоже есть, но это всего лишь один из аспектов. Лично я не готов платить за его наличие громоздкостью комбайна сделанного исключительно под C#-подобный язык для крошечного ДСЛ в нашем примере.

Обычный unix-way — дайте мне лучшие компоненты, я сам соберу из них, что мне нужно.
Re[2]: [Nitra] Пример простого языка вычисляющего выражения
От: VladD2 Российская Империя www.nemerle.org
Дата: 09.12.15 21:37
Оценка:
Здравствуйте, xvost, Вы писали:

X>А когда парсер С# в РеШарпере будет написан на Nitra вместо PsiGen'а?


Это не от нас зависит, как ты понимаешь. Он ведь и так работает и каши не просит. Вокруг все скептики. Те кто исследователи по натуре переключились на Котлин. Найтра никому не интересна. Путь даже код Решарпера сжался бы в 10 раз будучи переписанным на Найтре и стал бы в 100 раз понятнее и стабильнее, но никто на это не решится.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: [Nitra] Пример простого языка вычисляющего выражения
От: VladD2 Российская Империя www.nemerle.org
Дата: 09.12.15 21:51
Оценка:
Здравствуйте, novitk, Вы писали:

N>твои примеры, расширяемость операторов и прочие шлюхи.


Шлюх не заметил. В прочем, теперь там черт ногу сломит.

Что там у тебя с восстановлением после ошибок? Как организовать подсветку и переходы к определению переменных в редакторе? Сколько там еще нужно "строчек"?

Обработка ошибок на исключениях — это вообще прелесно! О востановлении после ошибок можно сразу забыть. Еще нужно незабыть написать код обработки этих исключений и вывода людям в человеческой форме.

N>"Уродец" это субъективно, а вот 50 строчек, Карл, нет.


Уродец это объективно. Как бы язык там можно разглядеть только очень напрягшись. То что ты его упаковал в 50 строк не исправляет того факта, что это 50 строк говнокода, которые при росте сложности языка превратится в вечную попоболь. Да и более 50 строк там уже.

Еще прибавь сюда тормоза, так тавои комбинаторы это треш с точки зрения производительности.

В итоге получается унылое говно которое совершенно невозможно читать, сложно поддерживать, которое тормозит и кидается исключениями вместо диагностики. И это на примитивном примере.

На Нитре тоже можно написать в подобном стиле. Не в том смысле что можно получить такой говнокод, а в том смысле, что можно обойтись без АСТ, символов, и зависимых вычислений. В Нитре есть rule-методы, которые так же позовляют размазать код вычислегний по дереву разбора (см., например, пример калькулятора
Автор: VladD2
Дата: 09.12.15
). Суть примера в том, чтобы показать как и для чего используются средства Нитры. Конечно, если хочешь увидеть выигрыш от применения Нитры, лучше смотреть код типизации Шарпа или самой Нитры. Именно ради таких задач и создавались все эти навороты.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: [Nitra] Пример простого языка вычисляющего выражения
От: VladD2 Российская Империя www.nemerle.org
Дата: 09.12.15 22:00
Оценка:
Здравствуйте, novitk, Вы писали:

N>По остальным пунктам поясню. Я это фрагмент сделал лишь потому, что Влад усомнился в возможности сделать его пример сравнимым количеством кода без Нитры, а не потому что я тебя не уважаю или считаю что Нитра не нужна. Все, горячится не надо.


Так ты до сих пор и не убидел. Я же тебе сразу сказал, что у тебя нет:
1. Восстановления после ошибок.
2. Нормальной диагностики ошибок.
3. Поддержки IDE (навигация, подсветка, реалтаймная подсветка ошибок).
4. Да что уж там? Просто читабельного решения нет. Ты этим примером людей Скалы реально отпугнул.

Это уже будет не 50 и даже не 500 строк. Это ты вообще не потянешь. А тут из коробки. За здорово живешь.

Ну, и комбинаторы твои — тормоза. В Скле вроде как появлися вариант на макрах. Это аналог нашего PegGrammar-а
Автор(ы): Чистяков Владислав Юрьевич
Дата: 07.06.2011
Макрос PegGrammar – это макрос Nemerle, позволяющий добавлять в приложения парсеры, описываемые в нотации PEG.
, только с более убогим синтаксисом (патамушта расширение синтаксиса нам не нужно (ц)). Попробуй на нем, что ли, а не на этих убоги комбинаторых.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[11]: [Nitra] Пример простого языка вычисляющего выражения
От: WolfHound  
Дата: 09.12.15 22:01
Оценка: +1
Здравствуйте, novitk, Вы писали:

WH>>Часть замечаний ты замазал.

N>Не "замазал", а "исправил". Что за хамская манера?
Это именно что замазал. Исправил, это когда ты можешь показать все сообщения об ошибках.

WH>>Но большая часть осталась.

N>Перечисли. Типизации в этом примере нет. Раскраска и прочая гуйня выведет размер за разумные рамки, но что тут интересного?
То что нитра даёт это всё бесплатно. Причём качественно.
А с твоим подходом это всё за разумными рамками.

WH>>А главное код стало понять ещё сложнее.

N>Перестань. Любой ФПишник сможет поддерживать этот код, тем более что у него сейчас есть нормальная IDE.
Давай спросим у ФПшников, какой код им будет проще поддерживать?

Пойми, тут никто не сомневался, что можно как-то написать код, который будет делать что-то похожее.
Разговор был про качественное воспроизведение всего функционала.
... << RSDN@Home 1.2.0 alpha 5 rev. 62>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[12]: [Nitra] Пример простого языка вычисляющего выражения
От: VladD2 Российская Империя www.nemerle.org
Дата: 09.12.15 22:04
Оценка:
Здравствуйте, novitk, Вы писали:

N>Не совсем так. Я как раз неплохо понимаю, что они делают и как. Просто они претендуют на некоторую универсальность и революционность, которой я не наблюдаю. А как конструктор для Немерле 2 или как оно там теперь называется, проект имеет право на жизнь. На мой вкус переборщили с DSL-ами, но я списываю это на их фанатизм и мой субъективизм.


Мне кажется ты отлично показал, что наши ДСЛ-и намного читабельнее чем, то что можно выжать даже из очень продвинутой Скалы (без расширения синтаксиса).

Влад сразу сказал: "сделай — сравним". Вот теперь есть что сравнивать и есть на что указывать. Можно спросить у окружающих. Считают ли они твой вариант человеко-читаемым и считают ли они достоинством компактность в ущерб понятности.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[11]: [Nitra] Пример простого языка вычисляющего выражения
От: VladD2 Российская Империя www.nemerle.org
Дата: 09.12.15 22:09
Оценка:
Здравствуйте, novitk, Вы писали:

N>Перечисли. Типизации в этом примере нет. Раскраска и прочая гуйня выведет размер за разумные рамки, но что тут интересного?


Ну, дык интересно то, что в нашем то примере все это есть, так как Нитра именно для этого и нужна.

WH>>А главное код стало понять ещё сложнее.

N>Перестань. Любой ФПишник сможет поддерживать этот код, тем более что у него сейчас есть нормальная IDE.

Перестань. Любой разумный программист перепишет этот код. И пусть он станет в 10 раз длинне, но его можно будет читать, а не только писать.

Это форменный говнокод. Вычисления перемешаны с правилами грамматики так, что нужно пол часа вчитываться, чтобы понять что где.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[14]: [Nitra] Пример простого языка вычисляющего выражения
От: VladD2 Российская Империя www.nemerle.org
Дата: 09.12.15 22:17
Оценка:
Здравствуйте, novitk, Вы писали:

N>Визуализатор? Полезная штука для отладки. В ANTLR он тоже есть, но это всего лишь один из аспектов.


В ANTLR нет ничего кроме парсера. Их ГУЙ о том как отлаживать грамматики. Это у них сделано отлично. Но сравнивать их невозможно. Разные задачи и разные возможности.

Закладку что показал NN используют для отладки типизации, а не парсинга. Как раз средств отладки парсинга у нас мало.

N>Лично я не готов платить за его наличие громоздкостью комбайна сделанного исключительно под C#-подобный язык для крошечного ДСЛ в нашем примере.


Ну, ты же понимаешь, что пример крошечный специально, чтобы людей не грузить? Естественно Нитра не для подобных игрушек сделана. Проблема в том, что если я покажу реально мозговышибательные вещи типа вычисления областей видимости и связывания для C#, то понять это без подготовки не сможет никто. Вот мы и придумали (за 20 минут до презентации) язычок в котором все просто, но есть на чем показать связывание и таблицы имен.

N>Обычный unix-way — дайте мне лучшие компоненты, я сам соберу из них, что мне нужно.


Ты уже скала-вей показал. Собрал страшилку.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Отредактировано 09.12.2015 22:30 VladD2 . Предыдущая версия .
Re[12]: [Nitra] Пример простого языка вычисляющего выражения
От: novitk США  
Дата: 09.12.15 22:36
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Это форменный говнокод.

Это абсолютно обычный FP-код. Вам parsec не нравиться что-ли? Его там всего 4 строчки. Предположи, что я взял ANTLR или что тебе там нравится, и забудь.

VD>Вычисления перемешаны с правилами грамматики так, что нужно пол часа вчитываться, чтобы понять что где.

O чем ты? EvalContext абсолютно независим от парсера. Я поместил его в один файл только для удобства оформления.
Re[10]: [Nitra] Пример простого языка вычисляющего выражения
От: novitk США  
Дата: 09.12.15 23:59
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Шлюх не заметил. В прочем, теперь там черт ногу сломит.

VD>Что там у тебя с восстановлением после ошибок? Как организовать подсветку и переходы к определению переменных в редакторе? Сколько там еще нужно "строчек"?
А почему у вас нет автоматической трансляцией под CUDА или генерации документации по ГОСТ#123.б ?!
Если серьезно, то с подсветкой у меня все ровно так же как и у тебя — надо писать код. Так как этот код из Нитры ты не привел с чем мне мой сравнивать?
Безусловно "из коробки" у вас много и это прекрасно. Меня только цена не устраивает для моих целей.

VD>Обработка ошибок на исключениях — это вообще прелесно! О востановлении после ошибок можно сразу забыть. Еще нужно незабыть написать код обработки этих исключений и вывода людям в человеческой форме.

Дак, а откуда ты знаешь какая семантика обработки ошибок будет нужна. Может мне будет надо спустить унитаз на "a=b;b=a"?
Дефолтная семантика нитры делает конечно больше чем скалы, но это потому, что кто-то написал код, см выше.

VD>Еще прибавь сюда тормоза, так тавои комбинаторы это треш с точки зрения производительности.

Правильно, поэтому завтра я могу выкинуть эти комбинаторы и взять ваш крутой парсер, но при этом оставить свой "крутой" RP-pull граф с ассинхронностью и паралеллизацией, а не ваш детский сад под названием "зависимые свойства". Под "свою" имеется ввиду, то что мы используем в продакшене, а не в моем примере. Unix way, brother! Нет я конечно понимаю, что можно использовать только ваш парсер, но клеить-то придется на N, а значит ваш парсер тоже идет в топку.

VD>В итоге получается унылое говно которое совершенно невозможно читать, сложно поддерживать, которое тормозит и кидается исключениями вместо диагностики. И это на примитивном примере.

за час изобразить все что вы придумывали и писали пятилетку? Вопрос стоял не так. Я всего лишь сказал, что опишу синтакс и семантику вычислений компактней.
Re[11]: [Nitra] Пример простого языка вычисляющего выражения
От: WolfHound  
Дата: 10.12.15 00:14
Оценка:
Здравствуйте, novitk, Вы писали:

N>Если серьезно, то с подсветкой у меня все ровно так же как и у тебя — надо писать код. Так как этот код из Нитры ты не привел с чем мне мой сравнивать?

Это вообще к делу не относится.
Мы же у тебя не требуем код скалы и парсеркомбинаторов.

N>Безусловно "из коробки" у вас много и это прекрасно. Меня только цена не устраивает для моих целей.

А что с ценой?
Даже на игрушечном примере она намного меньше, чем с твоими подходами.

N>Дак, а откуда ты знаешь какая семантика обработки ошибок будет нужна. Может мне будет надо спустить унитаз на "a=b;b=a"?

1)Получи сообщение об ошибки и спускай.
2)Единственная разумная реакция компилятора на ошибку это показать её пользователю.

N>Правильно, поэтому завтра я могу выкинуть эти комбинаторы и взять ваш крутой парсер, но при этом оставить свой "крутой" RP-pull граф с ассинхронностью и паралеллизацией, а не ваш детский сад под названием "зависимые свойства".

И где можно на него посмотреть?
После чего мы посмотрим, где детский сад.

N>за час изобразить все что вы придумывали и писали пятилетку? Вопрос стоял не так. Я всего лишь сказал, что опишу синтакс и семантику вычислений компактней.

Хватит уже выкручиваться.
Замахнулся на то, что не можешь осилить. Бывает.
Признай, что был не прав, и закончим на этом.
... << RSDN@Home 1.2.0 alpha 5 rev. 62>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[3]: [Nitra] Пример простого языка вычисляющего выражения
От: _someuser  
Дата: 10.12.15 09:36
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, xvost, Вы писали:


X>>А когда парсер С# в РеШарпере будет написан на Nitra вместо PsiGen'а?


VD>Это не от нас зависит, как ты понимаешь. Он ведь и так работает и каши не просит. Вокруг все скептики. Те кто исследователи по натуре переключились на Котлин. Найтра никому не интересна. Путь даже код Решарпера сжался бы в 10 раз будучи переписанным на Найтре и стал бы в 100 раз понятнее и стабильнее, но никто на это не решится.


В этом плане интересен вопрос, как будет отличаться производительность реализации парсера и типизации на найтре от решарпера или рослина. Скажем, насколько знаю, в рослине поддерживается инкрементальный парсинг, а в найтре пока нет (насколько понял планируется, но пока не в приоритете). Интересно узнать, у вас, как разработчиков найтры, какие мысли по поводу производительности? Т.е. почему ваша реализация будет работать не медленнее или быстрее?
Re[13]: [Nitra] Пример простого языка вычисляющего выражения
От: VladD2 Российская Империя www.nemerle.org
Дата: 10.12.15 10:57
Оценка:
Здравствуйте, novitk, Вы писали:

N>Это абсолютно обычный FP-код.


Это ты рассказываешь человеку который каждый день ФП применяет. ФП разное бывает. Бывает по делу, а бывает набор спермитазойдов и смайликов, как в твоем случае.

И это не мудрено. Для описания парсеров нужна грамматика, а не ее кодирование с помощью смайликов.

Вот это:
syntax module SampleSyntax
{
  using Nitra.Core;
  using Nitra.CStyleComments;

  regex Keyword = "var";

  [Reference] token Reference = !Keyword IdentifierBody;
  [Name]      token Name    = !Keyword IdentifierBody;

  [StartRule] syntax TopRule = (VariableDeclaration nl)*;

  syntax VariableDeclaration = "var" sm Name sm "=" sm Expression ";";

  syntax Expression
  {
    | [SpanClass(Number)] Num = Digits {  Digits = ['0'..'9']+; }
    | Braces = "(" Expression ")";
    | Variable = Reference;
  precedence Sum:
    | Sum = Expression sm Operator="+" sm Expression;
    | Sub = Expression sm Operator="-" sm Expression;
  precedence Mul:
    | Mul = Expression sm Operator="*" sm Expression;
    | Div = Expression sm Operator="/" sm Expression;
  precedence Unary:
    | Plus  = Operator="+" Expression
    | Minus = Operator="-" Expression
  }
}

грамматика.
А это:
  class Expr;
  class BinOp(val evalF: (Int, Int) => Int, val expr: Expr);
  def mkBinOp = (new BinOp(_, _)).curried
  val binOpGroups = Seq(
      Seq("*" -> mkBinOp(_*_), "/" -> mkBinOp(_/_)),
      Seq("^^" -> mkBinOp(Math.pow(_, _).toInt)),
      Seq("+" -> mkBinOp(_+_), "+" -> mkBinOp(_+_)))

  case class NumberExpr(num: Int) extends Expr;
  case class VarExpr(name: String) extends Expr;
  case class OpExpr(expr: Expr, subExprs: List[BinOp]) extends Expr;
  class VarDef(val name: String, val expr: Expr)
  
  def makeOpExpr(p: ~[Expr, List[BinOp]]): Expr = p match {
    case f ~ Nil => f
    case f ~ l => OpExpr(f, l)
  }
  def binOpGroupParser(termAbove: Parser[Expr], opGroup: Seq[(String, Expr => BinOp)]): Parser[Expr] = {
    val opGroupParsers = opGroup.map { case (opCode, constr) => opCode ~> termAbove ^^ constr }.reduce(_|_)
    (termAbove ~ rep(opGroupParsers)) ^^ makeOpExpr
  }  

  def factor: Parser[Expr] = wholeNumber ^^ (s => NumberExpr(s.toInt)) | ident ^^ VarExpr | "(" ~> expr <~ ")"
  def expr: Parser[Expr] = binOpGroups.foldLeft(factor)(binOpGroupParser(_, _))
  def varDef: Parser[VarDef] = ("var" ~> ident) ~ ("=" ~> expr <~ ";") ^^ { case n ~ e => new VarDef(n, e) }
  def varDefParseAll(in: CharSequence): ParseResult[VarDef] = parseAll(varDef, in)

закарючки.

N>Вам parsec не нравиться что-ли?


Конечно, нет. Грамматика ANTLR мне нравится, а закарчки на Хаскеле эмулирующие грамматику — нет.

N>Его там всего 4 строчки. Предположи, что я взял ANTLR или что тебе там нравится, и забудь.


Зачем мне что-то предполагать? Ты обещал, что на Скале будет проще. Я вижу что получился какой-то не читаемый пипец с кучей упрощений, не поддерживающий IDE ни в каком виде и в добавок еще и потенциально тормозной из-за комбинаторов.

VD>>Вычисления перемешаны с правилами грамматики так, что нужно пол часа вчитываться, чтобы понять что где.

N>O чем ты?

Вот об этом "(s => NumberExpr(s.toInt))", об это "{ case n ~ e => new VarDef(n, e) }" и о другой грязи.

Я уже говорил, о том, что это мы проходили уже очень давно. У нас есть в разы более чистый путь — rule-методы:
  syntax Expr
  {
    Value() : double;

   | [SpanClass(Number)] Number
      {
        regex Digit = ['0'..'9'];
        regex Number = Digit+ ('.' Digit+)?;
 
        override Value = double.Parse(GetText(Number));
      }

    | ParenthesesParentheses = '(' Expr ')' { override Value = Expr.Value(); }
  precedence Additive:
    | Add         = Expr '+' Expr { override Value = Expr1.Value() + Expr2.Value(); }
    | Sub         = Expr '-' Expr { override Value = Expr1.Value() - Expr2.Value(); }
  precedence Multiplicative:
    | Mul         = Expr '*' Expr { override Value = Expr1.Value() * Expr2.Value(); }
    | Div         = Expr '/' Expr { override Value = Expr1.Value() / Expr2.Value(); }
  precedence Power:
    | Pow      = Expr '^' Expr precedence 30 right-associative { override Value = Math.Pow(Expr1.Value(), Expr2.Value()); }
  precedence Unary:
    | Neg         = '-' Expr { override Value = -Expr.Value(); }
  }

это выглядит не плохо только на примитивных примерах. Смешение кода и грамматики — плохая идея. Да и вычисления прямо на дереве разбора — тоже.

В серьезных языках нужны такие вещи как полмиморфизм, разделение грамматики и семантики, неявное задание последовательности вычислений и т.п.

Так же есть и чисто технические аспекты которые на практике так же важны.

N>EvalContext абсолютно независим от парсера. Я поместил его в один файл только для удобства оформления.


Сомнительное удобство, кстати. Погоня за минимизацией символов. Людям это не надо. Людям нужно минимизировать число сущностей которые они обязаны одновременно держать в голове. А количество строк их абсолютно не волнует. Иначе все писали бы даже не на Хаскеле, а на каком нибудь J или K.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Отредактировано 10.12.2015 13:00 VladD2 . Предыдущая версия .
Re[11]: [Nitra] Пример простого языка вычисляющего выражения
От: VladD2 Российская Империя www.nemerle.org
Дата: 10.12.15 11:48
Оценка:
Здравствуйте, novitk, Вы писали:

VD>>Что там у тебя с восстановлением после ошибок? Как организовать подсветку и переходы к определению переменных в редакторе? Сколько там еще нужно "строчек"?

N>А почему у вас нет автоматической трансляцией под CUDА

Почему нет? Есть. В Nemerle есть макросик поддерживающий CUDА.

N>или генерации документации по ГОСТ#123.б ?!


За ГОСТ не скажу, но о том чтобы добавить поддержку автоматизации документирования я давно подумываю. Ее отстутствие это недостаток.

Просто это не так критично как возможность удобно редактировать код на своем языке. И это не так сложно реализовать.

Любой кто создает свой язык (даже самый примитивный) хочет чтобы у него была максимально удобная поддержка IDE. Вот только это очень сложно. Так что большинство на это забивают. Мы же предоставляем базовые сервисы почти бесплатно. Да, нужно немного больше аннотаций, но это не сравнимо с затратами на разработку собственного плагина к IDE.

N>Если серьезно, то с подсветкой у меня все ровно так же как и у тебя — надо писать код.


Тебе ведь уже приводили примеры того как с этим "у меня". Того описания что я привел достаточно для получения не только подсветки, но и полнофункциональной поддержки IDE. К твоим услугам и навигация к определению переменных, и подсветка корректных ссылок на них (причем ты сам можешь задать стиль, а пользователь потом сможет настроить его в IDE), и поиск вхождений, и поддержка проекта, и реалтаймное выведение сообщений об ошибках.

Так что вое решение не только менее читабельно, но и намного менее функционально. Чтобы его приблизить к нашему тебе придется сделать все что сделали мы. А это годы работы. 99% просто не осилят ее никогда.

N>Так как этот код из Нитры ты не привел с чем мне мой сравнивать?


Я привел весь необходимые код. Все остальное делает Нитра. Ах, да. Забыл. Еще нужен скрипт для генерации плагина. Он выглядит примерно так:
Nitra.LanguageCompiler.exe MyLang.dll

На выходе будет клагин к Решарперу. Потенциально можно генерировать плагины к любой IDE. Так же можно сделать генерацию исполняемых файлов под любую платформу. И все это потому что у нас DSL-и, а не хардкод на Скале или Немрле. Мы просто читаем исчерпывающее описание и генерируем по нему нужный код.

N>Безусловно "из коробки" у вас много и это прекрасно. Меня только цена не устраивает для моих целей.


А что с ценой то не так? Все объективная критика пока что сводится к тому, что многим кажется, что АСТ и мапинг лишние. Ну, да на простых примерах они кажутся лишними. Ну, да можно как-то оптимизировать это дело. Но по сути там ничего лишнего. Каждое решение взвешивалось по сто раз и является обоснованным.

VD>>Обработка ошибок на исключениях — это вообще прелесно! О востановлении после ошибок можно сразу забыть. Еще нужно незабыть написать код обработки этих исключений и вывода людям в человеческой форме.

N>Дак, а откуда ты знаешь какая семантика обработки ошибок будет нужна. Может мне будет надо спустить унитаз на "a=b;b=a"?

Я не знаю. Я проставляю средства для этого. Я знаю только, что ошибки люди хотят видеть не виде трапов IDE и компилятора, а в виде списка выведенного на экран (на консоль в компиляторе и в GUI-список в IDE).

Ошибки парсинга вообще не должны заботить пишущего код человека. Мы обеспечиваем восстановление после ошибок и формирование внятных сообщениях о них. И это все на основании той самой грамматики. Никаких дополнительных приседаний. Ошибки связывания так же выводятся автоматически. А если нужны какие-то семантические проверки и сообщения, то у нас есть простой механизм выдать их. Примерно так:
ast Xxxx
{
  ...
  when (делаем проверку обращаясь к зависимым свойствам)
    Error(сообщаем об ошибке);
}


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

N>Дефолтная семантика нитры делает конечно больше чем скалы, но это потому, что кто-то написал код, см выше.


Естественно! И еще потому что мы пишем на не Немерле, а на языке (точнее языках) специально предназначенном для решения этой задачи. Когда его проектировали, то все это предусмотрели.

Конечно же ты ты тоже можешь на Скале написать такой же язык, но это и будет аналог Нитры.

Вот именно по этому решение на Скале никогда не будет конкурентом решению на Нитре. Чтобы сделать аналогичное решение ты будешь вынужден написать на Скале аналог Нитры.

N>Правильно, поэтому завтра я могу выкинуть эти комбинаторы и взять ваш крутой парсер, но при этом оставить свой "крутой" RP-pull граф с ассинхронностью и паралеллизацией, а не ваш детский сад под названием "зависимые свойства".


Надеюсь, что когда ты поймешь что такое зависимые свойства и для чего они нужны тыне будешь говорить такие глупости. Зависимые свойства — это возможность произвести вычисления по разобранному коду при этом не задавая их порядок явно и имея возможность в любой момент расширить их новыми конструкциями не меняя реализацию базового языка.

В немерловых макросах (как и в скалоских) такой штуки очень не хватает. Но для того чтобы понять это нужно попробовать написать что-то не тривиальное, что требует ожидания наличия нужных данных от компилятора или создание собственных проходов компиляции.

N>Под "свою" имеется ввиду, то что мы используем в продакшене, а не в моем примере.


Похоже ты даже не понял, что зависимые свойства работают во время компиляции. Ты явно путаешь их с собственной моделью вычислений.

Пойми ЗС — это средство сделать типизацию декларативной и независимой от последовательности вычислений.

N>Unix way, brother! Нет я конечно понимаю, что можно использовать только ваш парсер, но клеить-то придется на N, а значит ваш парсер тоже идет в топку.


Если ты о зависимости от платформы, то мы проектировали все так, чтобы можно было относительно легко портировать языки написанные на Нитри (а значит и саму Нитру) на другие платформы. Это не тривиальное занятие и у нас нет на него сил/времени, но технически это возможно.

N>за час изобразить все что вы придумывали и писали пятилетку? Вопрос стоял не так. Я всего лишь сказал, что опишу синтакс и семантику вычислений компактней.


Ты сказал, что реализация будет не больше. Но твоя реализация не равноценна. Она много чего не умеет и срезает углы. При этом она получилась очень запутана.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: [Nitra] Пример простого языка вычисляющего выражения
От: VladD2 Российская Империя www.nemerle.org
Дата: 10.12.15 12:40
Оценка:
Здравствуйте, _someuser, Вы писали:

_>В этом плане интересен вопрос, как будет отличаться производительность реализации парсера и типизации на найтре от решарпера или рослина. Скажем, насколько знаю, в рослине поддерживается инкрементальный парсинг, а в найтре пока нет (насколько понял планируется, но пока не в приоритете).


Основная наша цель на сегодня обеспечить приемлемую для использования в IDE производительность. Мы вибираем архитектуру позволяющую достичь необходимой производительности. На оптимизации времени не хватает. Не буду скрывать. Но все спроектировано так, чтобы оптимизации было не сложно добавить в дальнейшем (и при этом не пришлось бы сильно все менять).

В конечном итоге планируем сделать и инкрементальный парсинг, и инкрементальную типизацию. Те же зависимые свойства выбраны, в не малой степени, с учетом того, что их можно пересчитывать инкрементально.

_>Интересно узнать, у вас, как разработчиков найтры, какие мысли по поводу производительности? Т.е. почему ваша реализация будет работать не медленнее или быстрее?


Мы не гарантируем, что она будет быстрее любой другой. Это физически невозможно, так как конкретную реализацию всегда можно заоптимизировать сильнее, чем общую. Мы делаем так, чтобы производительности хватало для комфортного использования. Скажем, если мы печатаем в редакторе, то не должно возникать тормозов. То же инкрементальное редактирование нужно именно для того, чтобы комфортно печатать было и в больших файлах.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Отредактировано 10.12.2015 13:10 VladD2 . Предыдущая версия .
Re[11]: [Nitra] Пример простого языка вычисляющего выражения
От: VladD2 Российская Империя www.nemerle.org
Дата: 10.12.15 12:49
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Это конечно интересно , однако людям нужны простые примеры.


Вот видишь? Сделали простой пример, так сразу нашлись любители докопаться до радио, которые вместо того, чтобы на их основе понять как что работает в Найтре, начали обсуждать объемы кода и другую "важную" пенесометрию.

Возможно надо просто разбирать каждую особенность по отдельности и приводить отдельные примеры.

Если есть идеи примеров — подкидывайте.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: [Nitra] Пример простого языка вычисляющего выражения
От: VladD2 Российская Империя www.nemerle.org
Дата: 10.12.15 13:52
Оценка:
Здравствуйте, Kolesiki, Вы писали:

VD>>1. Его иерархия типов захардкожена и не расширяется.


K>При переписывании это легко устранить, опираясь только на внутренние типы .NET; Касательно вообще типов, мы все знаем, что .NET "объектно натянут" по самые хэдеры, т.е. "язык под .НЕТ" уже должен быть ООП, с классами и методами.


Язык выполняющийся на донтнете вовсе не бязан быть ООП. Примером могут служить регулярные выражения.

Для поддержки ООП можно сделать библиотечное решение (что мы и сделали). Но при этом должна быть возможность вводить сущности присущие предметной области на которую нацелен язык. Например, в той же Найтре у нас есть символы и типы правил, типы АСТа и т.п. Оно в итоге переписывается в классы, но работать с ними нужно как правилами, АСТом и т.п. Иначе код становится слишком сложным.

В Немерле у тебя нет средств выразить твои сущности и ты вынужден самостоятельно писать АСТ и символы для своего языка. Хорошо если ты имеешь подготовку и сразу понимаешь, что это надо делать. Большинство же людей начинают решать проблему в лоб и упираются в то, что это очень сложно.

K>Это я к тому, что нет смысла закладываться на "язык черепашки с вкраплениями SQL", т.к. это ортогональное дотнету решение.


Ну, вот Linq встроили в C#. Он к ООП никаким боком. Скорее это ФП. Мы без проблем можем оформить Linq в виде отдельного расширения. А это значит, что любой может создать подобное решение. При этом оно будет интегрировано в зык и IDE не хуже чем "родное".

K>А раз мы в рамках ООП, то и "конструктор языков" сразу можно упростить до понятия "у нас есть классы и их члены" — далее можно плясать от этой модели.


Дело в том, что мы то ведь пробовали делать свои языки. Потому и пришли к Нитре.

hi_octane очень правильно сказал
Автор: hi_octane
Дата: 06.12.15
про выпрямление косяов и убирание хардкода. Мы сняли ограничения на расширение грамматики и семантики. Нужный тебе язык становится родным. И совершенно все равно является ли он простеньким встроенным в другой язык ДСЛ-ем, или отдельным полнофункциональным языком. Мы потому и работали так долго над Найтрой, что это не тривиальное решение.

VD>>2. Сам язык типизируется горой кода в которой не могут разобраться даже авторы.


K>Очевидно, что студенческий код рано или поздно пришлось бы выкинуть, но для этого вы и нужны — люди, которые знают старое и видят, как правильно создавать новое!


Гы. Эти студенты дадут фору большинству профессионалов из МС и Гугля. Они конечно гнали вперед срезая угля, но очевидно, что проблемы не только в их косяках. Проблемы в самом подходе. В современном языке программирования (воде Немерла, C# или даже VB) области видимости переплетены хитрейшим образом. Такие языки невозможно типизировать в один проход. Явное описание зависимостей выливается в гору кода и, как следствие, к необходимости его поддерживать в дальнейшем.

Чтобы написать и поддерживать Немерл нужно не 2.5 человека, как есть у нас, а человек 20 профессионалов на полной зарплате. Таких ресурсов нам никто не даст. По сему мы пишем средство которое сокращает сложность задачи во много раз. Поддерживать это средство и реализацию на нем таки проще, чем реализацию без него.

K>эээ.... даже не понял, про что это. Думаю, Туьукду(Nemerle ) не первый компилятор, построенный без них — другие же как-то справляются?


Справляются. Одни городят архитектуры и нанимают кучу программистов. Другие довольствуются компилятором командной строки, а каждое его зименение выливается в попоболь.

Так для справки, в Решарпере гигабайты кода.

K>Опять же, кто сказал, что нужна именно VS? Сред для расширения навалом, можно и своё написать.


Начинать лучше с ОС. Это более традиционный для России подход.

K>Но я в целом что хотел сказать: пилить "конструктор" и пилить "расширяемый язык" — две задачи, отличающиеся на порядок (понятно, последняя проще).


Да не особо.

Опять же для справки. Немерл пилили 10 лет в общей сложности более 20 программистов. Правда, по очереди. Одновременно до 4 программистов трудилось. Мы над найтрой работаем 3 года. Еще пол года нужно на язык уровня немерла.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.