Re[12]: Опциональные типы
От: WolfHound  
Дата: 23.02.17 13:53
Оценка: +1 -1
Здравствуйте, vdimas, Вы писали:

WH>>>>Покрой шаблонами целое неограниченного размера.

V>>>Ну вот я со звуком много работал. Там идёт работа с пачками отсчетов вполне конечного размера.
WH>>Как эти предложения вообще связаны?

V>Очевидно так, что для некоторых сценариев трюка эмуляции ЗТ достаточно.

V>В упомянутых звуковой предметной области пачки отсчетов не просто конечного размера, а строго по некоей сетке:
V>40 байт, 80, 120, 160, 240, 320.
1)Это не имеет никакого отношения к зависимым типам.
Просто по определению зависимых типов.
2)Ты говоришь про конечный (и очень маленький) набор вариантов, а я говорю про БЕСКОНЕЧНЫЙ.

V>Не хами, парниша.

V>Ты на удивление несообразителен порой или невнимателен — на выбор. И это раздражает, ты даже не представляешь как.
V>Общаешься с коллегами забыв проснуться.
Даже определение зависимых типов запомнить не в состоянии.
Да даже несоизмеримо более простой альфабленд пикселей с альфаканалом для тебя запредельно сложен.
Да ещё трепло, ибо генератор GLR парсеров который работает быстрее лексера ты так и не показал.
Что и не удивительно. Ибо если бы такие существовали, то я бы GLR и использовал. Но в реальной реальности, а не твоём воображении у GLR огромная константа, которая тормозит даже когда GLR не улетает в O(N^3). Это подтверждают ВСЕ работы по GLR которые я видел.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Отредактировано 25.02.2017 22:59 VladD2 . Предыдущая версия .
Re[13]: Опциональные типы
От: alex_public  
Дата: 23.02.17 14:06
Оценка: +1
Здравствуйте, WolfHound, Вы писали:

_>>Что-то не припомню языка с реальным (т.е. чтобы массив из 4-ёх штук занимал один байт) двухбитовым типом. Максимум что вспоминается, это битовые поля C++, но они опять же не позволяют задавать массивов. Снова фантазируешь? )

WH>Я даже в С++ могу сделать шаблон который будет это делать.

ОК, давай продемонстрируй мне двухбитовый тип на C++, который можно засунуть в массив (не важно какой, хоть обычный, хоть vector<X>).

WH>А уж сделать компилятор, который такое может вообще не проблема.


Компилятор можно, да) Но в существующих языках я подобного не припомню. )

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

WH>Структура массивов предпочтительна практически всегда.
WH>Они только могут сравнится по производительности, когда в цикле используют все поля.

На самом деле не всё так однозначно — всё зависит от конкретных размеров структур (т.к. кэш линия обычно занимает 64 байта). Но в любом случае я не очень пойму почему ты делаешь вид, что пытаешься меня тут в чём-то убедить. Я вообще то говорил лишь об неэффективности ссылочных данных и ты по сути подтвердил эти мои слова занимаясь сравнением исключительно двух вариантов решений с нессылочными данными. )))

WH>>>Тут у нас есть два крайних случая.

WH>>>1)Везде Some(что-то)
WH>>>2)Везде None
WH>>>В первом случае мы прочитаем в 33 раза больше памяти чем во втором.
WH>>>А если без разбиения на массивы, то в 64 раза больше. Причём всегда.
_>>Не верно, будет 64 и 32 раза, но это не суть, просто мелкое замечание. )
WH>Не можешь память посчитать, а лезешь рассказывать про низкоуровневые оптимизации.

Т.е. считаешь, что количество запрошенной памяти для прохода по массиву optional не зависит от того есть там данные или нет? ) Их твоих цифр получается именно такая позиция. )))

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

_>>И какое отношение данный код (кстати вполне реальный и эффективный) имеет даже уже не к нашей дискуссии о неэффективности ссылочных данных,

WH>Наипрямейшие. Если уж мы начинаем корёжить структуры данных для того чтобы процессор работал лучше нужно идти до конца и переходить к структуре массивов.

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

_>>Если мы уходим от использование optional (причём не в сторону ссылочных данных, а наоборот на ещё более низкий уровень битовых полей и т.п.), то возникают уже совершенно другие расклады по производительности (причём это применимо и к варианту без разбиения на массивы — там же тоже можно сделать более интересный код без optional).

WH>Не уходим. Этот код может сделать компилятор из такого:
WH>
WH>soa<option<int32>> values[1024*1024];
WH>foreach (Some(value) in values)
WH>{
WH>    //делаем что-то с value
WH>}
WH>


Компилятор какого языка? )

WH>Совсем фантазии никакой. Всё разжёвывать нужно.


Да, я уже давно заметил что у тебя великолепная фантазия. Много разных идей о том, что можно сделать в идеале. Но при этом к сожалению пока что не видел ни единой реализации этих идей. )
Re[14]: Опциональные типы
От: WolfHound  
Дата: 23.02.17 15:12
Оценка:
Здравствуйте, alex_public, Вы писали:

_>ОК, давай продемонстрируй мне двухбитовый тип на C++, который можно засунуть в массив (не важно какой, хоть обычный, хоть vector<X>).

Ох. Делаем
tempalte<int bits>
class Integer
{
...
};

Далее пишем частичную специализацию std::vector для него.
И всё. Для bool такая специализация уже есть.

WH>>А уж сделать компилятор, который такое может вообще не проблема.

_>Компилятор можно, да) Но в существующих языках я подобного не припомню. )
Я точно такое видел. Но не помню где.

_>На самом деле не всё так однозначно — всё зависит от конкретных размеров структур (т.к. кэш линия обычно занимает 64 байта).

А это не важно. Размер структуры (вместе с выравниванием) которую я показал 32 байта.
Если мы проходим по одному 32х битному полю, то трафик памяти будет в 8 раз больше для любой кэш линии размером 32 байта или больше.

_>Но в любом случае я не очень пойму почему ты делаешь вид, что пытаешься меня тут в чём-то убедить. Я вообще то говорил лишь об неэффективности ссылочных данных и ты по сути подтвердил эти мои слова занимаясь сравнением исключительно двух вариантов решений с нессылочными данными. )))

1)В .НЕТ можно делать массив структур. И я что-то не припомню случаи, когда мне была бы нужна ссылочная семантика и массив структур одновременно. Так что решение в .НЕТ вполне рабочее.
2)Если тебя так заботит производительность, то не останавливайся на полумерах.

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

Я считаю что:
1)Если везде Some(что-то), то мы прочитаем 4М + 128К памяти.
2)Если везде None, то мы прочитаем 128К памяти.
3)Если мы засуним Option<int32> в один массив, то мы прочитаем 8М памяти.
(4М + 128К) / 128К = 33
8М / 128К = 64
Так тебе понятнее?

_>Да, и кстати в реальности это естественно никак не повлияет на быстродействие, т.к. после запроса флага из optional значение уже давно будет лежать в кэше. Но это не отменяет того факта, что озвученная тобой цифра была не верна.

В реальности это всё очень сильно влияет на быстродействие.
Ибо если мы читаем только флаги, то на подкачку памяти (64 байта по 100 тактов на линию кэша) мы потратим 204'800 тактов. На чтение и того и другого 6'758'400 тактов. А на чтение варианта с одним массивом 13'107'200 тактов.

_>Компилятор какого языка? )

Например этого
https://www.youtube.com/watch?v=ZHqFrNyLlpA
Там только для структур. Но нет ни каких проблем сделать тоже самое для алгебраических типов данных.

_>Да, я уже давно заметил что у тебя великолепная фантазия. Много разных идей о том, что можно сделать в идеале. Но при этом к сожалению пока что не видел ни единой реализации этих идей. )

У умных людей идей всегда больше чем времени на реализацию.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[13]: Опциональные типы
От: vdimas Россия  
Дата: 23.02.17 15:35
Оценка: :)
Здравствуйте, WolfHound, Вы писали:

V>>Очевидно так, что для некоторых сценариев трюка эмуляции ЗТ достаточно.

V>>В упомянутых звуковой предметной области пачки отсчетов не просто конечного размера, а строго по некоей сетке:
V>>40 байт, 80, 120, 160, 240, 320.
WH>1)Это не имеет никакого отношения к зависимым типам.
WH>Просто по определению зависимых типов.

Что "это"?
Можно прервать поток сознания и формулировать по-русски?


WH>2)Ты говоришь про конечный (и очень маленький) набор вариантов, а я говорю про БЕСКОНЕЧНЫЙ.


Мама мия...
Зависимые типы могут работать даже над bool, где всего два значения.

В общем, если ты считаешь, что определение "зависимые типы" относятся только к неким мифическим "бесконечным" мн-вам допустимых значений типов, то ты НЕ понимаешь, что такое зависимые типы. Или неверно себе представляешь эту технологию.
Иди почитай Пирса или HoTT.


V>>Общаешься с коллегами забыв проснуться.

WH>Отсутствие головного мозга демонстрируешь тут исключительно ты.
WH>Даже определение зависимых типов запомнить не в состоянии.

Да, да. Ты только что "блеснул" в очередной раз.
Опять прёт вот эта твоя поверхностность...

Вот это в тебе всегда раздражало, что сосредоточившись — ты что-то можешь. ))
Но в 99% случаев ты рассеян, увы.


WH>Да даже несоизмеримо более простой альфабленд пикселей с альфаканалом для тебя запредельно сложен.


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

Собсно, эти замашки необъяснимы.

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

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


WH>Да ещё трепло, ибо генератор GLR парсеров который работает быстрее лексера ты так и не показал.


ЧТД. Трепло тут ты. Говорилось, дословно:

со сравнимой с лексером скоростью на большинстве цепочек.

И никто тебе не обещал полноценный генератор парсеров.
Наоборот, я ПРЕДЛАГАЛ тебе, коль уже ты делаешь "универсальный генератор" обратить внимание на GLR — отсюда мы и зацепились, Остапа опять понесло. ))

А так-то у меня есть настраиваемый парсер, используется уже давно.
Парсер настраивается по специфическим схемам док-в EDI.
Тело парсера писано ручками. Таблица автомата генерится в рантайм по поданной схеме.
Работает в одном из нагруженных серваков сертификации EDI-документов.


WH>Ибо если бы такие существовали, то я бы GLR и использовал.


Ага, ветер дует от того, что деревья качаются.

Подсказка №1: GRL/LALR существуют во всех компиляторах языков, где требуется перемалывать БОЛЬШИЕ объемы исходников.
Подсказка №2: дотнет и немерле — это НЕБОЛЬШИЕ объемы исходников, скорее микроскопические.

В общем, ты обитаешь в мире небольшой нагрузки на парсеры и отсюда у тебя искажённые представления обо всём.

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

Помню как меня тогда даже забанили, когда я увидел, что ты не понимаешь, что лексический анализатор по леволинейной регулярной грамматике — это тот самый восходящий LR-разбор, хотя мы обсуждали нисходящий ваш ПЕГ тогда. Я аж обалдел от такой полнейшей безграмотности в сочетании со столь суровой присущей тебе безапеляционностью. Ох как одно оттеняет другое, ты бы только знал. ))

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


WH>Но в реальной реальности, а не твоём воображении у GLR огромная константа


Нет никакой константы. Ты знаешь как работает табличный лексер? Прочитал символ, перешел по таблице. Вот точно так же.
"Константа" там может быть только от кривых рук, но в таких руках в точности аналогичная константа будет и у табличного лексера. Итого, исходное моё утверждение останется в силе. ))

Или можно вместо таблицы реализовать на goto, но здесь требуется более сложный генератор, чем построитель таблицы переходов.


WH>которая тормозит даже когда GLR не улетает в O(N^3). Это подтверждают ВСЕ работы по GLR которые я видел.


При том, что программист с твоим опытом мог бы потратить пару дней и проверить самому, не?
Тем более, что я давал конкретные координаты сценариев, когда GLR рвет всех и вся как тузик грелку:

входные цепочки большой длины, но низкой "глубины" вложенности.

Любой алгоритм с откатами/мемоизациями просто не работает на таких данных.
Вернее, работает, но это ж-па полная.

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

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

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

А "совсем длинными" бывали цепочки, на которых шло по 2 от силы ветки разбора. И всего лишь однажды наблюдалось устойчивых 3 ветки на примерно 20-25% общей длины цепочки. В этом смысле современные языки программирования намного более однозначны, в сравнении со схемами док-в из области EDI.

А что касается константности — то это вопрос управления ресурсами. В GLR необходимо уметь оперативно порождать конкурирующие ветки разбора корнем от текущей и так же оперативно убивать отмершие, т.е. текущей может стать одна из новых конкурирующих.

Тут даже представление нетерминалов, получаемых от лексера, и то важно. ))
Я только на этом представлении умудрился скорость чисто парсинга поднять примерно вдвое. Т.е., включение парсера сверху лексера давало, скажем +20% ко времени работы "чистого лексера" (без парсера), а после вылизывания представления нетерминалов — всего 10% от чистого лексера. (Т.е. подключили к лексеру полноценный парсер, скорость потребления потока упала на 20% и 10% соответственно).

Т.е. эта константа не теоретическая ни разу, а зависит сугубо от реализации.
И так по каждому моменту этой "константы" — оно допиливается почти до скорости работы чистого лексера.

Далее.
Так же утверждалось, что он есть ВСЕ контекстно-свободные грамматики.
Т.е. пусть у нас даже будет сильно неоднозначная грамматика, данная сверху.
Однозначно её распарсить можно лишь GLR (или любым другим параллельным алгоритмом, не боящимся рекурсий, типа Эрли).

Т.е. вот тебе еще один сценарий, где GLR мог бы помочь.

К тому же, GLR — это алгоритм разбора, а не способ описания грамматики.
Re[14]: Опциональные типы
От: WolfHound  
Дата: 23.02.17 16:01
Оценка: +1
Здравствуйте, vdimas, Вы писали:

V>В общем, если ты считаешь, что определение "зависимые типы" относятся только к неким мифическим "бесконечным" мн-вам допустимых значений типов, то ты НЕ понимаешь, что такое зависимые типы. Или неверно себе представляешь эту технологию.

Я говорю, что они могут работать в том числе с бесконечными множествами.
А то что делаешь ты может работать только с конечными и на практике только с очень маленькими.

V>Иди почитай Пирса или HoTT.

Вот иди и почитай. Ибо ты как всегда ничего не понял.
Зависимый тип — это когда в типе есть ссылка на значение времени исполнения.
Всё остальное зависимым типом не является. Просто по определению.

V>Да, да. Ты только что "блеснул" в очередной раз.

Блещешь тут только ты.

V>Опять прёт вот эта твоя поверхностность...

Кто бы говорил.

V>Твой пример с альфаблендом был высмеян не за ошибочность, а за элементарщину, не соответствующую тому, как ты с этой элементарщиной носился, как с писанной торбой.

1)Я с ним не носился.
2)Ты так и не понял, что там происходит.

V>Не видишь себя со стороны. Не выдержан. Нелеп. Разговариваешь с голосами в голове, а не с реальными оппонентами. Т.е. склонен к нечистоплотности в спорах, активно приписывая оппонентам "удобную для разбивания" точку зрения. Не в состоянии принять аргументы оппонента как они есть без того, чтобы не "допилить" их до удобного для "опровержения" варианта. Слабак, кароч.

Это ты сейчас себя описал.

V>ЧТД. Трепло тут ты. Говорилось, дословно:

V>

V>со сравнимой с лексером скоростью на большинстве цепочек.

V>И никто тебе не обещал полноценный генератор парсеров.
V>Наоборот, я ПРЕДЛАГАЛ тебе, коль уже ты делаешь "универсальный генератор" обратить внимание на GLR — отсюда мы и зацепились, Остапа опять понесло. ))
Что и требовалось доказать. Инструмента у тебя нет и не было.

V>Нет никакой константы. Ты знаешь, как работает табличный лексер?

Я не просто знаю. Я его написал.

V>Прочитал символ, перешел по таблице. Вот точно так же.

Какое отношение строго линейный лексер имеет к O(N^3) GLR парсеру?
Да никакого. Ты увидел слово автомат и тебя понесло.

V>Или можно вместо таблицы реализовать на goto, но здесь требуется более сложный генератор, чем построитель таблицы переходов.

И такой я тоже написал.

WH>>которая тормозит даже когда GLR не улетает в O(N^3). Это подтверждают ВСЕ работы по GLR которые я видел.

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

V>Однозначно её распарсить можно лишь GLR (или любым другим параллельным алгоритмом, не боящимся рекурсий, типа Эрли).

Ты не поверишь... но мой алгоритм умеет переключаться в Эрли, когда по-другому не получается.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[7]: Опциональные типы
От: meadow_meal  
Дата: 23.02.17 20:01
Оценка: 16 (1) +2 -1 :)
Здравствуйте, vdimas, Вы писали:

Отвечу только по ключевым пунктам.

По поводу вложенного Optional мне добавить нечего.

По поводу бинарной сериализации. Я не понимаю, зачем ты в разговоре постоянно скачешь с системы типов IDL на бинарную сериализацию и обратно. Они связаны конечно, но далеко не так прямо, как ты это хочешь представить. Битовое кодирование опциональных полей — это всего лишь деталь реализации, оптимизация, и никакого отношения к исходному вопросу не имеет.

Ну и отвечу на наезды по поводу IDL. Так как это оффтопик, то под кат.

  Скрытый текст
Прежде всего, в 2017 году странно считать, что разработка DSL и IDL вообще это rocket science.

Зачем нужен IDL? Ты все сводишь к протоколам коммуникации, это лишь часть айсберга. Мы занимаемся играми средних размеров (цикл разработки один-три года до релиза, и затем поддержка). Играм нужен инструментарий — дизайнерам, локализаторам, создателям контента, аналитикам, коммьюнити-менеджерам, администраторам. Писать их под каждый проект — неокупаемо. Для AAA-игр — возможно да, для нас — нет. Нужен проектно-независимый инструментарий. Кому-то нужен код, сгенерированный из IDL, кому-то схема, подтягиваемая на лету. Без единой модели данных, описанной в IDL, все развалится, потеряет актуальность.

Важная часть моей работы — оптимизация workflow. Когда к нам приходят новые сотрудники, я спрашиваю их, как они работали раньше. Вот на примере дизайнеров. "Мы редактировали XML и коммитили в гит" — это самый печальный ответ, но он же — самый частый. Основные затыки дизайнерского worlflow — это отстойные инструменты (само собой), это система контроля версий (как только вы смешали работу дизайнера с работой программиста в одном репозитории — вы замедлили и их, и себя), это устаревание инструментария (когда протокол изменился, и дизайнер отдыхает, обновляясь или ожидая обновления), это необходимость общения между дизайнером и программистом, это цикл "попробовал — увидел результат", и это плохая обратная связь в случае ошибок. У нас ничего этого нет. Они работают в своем инструментарии, их схема всегда актуальна, валидация всегда качественна, и все их изменения применяются на живом сервере для всех текущих клиентов по нажатию кнопки "сохранить". А ведь в этом нет ничего особенного, это всего лишь результат использования IDL.

Разработка начинается с IDL и завязана на IDL. Он должен быть удобным, и кодогенерация должна быть гибкой. ASN.1? Нет. Он хорошо подходит для описания стандартов сетевых протоколов, но это же совсем другая задача.

Какие есть альтернативы? Из самого известного — Google protobuf, Apache Thrift, с недавних времен — Microsoft Bond. Мы начали с protobuf. Это было лет десять назад, все могло измениться. Но тогда генерируемый код был ужасен. Система типов — бедновата, даже map/dict не было. Плюс он заточен на версионность, что дает значительный оверхед по размеру пакетов — так как даже для required пакетов записывается числовой тэг. Генерации в JSON — не было. Расширение кодогенератора — адские муки. На одном проекте промучались, другой начали с создания своего IDL. Реализация прототипа на Nemerle заняла две недели. Человекогоды разработки? Видимо ты перепутал с годами использования. Да, IDL развивался, но благодаря использованию Nemerle (а потом Nitra) — с минимальными трудозатратами. Правильные инструменты всегда решают.


V>Самая главная у тебя проблема — это много недоговариваний, преувеличений и откровенного вранья в итоге.

А у тебя — это хамство. Я открыт критике, но ты уж слишком много на себя берешь. Увольнения, обманутые инвесторы, вранье — ну не на базаре же.
Re[14]: Опциональные типы
От: fddima  
Дата: 23.02.17 20:44
Оценка: +1
Здравствуйте, vdimas, Вы писали:

V>Подсказка №1: GRL/LALR существуют во всех компиляторах языков, где требуется перемалывать БОЛЬШИЕ объемы

Если ты тонко намекаешь на C++ — то мэйнстрим gcc/clang — это рукописные recursive-descent. Предполагаю что c# рослин тоже. Как минимум он хэндрайтен с минимумом генерации кое-кого кода, но там плясок больше вокруг как это уе заставить быстро работать вообще, а не вокруг алгоритма как такового. Их решение между прочим весьма ничего. Только GLR нафиг никому не впился:
— сложно восстанавливаться после ошибок;
— сложно сообразить вменяемый еррор репортинг;
— сложно саппортить.
Любой табличный метод который невозможно нормально отдебажить — в длинной перспективе обречены на провал — никто просто не хочет с этим возиться.
Именно поэтому ни один нормальный фронтэнд не использует *L*. При этом местами могут применяться всякие выверты и оптимизации основанные на автоматах.
Мне тут сказать вам только обоим — фейспалм. Нитра — хороша — но это не парсер. Это язык сам в себе. Спасибо, но это не то что нужно. (Хотя мне очень нравится инструмент). Проблема тока что авторы почему-то решили что бутстрап нужен только им — поэтому и имеют что имеют.
Насчет ваших споров с WH — это вообще ниочем. Господин WH выложит нормальный пейпер в пдф с выкладками — тогда и будет о чем говорить вообще. А так — видно что он в курсе — и все. Проблема что другие не в курсах.
Для ANTLR4 с их ALL(*) выкладка в пдф вот есть.
А так — хваставство у обоих. Правда у WH — есть на что ссылаться. У тебя нет. Впрочем мне пофигу — я не рефери а тема интересна.
Re[15]: Опциональные типы
От: WolfHound  
Дата: 23.02.17 21:30
Оценка:
Здравствуйте, fddima, Вы писали:

F>Только GLR нафиг никому не впился:

F> — сложно восстанавливаться после ошибок;
Тут трудно сказать какой вариант сложнее. У нисходящих и восходящих прасеров разные заморочки.
Но учитывая то что полно нисходящих парсеров которые хорошо восстанавливаются и не видно восходящих то видимо это жжжжж не с проста.

Основная причина почему я не использую восходящий парсер это то что не ясно как в его случае менять грамматику на лету. В случае с нисходящим парсером там всё тривиально.
Также у меня есть желание добавить в парсер нитры некоторые контекстно-зависимые возможности. Как засунуть их в нисходящий парсер в принципе ясно. А вот как это сделать с восходящим совершенно не понятно.

F> — сложно сообразить вменяемый еррор репортинг;

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

F> — сложно саппортить.

Если написан на ДСЛ, то пофигу.

F> Мне тут сказать вам только обоим — фейспалм. Нитра — хороша — но это не парсер. Это язык сам в себе. Спасибо, но это не то что нужно. (Хотя мне очень нравится инструмент). Проблема тока что авторы почему-то решили что бутстрап нужен только им — поэтому и имеют что имеют.

А что тебе нужно? И что конкретно тебя не устраивает в нитре? Можешь сформулировать?

F> Насчет ваших споров с WH — это вообще ниочем. Господин WH выложит нормальный пейпер в пдф с выкладками — тогда и будет о чем говорить вообще. А так — видно что он в курсе — и все. Проблема что другие не в курсах.

F> Для ANTLR4 с их ALL(*) выкладка в пдф вот есть.
Разница в том, что автор ANTLR4 профессор. Ему нужны статьи, а мне от них ни жарко, ни холодно.

F> А так — хваставство у обоих. Правда у WH — есть на что ссылаться. У тебя нет. Впрочем мне пофигу — я не рефери а тема интересна.

С моей стороны хвастовства нет. Всё что я пытаюсь это получить информацию.
vdimas говорит, что у него есть супермегакрутой парсер который работает быстрее лексера. Вот я и хочу на него посмотреть. Вдруг действительно можно будет сильно разогнать нитру.
Но похоже ничего кроме трёпа от него так и не будет. Видимо показывать просто нечего.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[16]: Опциональные типы
От: fddima  
Дата: 24.02.17 01:41
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Тут трудно сказать какой вариант сложнее. У нисходящих и восходящих прасеров разные заморочки.

WH>Но учитывая то что полно нисходящих парсеров которые хорошо восстанавливаются и не видно восходящих то видимо это жжжжж не с проста.
Ты не внимательно прочитал. В прамках того что пишет vdimas — а именно мегабайты парсинга — т.е. читай C++ — никто GLR не применяет. Это не значит что он неприпеним. Ноборот, в GLR говорят совремегный C++ разбирать легче. Но по голому факту: мэйнстрим фронты используют ужаснейший recursice descent.
Я без бюсысли на уого-то из вас наезжать — и твк ясно спор — давний и я тут — лишний. Я просто дал уточнение — что фронты совоеменных языков нмкогда не используют LR. Но фронты развивающихся — юзают. Потом тх пернрисыют на рукописные recursive descent. Блин! Да даже никому неизвестный loci постигла эта же участь.

F>> — сложно сообразить вменяемый еррор репортинг;

WH>А вот тут пофигу.
WH>Парсер нитры не генерирует сообщения об ошибках.
Ты забываешь, что не нитрой единой.

WH>Их собирают отдельным проходом по восстановленному АСТ. Это очень быстро, ибо посещаются только те места где есть ошибки.

Вопрос ровно в одном — дать коду стэк разбора. Если их предложить штук 100 — то ясен фиг будет порногоафия. Прошу учесть, что это не про нитру.

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

Т.е. ты считаешь что нисходящие (аля top-dow и recirsive-descent но тут я вообще подход имею ввилу — т.е более общем смысле) лучше?

WH>И я не готов тратить на эти исследования несколько лет.

F>> — сложно саппортить.
WH>Если написан на ДСЛ, то пофигу.
Даже если написал dsl — то нн пофигу.
Но у меня вообще речь была о хэндрайтен. видишь ли — люди не идиоты — они выбираюи самые трудоемкие способы но которые стабильные через десятилетия.
Однако, и у тебя и у меня возникает вопрос — неужели нельзя бы было сгенерить? Я уверен что можно. Вопрос чем — нитрой? А зачем? (нитрачисто бля примера, но я ещё раз повторю — на практике "до зачем" — другие нитровые вопросы стоят). не показатель, увы.

Насчет бутстрапа — мне кажется что любой вменяемый ЯП захочется бутстрапиться. С нитрой *пока* что это не выглядит возможным.

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

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

Так и с нитрой — инструмент на сегодняшнмй — аховый. Я уже спрашивал... Влад очень подробно объяснил. Но, на сейчас: по факту — или ты живешь с рантаймом да ещё под дот нетом или бери любой другой инструмент (удовлетворяющий задаче).

Ты пойми правильно — мои выпады о стратегии развития и они реальны. Даже если счтаешь что не так — то... да хер что ты изменишь. Огранияения вашей платфоры ж и так понятны. Но я и говорю.- что как же ж так. Какого хера что- бы это спортировать — нужно спортировать целый немерл?
Правильно или нет — это судить не мне.

F>> Для ANTLR4 с их ALL(*) выкладка в пдф вот есть.

WH>Разница в том, что автор ANTLR4 профессор. Ему нужны статьи, а мне от них ни жарко, ни холодно.
Но ими можно доказать людям что впша придумка не фикция. Это раз. Во-вторых — профессору пришлось потратить 20 лет на эту статью. WH — ты вот недавно предложил человпку парсер в другом форуме — всё супер. Но... если бы ты дал ссылки на внешние ичточникм — было бы хорошо. Но ещё лучше — если бы ты описал все свои чаяния и/или нитра алгорттм в любой доступной тебе форме.Если профессор сука потратил 20 лет на сраный кеш правил и назвал это ALL — неужели ты не можешь что-то подобное совеошить? Тем более кау я слышал нитра там ошибки генерирует красивые.
Если не ново — тогда простите. Выдаваьось за ноухау. Я сбил спесь наполовину. Та блин. я лично сбил спесь от немерле.пег на 90% и то — то что — было — это круто.

Имхо просто не все могут задачу осознать. Но короче — мое сугубое имхо — или ЯП с помощью нитры смогут сами себя компилировать (без ВМ разумееися). Либо...
Re[17]: Опциональные типы
От: WolfHound  
Дата: 24.02.17 03:03
Оценка:
Здравствуйте, fddima, Вы писали:

F>Ноборот, в GLR говорят совремегный C++ разбирать легче. Но по голому факту: мэйнстрим фронты используют ужаснейший recursice descent.

GLR, GLL, Earley или любым другим алгоритмом, умеющим парсить все контекстно-свободные грамматики разбирать естественно проще чем неким огрызком, которому то одно правило не нравится то другое.

F> Я без бюсысли на уого-то из вас наезжать — и твк ясно спор — давний и я тут — лишний. Я просто дал уточнение — что фронты совоеменных языков нмкогда не используют LR. Но фронты развивающихся — юзают.

Просто быстрое начало. В начале разработки нитры тоже в качестве парсера использовался ужос. Но когда нитра заработала ужос выкинули и заменили на нитру.

F>Потом тх пернрисыют на рукописные recursive descent. Блин! Да даже никому неизвестный loci постигла эта же участь.

Вот я и говорю, что это жжжжжжж не с проста.

F>>> — сложно сообразить вменяемый еррор репортинг;

WH>>А вот тут пофигу.
WH>>Парсер нитры не генерирует сообщения об ошибках.
F> Ты забываешь, что не нитрой единой.
Я ничего не забываю. Просто говорю, что парсеру не обязательно генерировать сообщения об ошибках.
Их можно сгенерировать по полученному АСТ.
Так получается проще и качественней.

И эту технологию можно применить к любому парсеру.

F> Вопрос ровно в одном — дать коду стэк разбора. Если их предложить штук 100 — то ясен фиг будет порногоафия. Прошу учесть, что это не про нитру.

В общем случае там не стек, а DAG стеков. И я не только про нитру говорю.
А вообще про все парсеры которые могут возвращать лес деревьев.

F> Т.е. ты считаешь что нисходящие (аля top-dow и recirsive-descent но тут я вообще подход имею ввилу — т.е более общем смысле) лучше?

У меня нет полной уверенности. Но жжжжжж которое доносится из всех промышленных решений говорит, что с восходящими явно что-то не то.
Может просто очень сложно. А может есть фундаментальные проблемы. Я не знаю. И исследовать этот вопрос не хочу.

F> Однако, и у тебя и у меня возникает вопрос — неужели нельзя бы было сгенерить?

Нельзя. До сих пор все генераторы парсеров создавались для того чтобы статью в журнал написать. И к реальной работе пригодны небыли.
По крайней мере я до сих пор не слышал ни об оlном генераторе парсеров который создавался бы как инструмент для создания промышленных решений не уступающих рукописным парсерам.

F> Насчет бутстрапа — мне кажется что любой вменяемый ЯП захочется бутстрапиться. С нитрой *пока* что это не выглядит возможным.

1)Не любой. Например, как ты будешь SQL бутстрапить? Да и зачем?
2)Нитра уже частично бутстапится.

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

SQL очень полезный язык. И он далеко не единственный полезный язык, который не может бутстрапиться.

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

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

F> Так и с нитрой — инструмент на сегодняшнмй — аховый. Я уже спрашивал... Влад очень подробно объяснил. Но, на сейчас: по факту — или ты живешь с рантаймом да ещё под дот нетом или бери любой другой инструмент (удовлетворяющий задаче).

В чём проблема компилятору языка быть написанным на .НЕТ?
.НЕТ в нужном объёме сейчас есть везде. И на машину разработчика поставить его не проблема.
А сгенерированный код может быть любым. И о .НЕТ даже не догадываться. Таким образом в продакшене .НЕТ не нужен.

F> Ты пойми правильно — мои выпады о стратегии развития и они реальны.

Я просто так и не понял, что у тебя за выпады.

WH>>Разница в том, что автор ANTLR4 профессор. Ему нужны статьи, а мне от них ни жарко, ни холодно.

F> Но ими можно доказать людям что впша придумка не фикция.
Нельзя.

F>Это раз. Во-вторых — профессору пришлось потратить 20 лет на эту статью. WH — ты вот недавно предложил человпку парсер в другом форуме — всё супер. Но... если бы ты дал ссылки на внешние ичточникм — было бы хорошо. Но ещё лучше — если бы ты описал все свои чаяния и/или нитра алгорттм в любой доступной тебе форме.Если профессор сука потратил 20 лет на сраный кеш правил и назвал это ALL — неужели ты не можешь что-то подобное совеошить?

Алгоритм нитры это промышленное, а не академическое решение. И как следствие это не красивый алгоритм, а жуткий монстр. Примерно, как IntroSort (сборная солянка из нескольких сортировок) только намного сложнее.
Я устану его описывать.
Тем более что у меня есть желание неслабо его переделать.
Нужно только с духом собраться.

F>Тем более кау я слышал нитра там ошибки генерирует красивые.

Ошибки Влад генерирует по АСТ которое создаёт мой парсер.
https://github.com/rsdn/nitra/blob/master/Nitra/Nitra.Runtime/Errors/ErrorCollectorWalker.n
Подобный алгоритм можно применить и к другим парсерам.
Главное, чтобы при обходе АСТ можно было понять, что ветка сломана и можно было получить метаинформацию для этого правила.

F> Если не ново — тогда простите. Выдаваьось за ноухау. Я сбил спесь наполовину. Та блин. я лично сбил спесь от немерле.пег на 90% и то — то что — было — это круто.

Я вообще не понял, что тут написано.

F> Имхо просто не все могут задачу осознать. Но короче — мое сугубое имхо — или ЯП с помощью нитры смогут сами себя компилировать (без ВМ разумееися). Либо...

Как я уже сказал это крайне неправильное мнение.
Так делать не нужно не по тому что у нитры на данном этапе есть технические проблемы, которые будут со временем решены, а по тому что это просто неправильно.
Ибо такой подход ведёт к огромному перерасходу ресурсов и значительному ухудшению качества конечного продукта.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[15]: Опциональные типы
От: alex_public  
Дата: 24.02.17 13:39
Оценка:
Здравствуйте, WolfHound, Вы писали:

_>>ОК, давай продемонстрируй мне двухбитовый тип на C++, который можно засунуть в массив (не важно какой, хоть обычный, хоть vector<X>).

WH>Ох. Делаем
WH>
WH>tempalte<int bits>
WH>class Integer
WH>{
WH>...
WH>};
WH>

WH>Далее пишем частичную специализацию std::vector для него.
WH>И всё. Для bool такая специализация уже есть.

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

_>>На самом деле не всё так однозначно — всё зависит от конкретных размеров структур (т.к. кэш линия обычно занимает 64 байта).

WH>А это не важно. Размер структуры (вместе с выравниванием) которую я показал 32 байта.
WH>Если мы проходим по одному 32х битному полю, то трафик памяти будет в 8 раз больше для любой кэш линии размером 32 байта или больше.

Не верно, сразу в трёх местах)

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

Кстати, отдельным пунктом во всём этом идёт возможность использования SIMD, так что в итоге всё существенно зависит от конкретного алгоритма в цикле. Но это уже немного другой вопрос — там где SIMD нормально применим, кэш обычно априори работает максимально эффективно. )))

_>>Но в любом случае я не очень пойму почему ты делаешь вид, что пытаешься меня тут в чём-то убедить. Я вообще то говорил лишь об неэффективности ссылочных данных и ты по сути подтвердил эти мои слова занимаясь сравнением исключительно двух вариантов решений с нессылочными данными. )))

WH>1)В .НЕТ можно делать массив структур. И я что-то не припомню случаи, когда мне была бы нужна ссылочная семантика и массив структур одновременно. Так что решение в .НЕТ вполне рабочее.

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

WH>2)Если тебя так заботит производительность, то не останавливайся на полумерах.


При условие сохранения удобства — само собой. Если же быстродействие будет требовать уменьшения удобства, то тут уже надо смотреть конкретную ситуацию — стоит ли оно того. )

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

WH>Я считаю что:
WH>1)Если везде Some(что-то), то мы прочитаем 4М + 128К памяти.
WH>2)Если везде None, то мы прочитаем 128К памяти.
WH>3)Если мы засуним Option<int32> в один массив, то мы прочитаем 8М памяти.
WH>(4М + 128К) / 128К = 33
WH>8М / 128К = 64
WH>Так тебе понятнее?

8М будет в случае Some optional. А в случае None optional будет 4M, т.к. мы будем запрашивать из памяти только флаги.

_>>Да, и кстати в реальности это естественно никак не повлияет на быстродействие, т.к. после запроса флага из optional значение уже давно будет лежать в кэше. Но это не отменяет того факта, что озвученная тобой цифра была не верна.

WH>В реальности это всё очень сильно влияет на быстродействие.
WH>Ибо если мы читаем только флаги, то на подкачку памяти (64 байта по 100 тактов на линию кэша) мы потратим 204'800 тактов. На чтение и того и другого 6'758'400 тактов. А на чтение варианта с одним массивом 13'107'200 тактов.

Ты как-то плохо читаешь сообщения своих собеседников. Я вроде как явно написал, что не будет особой разницы в быстродействие для optional в вариантах Some и None, а ты пишешь вообще про другое. )

_>>Компилятор какого языка? )

WH>Например этого
WH>https://www.youtube.com/watch?v=ZHqFrNyLlpA
WH>Там только для структур. Но нет ни каких проблем сделать тоже самое для алгебраических типов данных.

О, действительно любопытно. Спасибо за информацию, данный проектик как-то прошёл мимо меня (видимо потому что этот компилятор до сих пор нельзя пощупать руками). Кстати, на видео довольно проблематично найти нужное — лучше бы ты дал такую https://github.com/BSVino/JaiPrimer/blob/master/JaiPrimer.md ссылку. Но я не очень согласен с автором, что он опустился до уровня C в своей реализации (см. раздел Not Planned по моей ссылке). Я думаю, что всё же можно сохранить мощь современных языков, добавив к ним отдельно данную возможность. Причём возможно через МП (кстати, интересно хватило бы на это макросов Rust'а или Nemerle?)...

Да, и небольшое замечание по предыдущей дискуссии в контексте этой ссылки: обрати внимание, что все эти игроделы (и автор данного языка и остальные комментирующие) сразу ставят крест даже на самой идеи использования языка с GC в своей отрасли... )))
Re[16]: Опциональные типы
От: WolfHound  
Дата: 24.02.17 16:20
Оценка:
Здравствуйте, alex_public, Вы писали:

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

Я не вижу большой разницы.

_>Во-первых, размер твоей структурки будет 28 байт, а не 32 — разберись уже с тем, как работает выравнивание. )

В этом месте немного ошибся.

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

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

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

Очень часто память доминирует.

_>Жёсткая связь между типом данных и типом размещения данных в любом случае не рабочая.

На практике она достаточно хороша.

_>При условие сохранения удобства — само собой. Если же быстродействие будет требовать уменьшения удобства, то тут уже надо смотреть конкретную ситуацию — стоит ли оно того. )

Как я уже говорил всё это безобразие может делать компилятор.
Нужно его только этому научить.

_>8М будет в случае Some optional. А в случае None optional будет 4M, т.к. мы будем запрашивать из памяти только флаги.

Не правильно. Мы не можем запросить из памяти 4 байта. Только всю линейку кэша целиком.

_>О, действительно любопытно. Спасибо за информацию, данный проектик как-то прошёл мимо меня (видимо потому что этот компилятор до сих пор нельзя пощупать руками). Кстати, на видео довольно проблематично найти нужное — лучше бы ты дал такую https://github.com/BSVino/JaiPrimer/blob/master/JaiPrimer.md ссылку.

Когда я последний раз интересовался этим проектом были только видео.

_>Но я не очень согласен с автором, что он опустился до уровня C в своей реализации (см. раздел Not Planned по моей ссылке).

Я тоже с ним много в чём не согласен.
Данная фича единственная интересная идея в этом проекте.
А его подход к метапрограммированию просто ужасен.

_>Я думаю, что всё же можно сохранить мощь современных языков, добавив к ним отдельно данную возможность. Причём возможно через МП (кстати, интересно хватило бы на это макросов Rust'а или Nemerle?)...

Про руст не знаю. Слишком давно на него смотрел.
На немерле, если генерировать unsafe код, можно.

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

Это психологические проблемы.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[15]: Опциональные типы
От: vdimas Россия  
Дата: 24.02.17 18:12
Оценка: -1
Здравствуйте, fddima, Вы писали:

V>>Подсказка №1: GRL/LALR существуют во всех компиляторах языков, где требуется перемалывать БОЛЬШИЕ объемы

F> Если ты тонко намекаешь на C++ — то мэйнстрим gcc/clang — это рукописные recursive-descent.

Исторически GCC юзал LALR-парсер. Но LALR имеет известные проблемы (не буду тут расписывать, бо они на всех углах расписаны).
Поэтому часто используют LALR + некое ручное допиливание неоднозначных мест.

Более того, есть такой трюк — декомпозиция грамматик. Вот был пример ПЕГ — это и есть, собсно, принцип такой декомпозии.

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

Например, факт "захода" на объявления типов (классов/структур/перечислений/объединений) или на объявления функций/лямбд в С++ — это всё можно распознать простейшими (дебильными) средствами, писаными вручную, т.е. только лишь по ветвлению по нетерминалам, получаемым от лексера, из "текущего контекста". А ПЕГ всегда знает "текущий контекст", ес-но.

А вот это уже тело ф-ий удобней разбирать восходящими грамматиками — особенно что касается вложенных вызовов или математических выражений или совместной работе одного и другого. Что и происходит в реальности. Там тот же самый *LR. Потому что нисходящий разбор страдает склонностями к зацикливаниям на неоднозначных участках кода by design или к тяжеловесным откатам — и это тоже на всех углах обсосано, не буду повторяться.


F>Предполагаю что c# рослин тоже.


C# рассматривать нелепо:
— грамматика сильно однозначная;
— объем перемалываемых исходников смешон; для сравнения, в современной С++ программе из каждого CPP-фала может быть подключено до половины Буста (утрирую, но оно близко к такому положению дел).


F>Только GLR нафиг никому не впился:

F> — сложно восстанавливаться после ошибок;

Наоборот, если речь о неоднозначных участках кода.
При рекурсивном спуске проще генерить ошибку только о простых ситуациях, типа, тут идёт объявление класса, а после имени класса написано, скажем, const — и генерим ошибку "это не ожидается здесь". ))


F> — сложно сообразить вменяемый еррор репортинг;


Еще раз, медленно — ровно наоборот.

LR-разбор в состоянии подсказать множество верных ожидаемых символов. В реальности там выбор из 1-2-х вариантов максимум, потому что в С++ неоднозначность происходит в выборе м/у идентификатором типа или переменой, вот и вся неоднозначность, которой "болеет" С++.

Т.е. типа такого:
id1 id2(id3);

В этом месте id1 — всегда идентификатор типа, а вот чем является id2 зависит от id3.

Если id3 — это значение (переменная/константа/перечисление), то id2 — это идентификатор переменной, а всё выражение означает объявление переменной типа id1 и вызов соотв. конструктора этого типа. А если id3 — это имя типа, то всё выражение означает объявление сигнатуры некоей ф-ии id2.

С другой стороны, подобную неоднозначность НЕ обязательно сваливать на парсер и её не сваливают — для такой конструкции заводится отдельный "недоопределённый" нетерминал и его ресолвят до однозначного через таблицу идентификаторов ручками. Т.е. на скорости работы именно парсера по алгоритму *LR это не сказывается (если убрать ресолвинг). Это конкретные заморочки конкретно С++, которые верны для ЛЮБОГО алгоритма парсинга.


F> — сложно саппортить.


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

Тут принцип простой — если нужен наколенный вариант для экспериментов, то ОК, пусть будет рукопашный код c предпросмотром (обязательно с предпросмотром, увы).

Собсно, команда GCC пишет о своём переходе на рукописный вариант:

the main benefits are facilitating of future enhancements


Но пишет так же о рисках:

Code may be wrongly accepted which should be rejected, or wrongly rejected which should be accepted.

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

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

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

Вот у Вольфхаунда, в последний раз, когда я смотрел на генерируемый им код (давно это было) — шла техника на goto. Как сейчас — не знаю. Давно не интересовался, т.к. он не исполнил данное 8 лет назад обещание сделать генерацию парсера на произвольные технологии, в том числе нейтивные.
Это много и долго.
В итоге, он уже скоро 10 лет занимается этой темой, а полезность выхлопа (востребованность результата) приближается к 0-лю.
Поэтому, он там может надуваться сколько ему вздумается, но нужен пригодный для потребления результат.


F> Любой табличный метод который невозможно нормально отдебажить — в длинной перспективе обречены на провал — никто просто не хочет с этим возиться.


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


F>Именно поэтому ни один нормальный фронтэнд не использует *L*.


"ни один нормальный фронтэнд"

Как раз наоборот.
Все "нормальные фронтенды" (С) для С++ используют *LR парсеры от EDG:
— MSVC;
— Intel compiler;
— Comeau;

Плюс всевозможные встраиваемые диалекты С/С++, включая многочисленные диалекты шейдеров (С-подобные языки):
— Analog Devices;
— ARM;
— AT&T;
— Axivion;
— Fujitsu Siemens Computers;
— Hewlett-Packard;
— Parasoft;
— и т.д. до бесконечности.

Вот что такое на сегодня мейнстрим.
Остальное рядом с ними тормозит как программист после бессонной ночи. ))

А конкретно GCC — это бесконечное экспериментаторство и баги на багах. Блин, уже 2017-й год, а у них до сих пор работоспособность (т.е. семантика) программы зависит от ключей оптимизации. У меня не всегда на -O3 программы продолжают работать.
Это как вообще? ))


F>При этом местами могут применяться всякие выверты и оптимизации основанные на автоматах.


Не важно. Промышленного кач-ва у GCC нет.

Для критичных вещей с серьезной оптимизацией под линухами используют icc (Intel compiler), который имеет режим совместимости бинарного кода библиотек с GCC. Потому что, повторюсь, уровень оптимизации -O3 до сих пор является де-факто не работающим в GCC. А если мы компиляем в продакшн на GCC, то только на -O2, как и весь остальной мир, ес-но.


F> Мне тут сказать вам только обоим — фейспалм. Нитра — хороша — но это не парсер. Это язык сам в себе. Спасибо, но это не то что нужно. (Хотя мне очень нравится инструмент). Проблема тока что авторы почему-то решили что бутстрап нужен только им — поэтому и имеют что имеют.


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


F>А так — хваставство у обоих. Правда у WH — есть на что ссылаться.


Я только что сослался много на чего — на весь коммерческий мейнстрим, собсно. Т.е. на вообще весь.
Данную мою инфу ты можешь проверить прямо сейчас.


F>У тебя нет.


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

Кароч, это детсад, но.
Я могу интересующимся в личку выслать ключевые слова, по которым можно найти использование моей разработки. Работа была сделана на заказ когда-то и под NDA, в сфере EDI с этим строго. Заказчик из Штатов, это был госзаказ. Одна из систем ГОСУДАРСТВЕННОЙ СЕРТИФИКАЦИИ участников электронного документооборота уже много лет юзает моё поделие. А кто широко юзает поделие нашего Великого и Ужасного, ы? ))

===========
В общем, не люблю переходить на пенисометрию, но Великий и Ужасный задалбывает именно этим и сходу.

Рассуждать просто о технологиях с честной аргументацией, т.е. в отрыве от неких "личных достижений" — у него это как разрыв шаблона каждый раз.
С т.з. технаря — некрасивые замашки. Инфатильность.
Отредактировано 24.02.2017 18:25 vdimas . Предыдущая версия .
Re[8]: Опциональные типы
От: vdimas Россия  
Дата: 24.02.17 22:14
Оценка: -3 :))
Здравствуйте, meadow_meal, Вы писали:

_>По поводу вложенного Optional мне добавить нечего.


Тебе ответить нечего, вестимо, потому что в 3-х соснах заплутал.

Рядом коллега D. Mon на пальцах абсолютно правильно объяснил, что такое Optional/Nullable.
Это когда берется всё множество значений некоего типа и к нему добавляется еще одно СПЕЦИАЛЬНОЕ значение (некоего типа, представленного единственным значением), образуя тем самым новый тип — алгебраическую сумму исходных типов.

Прямо отсюда должно стать понятным, что если под это СПЕЦИАЛЬНОЕ значение можно выделить некое значение из исходного диапазона, то надобность складывать типы резко отпадает. Трюк стар как мир, а поди ж ты.


_>По поводу бинарной сериализации. Я не понимаю, зачем ты в разговоре постоянно скачешь с системы типов IDL на бинарную сериализацию и обратно.


Потому что IDL не предназначена для эффективной сериализации by design, вестимо.
Собсно, поэтому появился ASN.1
А еще потому, что IDL описывает синхронные вызовы, где асинхронность лишь эмулируется через возвращаемый void.

Кароч. ЗАставляешь толкать те банальности, что вот уже десяток с лишним лет как самый последний разработчик сетевых приблуд осознал, что в сети рулит просто асинхронный обмен сообщениями, т.е. встречные трафики двух ендпоинтов можно рассматривать как независимые/несинхронизированные.

Именно поэтому в ASN.1 описываются сообщения (последовательности примитивных и составных типов данных), но не интерфейсы объектов.


_>Они связаны конечно, но далеко не так прямо, как ты это хочешь представить.


Рассуждения человека, далекого от предметной области.
Это в ASN.1 прямо стандартом вводится абстрагирование самого описания данных от способов (профилей) их кодирования. На сегодня есть 4 популярных профиля кодирования.

А вот в IDL, например, в CORBA-IDL или COM-IDL бинарная сериализация прибита гвоздями ко всему. И абсолютно никакие оптимизации недопустимы, потому что есть однозначный маппинг описания на содержимое потока.


_>Битовое кодирование опциональных полей — это всего лишь деталь реализации, оптимизация, и никакого отношения к исходному вопросу не имеет.


В IDL нет битового описания опциональных полей. Если описывать union, то минимальный дискриминатор будет 1 байт. А если взять хотя бы типизированный enum в кач-ве дискриминатора (это удобно и разумно), то это будет 2 байта. Вот такие дела.


_>Прежде всего, в 2017 году странно считать, что разработка DSL и IDL вообще это rocket science.


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

А вот IDL — да, это рокет саенс.

Т.е., ты вводишь всех в заблуждение. По какой причине? — ХЗ.
Может плохо понимаешь, что есть IDL, но тебе нравится аббревиатура...
А может понимаешь, но хочется, чтобы звучало громче (именно это я имел ввиду, говоря, что ты врёшь).


_>Зачем нужен IDL?


IDL — это инфраструктура:
(a) для сериализации/десериализации посылки сообщений объектам;
(b) организация принципов identity объектов, прозрачной для любого языка, на который происходит маппинг.

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

Ты уже понял, к чему я клоню? Последнее означает, что никакой ClanID не нужен.

В системе IDL можно просто присвоить ссылку на новый клан или null, если игрок вышел из клана.
Т.е. можно писать прямо вот так на серваке (на языке программирования сервака):
gamer.setClan(newClan);
// или
gamer.setClan(null);

И ву-а-ля. Всё будет прекрасно работать само на нормальном транспорте. И передастся на клиента. Т.е. такой код мог выполнятся на, скажем C#-серваке, а в реальности null будет присвоен объекту на C++-клиенте. Вот что такое IDL.

Т.е., твоё ClaID лично мне намекает, что никакого (b) у вас там нет и в помине, а есть лишь некое (a).

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


_>Ты все сводишь к протоколам коммуникации, это лишь часть айсберга. Мы занимаемся играми средних размеров (цикл разработки один-три года до релиза, и затем поддержка). Играм нужен инструментарий — дизайнерам, локализаторам, создателям контента, аналитикам, коммьюнити-менеджерам, администраторам. Писать их под каждый проект — неокупаемо. Для AAA-игр — возможно да, для нас — нет. Нужен проектно-независимый инструментарий. Кому-то нужен код, сгенерированный из IDL, кому-то схема, подтягиваемая на лету. Без единой модели данных, описанной в IDL, все развалится, потеряет актуальность.


Бла-бла, детсад.
ДУмаешь у других в области сетевых технологий как-то по-другому?
Сорри, но ты, блин, пишешь как вчерашний студент. Я бы дал не более 27-ми лет.

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


_>Важная часть моей работы — оптимизация workflow.


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


_>А ведь в этом нет ничего особенного, это всего лишь результат использования IDL.


У вас не IDL, у вас некий DSL.


_>Разработка начинается с IDL и завязана на IDL. Он должен быть удобным, и кодогенерация должна быть гибкой. ASN.1? Нет. Он хорошо подходит для описания стандартов сетевых протоколов, но это же совсем другая задача.


Потому что ты не понимаешь слова "абстракция", вестимо.

Как ты думаешь, что означают термины front-end и back-end?
В общем, если не в курсе — подсмотришь их самостоятельно.

Так вот. На front-end-е может исопльзоваться какой-нить простенький проблемно-ориентированный DSL. Его даже не зазорно делать уникальным для каждого отдельного проекта. Не с 0-ля, ес-но, а на каком-то общем DSL-ядре.

А вот для back-end-a для сетки надо брать что-то надёжное готовое.
Потому что иначе надо будет потратить заметное кол-во человекочасов для рождения альтернативы, как минимум не уступающей в кач-ве и надежности уже имеющимся разработкам.

Я предложил ASN.1 ровно по одной причине — это пример сугубо текстового описания на выходе, под которое можно выбирать профили кодирования. Именно этим мне ASN.1 и симпатичен. Но это не принципиально, ес-но, на сегодня есть куча альтернатив.


_>Какие есть альтернативы?


Их много.
Подойдёт любой с текстовым описанием.


_>Мы начали с protobuf. Это было лет десять назад, все могло измениться. Но тогда генерируемый код был ужасен. Система типов — бедновата, даже map/dict не было.


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


_>На одном проекте промучались, другой начали с создания своего IDL. Реализация прототипа на Nemerle заняла две недели. Человекогоды разработки? Видимо ты перепутал с годами использования. Да, IDL развивался, но благодаря использованию Nemerle (а потом Nitra) — с минимальными трудозатратами. Правильные инструменты всегда решают.


В вашем случае решили не инструменты, а случайность.

Потому что удобных инструментов для разработки своих языков полно.
Скажи честно — сколько времени ты потратил на эксперименты с ANTLR?
Даже совершенно неопытный в деле разработки языков разработчик может за пару дней на ANTLR разработать свой язык описания сетевых сообщений.
А уж опытному (всего второй такой язык в репертуаре) — это дело единиц часов.


V>>Самая главная у тебя проблема — это много недоговариваний, преувеличений и откровенного вранья в итоге.

_>А у тебя — это хамство. Я открыт критике, но ты уж слишком много на себя берешь. Увольнения, обманутые инвесторы, вранье — ну не на базаре же.

Да, да. Проходили.
Сначала малость увлекаемся, а потом строим из себя невинную овечку...
Вот это моё сообщение было абсолютно нейтральным, т.е. сугубо техническим:
http://www.rsdn.org/forum/philosophy/6706569.1
Почитай, что и в каком виде ты там наотвечал.
Тебе был предложен тон делового обсуждения.
Ты в ответ предложил цирк.
Оууукееей.
Отредактировано 24.02.2017 22:15 vdimas . Предыдущая версия .
Re[9]: Опциональные типы
От: meadow_meal  
Дата: 25.02.17 03:12
Оценка: +2
Здравствуйте, vdimas, Вы писали:

_>>По поводу вложенного Optional мне добавить нечего.

V>Тебе ответить нечего, вестимо, потому что в 3-х соснах заплутал.
V>...
V>Прямо отсюда должно стать понятным, что если под это СПЕЦИАЛЬНОЕ значение можно выделить некое значение из исходного диапазона, то надобность складывать типы резко отпадает. Трюк стар как мир, а поди ж ты.

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

V>Потому что IDL не предназначена для эффективной сериализации by design, вестимо.


Ты понятие IDL трактуешь очень узко, IDL это не только CORBA и COM. Посмотри в английскую википедию на список примеров IDL — многие из них это языки описания сервисов и данных, подобные обсуждаемому, при этом они себя позиционируют как IDL (а те IDL, о которых ты говоришь, остались в прошлом веке). Впрочем, если ввел тебя в заблуждение — сожалею, это не было намеренным.

Соответственно все остальное об IDL пропускаю.

V>Я предложил ASN.1 ровно по одной причине — это пример сугубо текстового описания на выходе, под которое можно выбирать профили кодирования. Именно этим мне ASN.1 и симпатичен.


Я на это тоже уже отвечал. ASN.1 compiler генерирует то, что генерирует, а не то, что мне нужно. При этом кодогенерация вообще никак не контролируется, системы метаданных как например в protobuf у него нет. То есть в Эрланге тупл вместо рекорда — нельзя, typespec — нельзя, в C# struct вместо class — нельзя, использовать алиас на существующий тип данных указав для него внешний сериализатор — нельзя, сгенерировать Equals/EqualityComparer/или что еще в голову взбредет — нельзя. Если и ошибся в каких деталях, все равно рано или поздно уткнусь в ограничения. То есть используя ASN.1 как таргет-язык для генерации, я просто не могу решать те задачи, которые ставлю перед исходным DSL.

Но главное даже не это. Даже если б это было возможно, но — нахрена? Я бы понял, если б ты предложил ASN.1 или что еще как основной язык (но в случае с ASN.1 это полное безумие), но как промежуточный?

Я так понимаю вот это твой ответ:
> А вот для back-end-a для сетки надо брать что-то надёжное готовое.
> Потому что иначе надо будет потратить заметное кол-во человекочасов для рождения альтернативы, как минимум не уступающей в кач-ве и надежности уже имеющимся разработкам.

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

V>Потому что удобных инструментов для разработки своих языков полно.


Разве с этим кто-то спорит?

V>ANTLR


Ну и что ANTLR-то? Nemerle.Peg не сложнее, а удобная интерполяция строк как в Nemerle это musthave для кодогенерации. Ты с чем конкретно споришь-то?

V>http://www.rsdn.org/forum/philosophy/6706569.1

V>Почитай, что и в каком виде ты там наотвечал.

Прочитал, но не понял, на что ты обиделся.
Re[10]: Опциональные типы
От: vdimas Россия  
Дата: 25.02.17 10:31
Оценка:
Здравствуйте, meadow_meal, Вы писали:

_>Ты понятие IDL трактуешь очень узко, IDL это не только CORBA и COM.


Я тебе дал вполне конкретное представление о том, что есть IDL, не наговаривай на конкретно CORBA или COM.
Почитай про тот же ICE:
https://en.wikipedia.org/wiki/Internet_Communications_Engine

В этом месте тебе должно быть уже понятно отличие Google protobuf или Microsoft bond от фреймворков подобного рода.
Не надо путать фреймворки сугубо для бинарной сериализации и фреймворки для удалённых вызовов методов объектов.

Потому что в первом случае ты сам работаешь напрямую с транспортным слоем, а во втором тебе транспортный слой, считай, не видим ("прозрачен", согласен IT-терминологии).

Поэтому, коль я по косвенным признакам догадался о неверном использовании тобой абревиатуры IDL, я предложил тебе фреймворк другого типа — ASN.1.
Почему именно он — он лучший на сегодня из всех.

Даже если тебе не нравится сам ASN.1 — я уже сказал что надо делать — надо просто написать свой примитивнейший DSL, который на выходе даст ASN.1.

Хотя, даже сам ASN.1 весьма удобен, просто надо потратить хотя бы час-другой времени на его изучение. Например, в этом языке есть ЯВНАЯ поддержка optional-семантики.

А еще в языке есть параметрические типы. ))
Т.е. можно задать генерик-описание сообщения, например:
Point{DataType} ::= SEQUENCE {
    x DataType, 
    y DataType
}

Зависимости можно протягивать:
Move{DataType} ::= SEQUENCE {
    from Point{DataType}, 
    to   Point{DataType}
}

а потом специализировать
UpdateXXX ::= CHOICE {
    i [0] Move<int32>, 
    f [1] Move<float>,
    d [2] Move<double>
}


А еще для этих параметрических типов можно описывать классы типов:
LevelParams ::= CLASS {
    &level-field-width int32,
    &level-field-height int32,
}

Move-PDU{LevelParams : param} ::= SEQUENCE {
   x INTEGER (0..param.&level-field-width),
   y INTEGER (0..param.&level-field-height)
}

И вот для разных уровней могут быть разные кодировки сообщений в потоке, потому что битовая ширина x и y может быть разной.

Есть еще много других прикольных плюшек, чего стоит один только тип SET — это же бомба!

Кароч, я много одно время смотрел альтернативных технологий, но они по выразительности и мощи проигрывают ASN.1, как первоклашки проигрывают профессору ВУЗ-а в области математики. ))


_>Я на это тоже уже отвечал. ASN.1 compiler генерирует то, что генерирует, а не то, что мне нужно.


У некоторых компилятором маппинг можно настраивать.


_>При этом кодогенерация вообще никак не контролируется, системы метаданных как например в protobuf у него нет.


Опять же — есть:
http://bnotes.sourceforge.net/

Вот тебе с метаинформацией для C#:
[ASN1Sequence ( Name = "TestSequence", IsSet = false )]
public class TestSequence 
{
    private long field1_ ;

    [ASN1Element ( Name = "field1", IsOptional = false , HasTag = false , HasDefaultValue = false ) ]
    public long Field1 {
        get { return field1_; }
        set { field1_ = value; }
    }
...



_>То есть в Эрланге тупл вместо рекорда — нельзя, typespec — нельзя, в C# struct вместо class — нельзя, использовать алиас на существующий тип данных указав для него внешний сериализатор — нельзя, сгенерировать Equals/EqualityComparer/или что еще в голову взбредет — нельзя.


Здра моя ра!
А не путаете ли вы, батенька, транспортный слой с прикладным?
Или у тебя там всё вперемешку?

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


_>Если и ошибся в каких деталях, все равно рано или поздно уткнусь в ограничения.


Потому что ты уткнулся в архитектуру без DAL.


_>То есть используя ASN.1 как таргет-язык для генерации, я просто не могу решать те задачи, которые ставлю перед исходным DSL.


ASN.1 тут не при чем от слова совсем, хосподя...

Я тебе предлагал на основе BLToolkit сделать автоматический маппинг с транспортного слоя на прикладной.
Я же говорю — ты не понял НИ СЛОВА из того, что я писал тебе ранее.
Даже где-то обидно... ))


_>Но главное даже не это. Даже если б это было возможно, но — нахрена? Я бы понял, если б ты предложил ASN.1 или что еще как основной язык (но в случае с ASN.1 это полное безумие), но как промежуточный?


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

А еще потому, что ASN.1 предлагает тебе trade-off изкаробки: можно выбирать из целой градации профилей кодирования, от самых эффективных по размеру пакета до самых эффективных по затрачиваемым ресурсам проца. И тебе несложно будет переключать эти профили. Например, если у какого-то клиента плохой пинг, то серверу стоит ужать трафик в сторону такого клиента в НЕСКОЛЬКО РАЗ. А если хороший, то стоит тратить на такого клиента меньше тиков процессора.

Никакая другая технология вот всеми этими совокупными св-вами НЕ обладает. Более того. На сегодня идёт развитие в нужном направлении только ASN.1.
Остальные конкурирующие технологии мертвы — будучи разработаны однажды для чего-то, быстро становятся невостребованы по окончании проекта, в котором были применены. Эдакая "одноразовость", мертвечинка...


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


И там и там.
А еще в ошибках, т.е. тупо в багах. Был я как-то на одном проекте, так только в коде бинарной кастомной сериализации отловил порядка десятка ошибок. Причем, ошибки удачно максировались тем, что периодически шла не только дельта, но и абсолютные значения, угу. Поэтому ошибки в дельтах приводили лишь к "кратковременному вранью", которое списывали на притормаживание. )) А не было никакого притормаживания, были баги.


V>>Потому что удобных инструментов для разработки своих языков полно.

_>Разве с этим кто-то спорит?
V>>ANTLR
_>Ну и что ANTLR-то? Nemerle.Peg не сложнее

Он не не сложнее, а беднее на многие-многие порядки. Он пуст как абстрактное zero. Как Мухосранк посреди Сибири. ))

Ты, таки, взял бы в руки ANTLR. Это мощнейшая визуальная система разработки и отладки грамматик.
В принципе, ПОСЛЕ отладки грамматики в ANTLR запросто можно закодировать её в чем угодно, хоть даже в Nemerle.

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


_>а удобная интерполяция строк как в Nemerle это musthave для кодогенерации.


Да это вообще для кодогенерации пофиг. Экономия 1% усилий. Проблема чаще не в кодогенерации, а в модели, по которой она происходит. А модель зависит от языка. А вот разработать сам язык — это и есть самая мякотка.


_>Прочитал, но не понял, на что ты обиделся.


Я не принимаю простых "я не согласен", "тут не прав", "а это грязный хак" (чего???) и прочей такой фигни.

Технический спор это:
— вот тут ты не прав, потому что: ...
или
— а здесь я бы предложил альтернативу, которая в сравнении с исходным вариантом даёт следующее: ...

И т.д. в этом же духе.

Всё остальное — это просто обмен какашками, в какую бы вежливую форму они ни были завёрнуты.
Отредактировано 25.02.2017 10:35 vdimas . Предыдущая версия . Еще …
Отредактировано 25.02.2017 10:31 vdimas . Предыдущая версия .
Re[17]: Опциональные типы
От: vdimas Россия  
Дата: 25.02.17 10:59
Оценка: -1
Здравствуйте, fddima, Вы писали:

F>Но по голому факту: мэйнстрим фронты используют ужаснейший recursice descent.


Это просто декомпозиция грамматик.

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

recursice descent в этом смысле — это декомпозиция грамматики на несколько НЕЗАВИСИМЫХ областей.

Простой пример: нет смысла парсить вычисления формул в синтаксисе объявлении класса или заголовков методов в C#. А вот внутри тел методов — есть, но зато внутри тел методов нельзя объявлять другие классы, поэтому эта часть грамматики внутри тел методов НЕ нужна. Вот тебе и декомпозиция.
Re[16]: Опциональные типы
От: vdimas Россия  
Дата: 25.02.17 11:42
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Но похоже ничего кроме трёпа от него так и не будет. Видимо показывать просто нечего.


Показываю.

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

А теперь представим, что есть неоднозначность, которую можно разресолвить лишь "когда-нибудь потом". Из таблицы для такого разборщика по данному символу идёт список следующих состояний. На каждую альтернативу ты заводишь по новой "копии" текущего состояния парсера. Всё копировать не надо — цепочка предыдущего разбора будет общая для всех новых альтернатив. В какой-то момент по текущему символу есть переходы не у всех альтернативных веток. У кого нет перехода (переход в ошибку) — те ветки отмирают. Если отмерли все ветки или в конце разбора будет более одной ветки — это ошибка во входной цепочке. Всё.

Далее.
Известно, что для класса регулярных грамматик (которые растут только справа или только слева) такую недетерминированную таблицу можно привести через известные несколько алгоритмов к детерминированной. Для случая леволинейной грамматики (а грамматики для лексера записывают почти всегда именно в этой форме) получим эдакий LR(0) разбор. 0 — потому что нет альтернатив, т.е. нет рекурсий/иерархий/дерева разбора, вернее дерево разбора имеет всегда константную вложенность — ровно 1, т.н. любая LR-"свертка" — это уже и есть конечный допустимый символ, это и есть выход лексера. Поэтому, если ты понимаешь, как работает автоматный лексер, то ты уже почти понимаешь как работает LR-разбор — в его случае "свернутая" цепочка нетерминалов заменяется другим нетерминалом и идёт разбор уже от него. Т.е. лексер выплёвывает нетерминал "куда-то наверх", а LR-парсер — себе же.

Итого, LR-разбор — это иерархия банальных тупейших лексеров, именно так. Т.е. каждая вложенность — это вызов эдакого "низлежащего лексера".

Например, в C#

public class MyClass : Base1, Base2 {

Вот эта изолированная цепочка относится к классу регулярных грамматик и соответственно её LR-парсинг столь же эффективен, да еще по точно такому же алгоритму по такой же таблице. На входе будет 8 символов-нетерминалов, полученных от лексера, на выходе — нетерминал, означающий заголовок описания класса.

Кстате, именно поэтому часто можно встретить scanerless GLR-парсер, бо а смысл выделять какой-то специальный уровень под автоматную грамматику, если у нас и так на каждом уровне иерархии зачастую идёт исключительно автоматная грамматика?

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

Большинство языков, даже С+, на более 90% своих цепочках однозначны, т.е. участки параллельного протягивания нескольких вариантов обычно весьма и весьма коротки.

==============
Дальше наблюдения насчёт применимости алгоритма.

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

А когда в случае EDI обычно идёт протягивание в среднем не более 2-х одновременных альтернативных веток парсера на такие "далекие расстояния", то параллельный алгоритм парсинга напрашивается сам собой.

В итоге, по результатам исследования своей предметной области я ВСЕГДА протягивал две непосредственные альтернативы + список дополнительных. Изначально шел сразу список, но это давало косвенность +1 на каждом шаге, к тому же на каждом участке получается цикл по списку, даже если у нас всего одна альтернатива. Затем я ввел одну непосредственную альтернативу + список остальных — стало лучше. В итоге лучший результат получил на двух непосредственных альтернативах + список остальных.

В итоге, в случае однозначных цепочек (т.е. когда работает лишь первая альтенатива) у меня всё отличие от алгоритма работы лексера по детерминированной таблице было в одном if на каждый входной НЕТЕРМИНАЛ.

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

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

подключение парсера к работающему лексеру даёт в среднем 5-10% проседания производительности.


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

=========
А твои "быстрее лексера" — это спекуляция и нечистоплотность.
Дословно было сказано "на уровне лексера".
Отредактировано 25.02.2017 12:02 vdimas . Предыдущая версия . Еще …
Отредактировано 25.02.2017 11:59 vdimas . Предыдущая версия .
Re[6]: Опциональные типы
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 25.02.17 11:55
Оценка: +1
Здравствуйте, meadow_meal, Вы писали:

V>>Если речь об IDL, то проблемно-ориентированное кодирование всей твоей матрешки идёт вот так:

V>>
V>>enum ClanUpdate { NoUpdate, EnterClan, ExitClan };

V>>union ClanEvent switch (ClanUpdate) { 
V>>       case NoUpdate: ; 
V>>       case EnterClan: int ClanId; 
V>>       case ExitClan: ; 
V>>}; 
V>>


_>Сразу вопросы:


_>1) А для обязательных полей ты тоже рекомендуешь объявлять enum и union? Или мы обязательные поля обновляем одним способом, а опциональные другим? Если так, то разве это — не проблема сопровождения? (Для меня одно из базовых требований при выборе паттерна — то, что придет новый человек и сможет сходу решать любую простую задачу "по аналогии".)


Ну если ты этому человеку опишешь это (в Erlang стиле) как {ok, ClanId:integer()} | no_update | exited — будет совершенно очевидно.

А вот заворот в несколько слоёв Optional<> хуже и тем, что после второго уровня шарики забегают за ролики, и тем, что туда не вложить никакую дополнительную информацию.

Не хочу тут рассуждать о формате IDL, всё это вторично, а то, что описал тут — важнее. IMHO.
The God is real, unless declared integer.
Re[7]: Опциональные типы
От: vdimas Россия  
Дата: 25.02.17 12:00
Оценка:
Здравствуйте, netch80, Вы писали:

N>Ну если ты этому человеку опишешь это (в Erlang стиле) как {ok, ClanId:integer()} | no_update | exited — будет совершенно очевидно.


Именно так.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.