Re[14]: Размышления о типизаторе для Н2
От: VladD2 Российская Империя www.nemerle.org
Дата: 27.06.11 16:49
Оценка:
Здравствуйте, artelk, Вы писали:

A>>>покрывающее, по крайней мере, строготипизированные языки программирования.

WH>>Что такое строготипизированные языки программирования я так и не понял.
WH>>Это слишком мутный термин.
A>А если убрать это слово, станет ли предложение верным?

Это у WolfHound-а стиль такой. Он вместо того чтобы просто что-то сказать выдает фантак сарказма.
В данном случае он имел в виду, что вместо "строготипизированные" нужно использовать термин "статическитипизированные".

А "строготипизированные" — это степень ревностности в отношении к проверкам типов. Строготипизированным может быть и скрипт. И термин действительно мутный.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[14]: Размышления о типизаторе для Н2
От: VladD2 Российская Империя www.nemerle.org
Дата: 27.06.11 18:05
Оценка:
Здравствуйте, artelk, Вы писали:

A>3. Далее рукопашный код, который сужает объем KC языка до спецификации целевого языка — третий слой со своими абстракциями (типами, перегрузками и т.п.)


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

A>4. Потом кодогенератор как отдельный слой...


Все давно украдено до нас (с).

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

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


Они отлично разделяются. Если это не так — это беда конкретных реализаций.


WH>>Ибо семантика языка задает смысл каждой строки языка.

A>Ну да, на каждом уровне происходит трансформация "предложений" "языка" нижнего уровня в язык верхнего, тем самым "обеспечивая" их семантикой.

+1

WH>>А это все проверки на то принадлежит ли строка языку. Те синтаксис.

WH>>Но Влад верит, что КС грамматика задает сам язык. То, что она задает не язык, а надмножество языка он не понимает.
A>Надмножество языка — тоже язык. Думаю, он просто опасается, что первые три уровня смешаются в одну большую кучу неподдерживаемого кода. Или что DSL для ее разруливания будет слишком сложным для простых смертных.

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

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

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

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

Более того. Это еще и невозможно сделать. Парсинг останется парсингом, а типизация типизацией. При всех громких заявлениях WolfHound так и не продемонстрировал алгоритма разбора КЗ-грамматик, а умные люди давно посчитали, что это слишком вичислительно затратно. Так что на это надеяться нет смыла.

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

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

A>Кстати, а нельзя ли саму кодогенерацию посадить на тот же движек?


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

A>У макросов есть rewrite часть, которая трансформирует элемент более высокоуровневого языка в термины более низкоуровневого.


Это довольно тонкий вопрос.

Почему в низкоуровневый то? На самом деле макры транслируют все в тот же язык. Макры это не кодогенерация в том смысле в котором этот термин понимается в компиляторе.

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

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

A>А чем MSIL или машинный код не языки?!


Отличный вопрос! Потому что MSIL — это другой язык. Трансляция в него и есть компиляция. Лепить трансляцию в MSIL на основании некого синтаксического сахара вроде foreach-а — это садомазохизм, так как это приведет к офигительному дублированию кода, серьезным сложностям и т.п. Скажем у linq-запросов из C# банально нет своей семантики. Она в спецификации выражается в терминах переписывания в другие конструкции C#. Лепить генерацию MSIL по linq-запросам — означает сдублировать кодогенерацию для вызова методов. А зачем это нужно?

A>Если позволить макросу иметь несколько rewrite частей и выбирать нужную в зависимости от текущей платформы, текущего "базового" языка или какого-то промежуточного, то будем иметь дополнительную гибкость повторного использования кода.


Это будет кабздец. Полный.

A> Нужно только как-то предотвратить перескакивание через языки — чтобы не позволить писать на Nemerle вперемежку с MSIL. Еще могут быть неоднозначности по какому пути идти от самого верхнего уровня к MSIL.


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

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

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

Раз мы имеем фиксированный и типизированный АСТ (язык в объектной форме), то трансляция его в действительно более низкоуровневые язки становится совершенно примитивной задачей. Нужно просто задать таблицу соответствия.

Единственная проблема которая встает у нас на пути — не все платформы (здесь под платформами я понимаю .Net, Java и различные варианты нэтив-рантаймов) могут реализовывать примитивы которые поддерживаются нашим обессахаренным языком. Например, в платформах может не поддерживаться: замыканий, ФВП, классов и т.п. Это приводит к мысли о том, что требуются средства расщепления примитивов. По сути это тот же процесс раскрытия макросов, и наверное, его можно реализовать теми же средствами. Единственное отличие — раскрытие таких макросов будет происходить в зависимости от бэкэнда. Если бэкэнд поддрживает ту или иную сущность, то ему не нужно раскрывать этим макросы. В обратном случае он получит код на все том же под-языке, но без некоторых конструкции. Эти конструкции будут заменены на другие конструкции.

Например, не секрет, что замыкания можно выразить через классы, а классы через замыкания. Можно легко представить, что для некоторого гипотетического функционального рантайма придется устранить классы, переписав их в замыкания, а для дотнета с явой придется расщепить замыкания преобразовав их в классы, а возможно и просто переписав часть кода так, чтобы он стал императивным (т.е. произведя оптимизацию).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[16]: Размышления о типизаторе для Н2
От: VladD2 Российская Империя www.nemerle.org
Дата: 27.06.11 18:44
Оценка:
Здравствуйте, artelk, Вы писали:

A>rewrite "if" of Nemerle to Nemerle

A>{
A> //тут только код на Nemerle и\или на языке, который в него транслируется
A> match(...)
A> ...
A>}

Вот это и есть макросы.

A>syntax "match" of Nemerle

A>//многа ядреного ДСЛя
A>typing
A>//многа ядреного ДСЛя

A>//отдельно

A>rewrite "match" of Nemerle to MSIL
A>{
A> //тут только код на MSIL и\или на языке, который в него транслируется
A>}

A>//где-то совсем в другом месте — там, где требуется генерация в нэйтив

A>rewrite "match" of Nemerle to x86_assembler
A>{
A> //тут только код на x86_assembler и\или на языке, который в него транслируется
A>}
A>[/code]
A>

А вот это уже есть задница, так как сгенерировать IL или asm по АСТ высокоуровневого языка (пуст даже типизированному) — это задача неберучка. В обоих кусках кода будет огромное дублирование кода.

Для справки. При компиляции match производится в несколько этапов:
1. Производится типизация паттерна. Тут в Н1 есть промашка этот этап слит со следующим.
2. Генерируется специализированное представление паттернов. В Н1 это представление выглядит так.
3. Далее происходит анализ специального представление и преобразование его в так называемое дерево вывода (decision tree).
4. Производится переписывание дерева вывода в код содержащий if-ы и goto. При этом части кода могут дублироваться, перемещаться и т.п.

Таким образом генерировать MSIL или asm по AST оператора match — это очень глупое занятие. Вместо этого имеет смысл иметь макрос-расщипитель (рассахариватель) заменяющий обращение к match на набор низкоуровневых конструкций. А кодогенерацию уже вести для них.

Более того! Код в который переписывается match — это уже не, например, Немерле! Ведь в Немерле нет goto и if (if макрос).

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

Итого можно вообразить следующую схему. У нас есть:
1. Макросы. Их цель — рассахаривание. Они переписывают язык X в него же самого. В конце раскрытия всех макросов мы должны получить рассахаренный язык X. Именно его я и называют базовым языком.
2. Кодогенераторы. Их цель — преобразовать над минимизированного языка X в язык Y. При этом в языке Y могут использоваться макросы.

В такой схеме бэкэнды становятся одним из типов кодогернераторов совмещенных с сериализацией в формат исполнимых файлов целевой платформы. Бэкэнд может использовать стандартные генераторы и раскрытие макросов с целью устранения из AST не поддерживаемых бэкэндом сущностей. Например, бэкэнд для дотнета устранит из AST замыкания, а бэкэнд для нэтив устранит вообще все кроме вызова функций и работы с переменными.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[16]: Размышления о типизаторе для Н2
От: WolfHound  
Дата: 27.06.11 19:12
Оценка:
Здравствуйте, artelk, Вы писали:

A>Строго-научно да. Но, с точки зрения практики, такое разбиение все равно целесообразно проводить и оно чаще всего приводило к заметному упрощению кода, не так ли? Хотя бы потому, что первые два слоя относительно легко посадить на геренатор парсера, а с третьим в этом смысле сложнее.

На самом деле и с первыми двумя все не просто.
Генераторы парсеров по EBNF особенно семейство LR страдают невнятными сообщениями об ошибках.

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

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

A>Если язык удобно представить в виде "матрешки" (например: наднадъязык, надъязык и собственно язык), то семантика будет появляться при каждом переходе от внешнего языка к более детальному внутреннему, имхо.

Матрешка это деталь реализации.
Не более того.
И в твоем случае терминология начинает плавать в зависимости от деталей реализации.

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

Куда пропадает?

A>Или же оптимизация это семантика?

И она тоже.

A>Родилось такое:

Очень наивно.
На практике все будет весьма иначе.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[15]: Размышления о типизаторе для Н2
От: WolfHound  
Дата: 27.06.11 19:39
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Более того. Это еще и невозможно сделать. Парсинг останется парсингом, а типизация типизацией. При всех громких заявлениях WolfHound так и не продемонстрировал алгоритма разбора КЗ-грамматик, а умные люди давно посчитали, что это слишком вичислительно затратно. Так что на это надеяться нет смыла.

Пожалуйста цитату в студию где я обещал использовать КЗ грамматику.

VD>То что для некоторых языков (которые давно пора хоронить) при парсинге нужно использовать таблицу символов (аргумент WolfHound-а) ровным счетом ничего не значит.

Это просто констатация факта.

VD>Если обратиться к столь нелюбимому WolfHound-ом Ахо, то на одной из первых картинок в его книге можно заметить диаграмму где слева находится таблица символов, а справа стадии анализа и генерации. Другими словами еще тыщы лет назад люди понимали, что таблица символов является аспектом проходящим на сквозь через все стадии компиляции. Ну, так и не фига ломать традиции без особых на то оснований?

Я тебя что-то не понимаю.
То "пора хоронить" то "не фига ломать".

VD>Почему в низкоуровневый то?

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

VD>На самом деле макры транслируют все в тот же язык. Макры это не кодогенерация в том смысле в котором этот термин понимается в компиляторе.

Это именно что кодогенерация.

VD>Отличный вопрос! Потому что MSIL — это другой язык.

Немерле с if'ом и немерле без if'а это тоже разные языки.

VD>Трансляция в него и есть компиляция. Лепить трансляцию в MSIL на основании некого синтаксического сахара вроде foreach-а — это садомазохизм, так как это приведет к офигительному дублированию кода, серьезным сложностям и т.п.

Разумеется, будет использована иерархия языков.
Читай внимательней, что тебе пишут.

VD>Скажем у linq-запросов из C# банально нет своей семантики. Она в спецификации выражается в терминах переписывания в другие конструкции C#. Лепить генерацию MSIL по linq-запросам — означает сдублировать кодогенерацию для вызова методов. А зачем это нужно?

Ты как ни крутись, а вызова по LINQ запросам тебе всеравно генерировать.

A>>Если позволить макросу иметь несколько rewrite частей и выбирать нужную в зависимости от текущей платформы, текущего "базового" языка или какого-то промежуточного, то будем иметь дополнительную гибкость повторного использования кода.

VD>Это будет кабздец. Полный.
Нет. Единственно верный путь.
Ты предлагаешь страшный костыль за те же деньги.

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

Бла-бла-бла.
Базовый язык не существует.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[13]: Размышления о типизаторе для Н2
От: artelk  
Дата: 27.06.11 21:15
Оценка:
Здравствуйте, VladD2, Вы писали:

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


VD>На самом деле вся разница между нашими подходами заключается только в том допускается ли преобразование нетипизированного АСТ или нет.

На мой взгляд подход WH — это придумать механизм, в котором твой подход с базовым языком (и аналогичные ему) делаются наиболее просто, лаконично и в общем виде. Хотя как быть с linq — мне лично пока не понятно. С одной стороны, это как язык в языке со своей грамматикой, с другой — в нем позволяются вставки из внешнего языка. Как его типизировать, не типизируя эти вставки и вообще что будет его типом (догадываюсь, что не IEnumerable<T>), причем, чтобы это позволило использовать интеллисенс — не знаю. Жду, когда WH представит свой вариант.

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

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

VD>Для проверки концепций достаточно создать маленький кусочек. Но чтобы его создать нужно сделать кучу побочной работы. Тот же "специализированный Меркури" включает в себя довольно много сложного кода большая часть которого есть в Н1. Это, в первую очередь, движок унификации который позволит унифицировать не просто термы (как в прологоподобных языках вроде Меркури), а типы с поддержкой подтипов. Это не маленький такой (и не самый простой) код. Только на его отдадку можно убить несколько месяцев. А на базе солвера из Н1 его можно создать очень быстро и просто. Он, конечно, будет далек от идеала по производительности, но для прототипа этого и не надо.

А не проще ли взять готовый Меркури и вызывать его в компайлтайме?
Re[17]: Размышления о типизаторе для Н2
От: artelk  
Дата: 27.06.11 21:38
Оценка:
Здравствуйте, VladD2, Вы писали:

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


VD>А вот это уже есть задница, так как сгенерировать IL или asm по АСТ высокоуровневого языка (пуст даже типизированному) — это задача неберучка. В обоих кусках кода будет огромное дублирование кода.

А я и не буду настаивать, чтобы match напрямую в IL или asm трансформировать. Согласен, между match и кодом целевой платформы нужно сделать еще несколько промежуточных языков. Т.е. транслировать только то, что транслируется просто, постепенно спускаясь на уровень платформы. При смене платформы достаточно создать алтернативные реализации только для достаточно низкоуровневых макросов, а всю сложную логику повторно использовать.

VD>Таким образом генерировать MSIL или asm по AST оператора match — это очень глупое занятие. Вместо этого имеет смысл иметь макрос-расщипитель (рассахариватель) заменяющий обращение к match на набор низкоуровневых конструкций. А кодогенерацию уже вести для них.

Да, но эти рассахариватели, по сути, тоже кодогенераторы в язык этих "низкоуровневых конструкций".

VD>Более того! Код в который переписывается match — это уже не, например, Немерле! Ведь в Немерле нет goto и if (if макрос).

VD>Таким образом можно говорить о том, что match — это макрос некоторого другого языка в который переписывается немерл.
Да.

VD>Итого можно вообразить следующую схему. У нас есть:

VD>1. Макросы. Их цель — рассахаривание. Они переписывают язык X в него же самого. В конце раскрытия всех макросов мы должны получить рассахаренный язык X. Именно его я и называют базовым языком.
Хмм.. рассахаренный match — это уже не Nemerle, т.е. не в него же самого.
VD>2. Кодогенераторы. Их цель — преобразовать над минимизированного языка X в язык Y. При этом в языке Y могут использоваться макросы.
А чем они принципиально отличаются от 1.?
Кстати, теоретически можно сделать компилятор IL в asm — свой ngen. Компиляция в IL будет кодогенератором или просто макросом?
Re[15]: Размышления о типизаторе для Н2
От: artelk  
Дата: 27.06.11 21:40
Оценка: +1
Здравствуйте, VladD2, Вы писали:

VD>Это у WolfHound-а стиль такой. Он вместо того чтобы просто что-то сказать выдает фантак сарказма.

Эх.. никто не безгрешен
Re[16]: Размышления о типизаторе для Н2
От: VladD2 Российская Империя www.nemerle.org
Дата: 27.06.11 21:42
Оценка:
Здравствуйте, WolfHound, Вы писали:

VD>>Отличный вопрос! Потому что MSIL — это другой язык.

WH>Немерле с if'ом и немерле без if'а это тоже разные языки.

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

VD>>Трансляция в него и есть компиляция. Лепить трансляцию в MSIL на основании некого синтаксического сахара вроде foreach-а — это садомазохизм, так как это приведет к офигительному дублированию кода, серьезным сложностям и т.п.

WH>Разумеется, будет использована иерархия языков.
WH>Читай внимательней, что тебе пишут.

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

Переписывание X в X делается тупым квази-цитированием. Переписывание, X в Y требует наличия кучи дополнительной информации (тех же типов и т.п.).

VD>>Скажем у linq-запросов из C# банально нет своей семантики. Она в спецификации выражается в терминах переписывания в другие конструкции C#. Лепить генерацию MSIL по linq-запросам — означает сдублировать кодогенерацию для вызова методов. А зачем это нужно?

WH>Ты как ни крутись, а вызова по LINQ запросам тебе всеравно генерировать.

И что? Мне их два раза сгенерировать? Один для псевдотипизации, а второй где будет типизироваться раскрытый код?

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


A>>>Если позволить макросу иметь несколько rewrite частей и выбирать нужную в зависимости от текущей платформы, текущего "базового" языка или какого-то промежуточного, то будем иметь дополнительную гибкость повторного использования кода.

VD>>Это будет кабздец. Полный.
WH>Нет. Единственно верный путь.
WH>Ты предлагаешь страшный костыль за те же деньги.

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

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

WH>Бла-бла-бла.

Снова хамишь.

WH>Базовый язык не существует.


Базовый язык — это язык в котором нечего раскрывать.

Совершенно по хрену когда происходит раскрытие макроса, до и или после типизации. Главное в макросе то, что он раскрывается в тот же язык (а значит может использовать все его примитивы). Преобразование же другой язык — это другое действие. При этом будет происходить изменение объектной модели.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[17]: Размышления о типизаторе для Н2
От: WolfHound  
Дата: 27.06.11 22:18
Оценка: 1 (1) +2
Здравствуйте, VladD2, Вы писали:

VD>Вот это грубейшая ошибка. Н без иф-а не перестает быть Н.

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

VD>А тебе не кажется, что есть огромная разница между переписыванием одного языка в свой же саб-сэт (а то и супер-сет, так как переписанный код так же может быть засахаренным), и переписывании одного языка в другой?

Нет.

VD>Переписывание X в X делается тупым квази-цитированием. Переписывание, X в Y требует наличия кучи дополнительной информации (тех же типов и т.п.).

Ну-ну. Про foreach и компанию уже забыл?

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

Повторной типизации не будет. Экспоненты тоже.

VD>Я предлагаю отделить мух от котлет.



VD>Сначала раскрываем все макросы и производим типизацию. В итоге получаем код без макросов (только с АСТ для которого вычислены типы. Потом то что получилось преобразуем в другой язык. Это делаем спомощью максимально формализованного (формально описанного на неком ДСЛ-е) маппера.

А тебе не кажется что вот этот вот маппер это то же самое, что переписыватель кода в случае с макрами?

VD>Базовый язык — это язык в котором нечего раскрывать.

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

VD>Совершенно по хрену когда происходит раскрытие макроса, до и или после типизации. Главное в макросе то, что он раскрывается в тот же язык (а значит может использовать все его примитивы). Преобразование же другой язык — это другое действие. При этом будет происходить изменение объектной модели.


Вот есть у нас макра LINQ это уже новый язык или еще нет?
А ComputationExpressions?
А XmlLiterlas?
А PegGrammar?
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[14]: Размышления о типизаторе для Н2
От: WolfHound  
Дата: 27.06.11 22:23
Оценка:
Здравствуйте, artelk, Вы писали:

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

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

A>Хотя как быть с linq — мне лично пока не понятно. С одной стороны, это как язык в языке со своей грамматикой, с другой — в нем позволяются вставки из внешнего языка. Как его типизировать, не типизируя эти вставки и вообще что будет его типом (догадываюсь, что не IEnumerable<T>), причем, чтобы это позволило использовать интеллисенс — не знаю. Жду, когда WH представит свой вариант.

При наличии модульного типизатора разници между linq и любой другой конструкцией языка не будет.

A>Все с нуля не обязательно — достаточно, например, несколько макросов-трансляторов между базовыми языками, если они близки.

Этого он тоже не понимает.

A>А не проще ли взять готовый Меркури и вызывать его в компайлтайме?

Не проще.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[18]: Размышления о типизаторе для Н2
От: VladD2 Российская Империя www.nemerle.org
Дата: 27.06.11 23:00
Оценка:
Здравствуйте, artelk, Вы писали:

VD>>Итого можно вообразить следующую схему. У нас есть:

VD>>1. Макросы. Их цель — рассахаривание. Они переписывают язык X в него же самого. В конце раскрытия всех макросов мы должны получить рассахаренный язык X. Именно его я и называют базовым языком.
A>Хмм.. рассахаренный match — это уже не Nemerle, т.е. не в него же самого.

В Nemerle оператор match является базовой конструкцией. Он не рассахиривается. Вот когда Nemerle конвертируется (отображается) в другой, более низкоуровневый язык, то match (в этом языке) уже будет макросом, и как следствие будет рассахариваться в конструкции if и goto.

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

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

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

VD>>2. Кодогенераторы. Их цель — преобразовать над минимизированного языка X в язык Y. При этом в языке Y могут использоваться макросы.

A>А чем они принципиально отличаются от 1.?

Моделью. Скажем исходный язык — это немерле. В нем есть match как базовое понятие и нет if и goto. Точнее if есть, но это макрос который является сахаром к match. Второй язык — это язык в котором нет match, точнее есть match, как макрос, и есть if и goto, как базовые конструкции. Кроме того целевой (2) язык не имеет таких штук как перегрузка и т.п. Он полностью определен и по нему можно генерировать код.

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

A>Кстати, теоретически можно сделать компилятор IL в asm — свой ngen.


В теории теория и практика эквивалентны, на практике — нет.

Это уже бессмысленные мечты. У ngen свои детали, которые делают этот продукт не простым. Вопросы парсинга и типизации при этом будет десятыми по важности. Да и нужды в этом нет. Никто не будет писать код на IL. Ну, а теоретически, да — можно.

A>Компиляция в IL будет кодогенератором или просто макросом?


Компиляция в IL — это вообще дело бэкэнда. Тут опят же важны детали. Кроме IL-а нужно еще ведь метаданные сборки сгенерировать.

Может ты ошибся и хотел сказать компиляция в асм (из IL-а)?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[14]: Размышления о типизаторе для Н2
От: VladD2 Российская Империя www.nemerle.org
Дата: 27.06.11 23:05
Оценка:
Здравствуйте, artelk, Вы писали:

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


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

Я же не против универсальных решений. Только в первую очередь решение должно быть удобным для конечного пользователя, делать то что нужно и быть понятным.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[18]: Размышления о типизаторе для Н2
От: VladD2 Российская Империя www.nemerle.org
Дата: 27.06.11 23:21
Оценка: -1
Здравствуйте, WolfHound, Вы писали:

VD>>Вот это грубейшая ошибка. Н без иф-а не перестает быть Н.

WH>Это у тебя каша в голове.
WH>Это другой язык просто по определению.
WH>Ибо он состоит из другого множества строк.



VD>>Переписывание X в X делается тупым квази-цитированием. Переписывание, X в Y требует наличия кучи дополнительной информации (тех же типов и т.п.).

WH>Ну-ну. Про foreach и компанию уже забыл?

Нет не забыл. Главное, что при переписывания foreach не требуются новые понятия. Переписанных код — это код на все том же языке, а форыч не более чем сахар.

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

WH>Повторной типизации не будет. Экспоненты тоже.



VD>>Сначала раскрываем все макросы и производим типизацию. В итоге получаем код без макросов (только с АСТ для которого вычислены типы. Потом то что получилось преобразуем в другой язык. Это делаем спомощью максимально формализованного (формально описанного на неком ДСЛ-е) маппера.

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

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

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

VD>>Базовый язык — это язык в котором нечего раскрывать.

WH>Его не существует.

Это у тебя каша в голове.

WH>Нельзя создать базовый язык на все случи жизни.


Это у тебя каша в голове.
Базовый язык — это просто макры без тел преобразования в тот же язык. Макры описывающие только АСТ. Для таких макр будет обязательна типизация (так как именно их придется в итоге мапить в концептуально другой язык).

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


Это у тебя каша в голове.

WH>Они просто разрушают семантику друг друга.


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

WH>Про языки с другим вычислительным базисом и говорить нечего.


Ну, вот и не будем.

VD>>Совершенно по хрену когда происходит раскрытие макроса, до и или после типизации. Главное в макросе то, что он раскрывается в тот же язык (а значит может использовать все его примитивы). Преобразование же другой язык — это другое действие. При этом будет происходить изменение объектной модели.

WH>
WH>Вот есть у нас макра LINQ это уже новый язык или еще нет?


Нет. Это у тебя каша в голове. Это чистый сахар.

WH>А ComputationExpressions?


Нет.

WH>А XmlLiterlas?


Нет.

WH>А PegGrammar?


Нет.

И на всякий случай еще раз — да, если надо, то можно будет воспользоваться типизацией до раскрытия, а так же поиском имен и т.п. Так что для PegGrammar будут все условия.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[18]: Размышления о типизаторе для Н2
От: VladD2 Российская Империя www.nemerle.org
Дата: 27.06.11 23:24
Оценка:
Здравствуйте, WolfHound, Вы писали:

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

Как бы обобщить работу с типами, так чтобы с одной стороны не привязываться к ООП, а с другой иметь возможность не изобретать велосипед с тем же ООП (да еще и для каждого языка по новой)?

Вот это куда более интересно вопрос что называть языком или синтаксическим анализом.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[19]: Размышления о типизаторе для Н2
От: gbear Россия  
Дата: 28.06.11 02:41
Оценка: +1
Здравствуйте, VladD2, Вы писали:

VD>>>Вот это грубейшая ошибка. Н без иф-а не перестает быть Н.

WH>>Это у тебя каша в голове.
WH>>Это другой язык просто по определению.
WH>>Ибо он состоит из другого множества строк.
VD>

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

VD>>>Переписывание X в X делается тупым квази-цитированием. Переписывание, X в Y требует наличия кучи дополнительной информации (тех же типов и т.п.).

WH>>Ну-ну. Про foreach и компанию уже забыл?
VD>Нет не забыл. Главное, что при переписывания foreach не требуются новые понятия. Переписанных код — это код на все том же языке, а форыч не более чем сахар.

"Не требуются новые понятия" значит. Они _[не]новые_ относительно чего?

VD>Грубо говоря макрос переписывает код в тот же тип АСТ, а маппер отображает в другой. Причем, в первом случае это просто функция из АСТ в АСТ, а в другом конструкция позволяющая определить некий паттерн (набор веток АСТ) и на выходе порождающая тоже набор веток (одну или более), но уже другого языка.


Я правильно понимаю, что ты утверждаешь, что маппер это не "функция из АСТ в АСТ"?

VD>>>Базовый язык — это язык в котором нечего раскрывать.

WH>>Его не существует.
VD>Это у тебя каша в голове.

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

VD>Это у тебя каша в голове.
WH>>Они просто разрушают семантику друг друга.
VD>Это проблемы дизайна языка и типизации. Если конструкции не могут встречаться в одном выражении, то код типизации должен это проверить и выдать сообщение об ошибке. Если, может, то должны проверяться условия сосуществования.

А можно и мне тоже так:


WH>>Вот есть у нас макра LINQ это уже новый язык или еще нет?


VD>

VD>Нет. Это у тебя каша в голове. Это чистый сахар.

Влад, на самом деле _любой_ синтаксический макрос — _формально_ — определяет новый язык. Пусть сколь угодно малый и простой. Пусть. Но, таки, _новый_ (т.е. _другой_) язык. Выражений этого языка — их просто не существует в исходном. Вот и всё. А то, что выражения этого языка (определенного синтаксическим макросом) отображаются в выражения исходного языка — того, для которого этот "макрос" создан — абсолютно ничего не меняет.
Re[19]: Размышления о типизаторе для Н2
От: WolfHound  
Дата: 28.06.11 08:58
Оценка:
Здравствуйте, VladD2, Вы писали:

WH>>Это другой язык просто по определению.

WH>>Ибо он состоит из другого множества строк.
VD>
Знаю, знаю. Все лингвисты дебилы.

WH>>Повторной типизации не будет. Экспоненты тоже.

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

VD>Грубо говоря макрос переписывает код в тот же тип АСТ, а маппер отображает в другой.

А слабо формально?

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

VD>Это у тебя каша в голове.
Покажи, как ты собрался их совместить.

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

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

WH>>Про языки с другим вычислительным базисом и говорить нечего.

VD>Ну, вот и не будем.
И зря.

VD>

VD>Нет. Это у тебя каша в голове. Это чистый сахар.
Ну начнем с того что это другой язык по определению...

WH>>А PegGrammar?

VD>Нет.
Ох тыж блин. Это просто феерия.
Он имеет свою систему типов.
Свою вычислительную модель, не имеющую ничего общего с немерлом.
У него есть свои оптимизации, которые практически невозможно сделать, оставаясь в рамках немерла.
Он отличается от немерла сильнее, чем немерле от MSIL.
И после всего этого он не отдельный язык?
Что тогда можно назвать другим языком?
Формальное определение в студию.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[19]: Размышления о типизаторе для Н2
От: WolfHound  
Дата: 28.06.11 08:58
Оценка:
Здравствуйте, VladD2, Вы писали:

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

На который я уже дал ответ, но ты докопался до цвета пуговиц и даже не попытался понять суть.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[17]: Размышления о типизаторе для Н2
От: artelk  
Дата: 28.06.11 13:52
Оценка:
Здравствуйте, WolfHound, Вы писали:

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


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

WH>Паттерны проектирования это вообще зло.
WH>Люди, начитавшись про паттерны, начинают лепить их куда попало.
Так это не сами паттерны виноваты, что кто-то, начитавшись их, лепит их куда попало, а то, что их представляют как панацею от всех бед и, вместо того чтобы думать своей головой, пытаются навтыкать их побольше в код.
Паттерны — это просто примеры довольно удачных часто встречающихся решений часто встречающихся проблем дизайна при разработке приложений на распространенных объектно-ориентированных языках программирования . С другой стороны, их можно рассматривать как примеры следования принципам SOLID. Изучать и анализировать их очень полезно. Еще хорошо то, что у них есть название и можно просто сказать, например, "тут нужен адаптер" вместо того, чтобы рассказывать 20 минут, что ты имеешь ввиду. Конечно, вопрос типа "какой бы мне тут паттерн применить, чтоб все стало хорошо" — глупость. Но если ты придумал удачное решение и обнаружил, что получился адаптер или еще что известное, то можно сразу использовать это название — другим будет нужно меньше объяснять что да как.
WH>Вообще самый правильный способ решать задачу это сначала сделать язык под задачу, а потом на этом языке ее решить.
На каждый чих делать DSL тоже не вариант. С другой стороны, дизайн классов — это тоже некоторым образом язык и если для какой-то задачи уже имеющихся языковых средств достаточно, чтобы выразить решение лаконично и понятно, то DSL клепать смысла нет.

A>>Если язык удобно представить в виде "матрешки" (например: наднадъязык, надъязык и собственно язык), то семантика будет появляться при каждом переходе от внешнего языка к более детальному внутреннему, имхо.

WH>Матрешка это деталь реализации.
WH>Не более того.
WH>И в твоем случае терминология начинает плавать в зависимости от деталей реализации.
Ага, понятия "больше" и "меньше" не строго-научны, т.к. один и тот же объект является большим по отношению к одним объектам и меньшим к другим — т.е. зависит от того, с чем мы его на практике сравниваем.

Кодогенерация тоже не так чтобы формализованная вещь. По сути это преобразование одного языка в другой. А "язык" — это очень растяжимое понятие.
Уже тут:
identifier : Identifier = !keyword "@"? identifierBody s;
identifier( _at             : NToken,
            identifierBody  : VString) : Identifier
{
  Identifier(identifierBody.Value)
}

чем не преобразование языков?

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

WH>Куда пропадает?
Вот были у нас классы, методы, замыкания и еще куча высокоуровневой информации, а на выходе получили тупые машинные инструкции, массивы памяти и адреса. Причем декомпиляция даже не всегда однозначна.

A>>Родилось такое:

WH>Очень наивно.
WH>На практике все будет весьма иначе.
Заинтриговал
Re[20]: Размышления о типизаторе для Н2
От: VladD2 Российская Империя www.nemerle.org
Дата: 28.06.11 15:50
Оценка:
Здравствуйте, gbear, Вы писали:

VD>>>>Вот это грубейшая ошибка. Н без иф-а не перестает быть Н.

WH>>>Это у тебя каша в голове.
WH>>>Это другой язык просто по определению.
WH>>>Ибо он состоит из другого множества строк.
VD>>

G>Влад, а можно таки пояснить свои "смешки" для особо одаренных?


Это что-то вроде объяснения шутки. ОК, одаренность надо ценить.

Вообще-то я пытаюсь продемонстрировать хамящему товарищу его же стиль общения.

G>"Не требуются новые понятия" значит. Они _[не]новые_ относительно чего?


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

G>Я правильно понимаю, что ты утверждаешь, что маппер это не "функция из АСТ в АСТ"?


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

G>А можно и мне тоже так:


Валяй! Может созерцание своего "стиля" со стороны наведет WolfHound-а на мысль о том, что подобный стиль общения выглядит неприглядно.

G>Влад, на самом деле _любой_ синтаксический макрос — _формально_ — определяет новый язык.


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

G>Пусть сколь угодно малый и простой. Пусть.


А кому нужно такое определение? Оно так же полезно как определение синтаксиса по WolfHound. То есть — никак.

G>Но, таки, _новый_ (т.е. _другой_) язык.


О! Супер! "Новый" и "другой" у нас уже разные вещи.

G>Выражений этого языка — их просто не существует в исходном. Вот и всё.


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

G>А то, что выражения этого языка (определенного синтаксическим макросом) отображаются в выражения исходного языка — того, для которого этот "макрос" создан — абсолютно ничего не меняет.


Это для трепачей-теоретиков ничего не меняет. Хотя даже теоретику ясно, что трансформация одного языка в другой язык и замена терминов на их определения — это разные вещи.

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

При преобразовании в другой язык, напротив, в результате должна появиться иерархия другого языка. В этой иерархии не должно быть вхождений исходного языка. Из этого следует, что трансформация "язык -> язык" должна быть пакетной операцией. Кроме того, так как при подобных трансформациях мы имеем дело не с синтаксическим сахаром, может случиться так (и обязательно случится), что невозможно будет заменить одну ветку исходного языка на одну или более целевого (что нормально для макросов). Обязательно будут случаи когда нужно преобразовывать набор ветвей исходного языка. И тут подход макросов попросту не подойдет.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.