В данный момент грамматика Cx# хотя и разбита на несколько модулей представляет собой монолит.
Из-за того, что модули ссылаются друг на друга невозможно удалять/добавлять фичи языка независимо друг от друга.
За исключением модуля Linq который грамотно изолирован от остальной грамматики.
Поэтому предлагаю сделать модуль Core который будет выглядеть примерно вот так:
Остальные модули должны ссылаться на этот модуль и те модули от которых непосредственно зависят.
В каждом модуле должна быть строго одна фича.
Например
namespace CSharp
{
syntax module AsyncAwait
{
using CSharp.Core;
using CSharp.AnonymousFunction;
keyword regex ['A'..'Z', 'a'..'z', '_'..'_']+ rule S;
extend syntax Modifier
{
| AsyncMod = "async"sm;
}
extend syntax Expression
{
| Lambda_SingleParam2 = "async" sm Name sm "=>" sm AnonymousFunctionBody;
| Lambda_ExplicitParams2 = "async" sm ExplicitAnonymousFunctionSignature sm "=>" sm AnonymousFunctionBody;
| Lambda_ImplicitParams3 = "async" sm ImplicitAnonymousFunctionSignature sm "=>" sm AnonymousFunctionBody;
| AnonymousFunction2 = "async" sm "delegate"sm ExplicitAnonymousFunctionSignature? nl "{" inl Statement* d "}";
| Await = "await" sm Expression; // C# 5
}
}
}
1)Это позволит легко собрать разные версии C#.
2)Это позволит людям иметь в языке только нужные им фичи.
Например, есть две команды одна пишет ядро системы вторая прикладную логику.
Первой команде доверить мощный язык не страшно. А вторая набрана по объявлениям за дёшево.
Первая команда выкидывает из языка всё лишнее (goto, unsafe,...), добавляет в язык прикладные ДСЛ. И отдаёт этот язык второй команде.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, WolfHound, Вы писали:
WH>В данный момент грамматика Cx# хотя и разбита на несколько модулей представляет собой монолит. WH>Из-за того, что модули ссылаются друг на друга невозможно удалять/добавлять фичи языка независимо друг от друга. WH>За исключением модуля Linq который грамотно изолирован от остальной грамматики. WH>Поэтому предлагаю сделать модуль Core который будет выглядеть примерно вот так:... WH>... WH>Остальные модули должны ссылаться на этот модуль и те модули от которых непосредственно зависят.
Полностью согласен. Сделаешь?
WH>В каждом модуле должна быть строго одна фича.
Вот это, по-моему, перебор.
1. Не всегда можно выделить фичу. Многое очень связано.
2. На уровне базовых вещей (пространства имен, классы, мемберы) просто нечего выделять.
3. Я не уверен, что море совсем мелких модулей не выйдет боком. Не ясно что будет с производительностью.
На мой взгляд разделять надо так:
1. Основной модуль (Core) в котором описаны базовые вещи (как у тебя), пространства имен и типы. Он будет общий для Cx# и Nemerle.
2. Модуль в котором описаны члены типов (методы, свойства, ...). Он будет общим для отдельного языка.
3. Модуль с базовым набором стейтментов. Он будет общим для отдельного языка.
4. Модуль с базовым набором выражений. Он будет общим для отдельного языка.
5. По модулю на пересечение версии языка и модулей 2, 3, 4. Т.е. модуль членов для C#
Думаю, поддерживать C# версии 1.0 смысла не имеет. Стало быть за базовый берем 2.0 и добавляем модули для фич версий 4, 5, 6 и 7. Примерно как ты описал.
В общем, поинт в том, чтобы не дробить модули до одурения. Иначе можно дойти до того, что в модуле будет ровно одна продукция.
Далее, все что ты говоришь относится к грамматике. Но кроме грамматики есть и AST описывающий семантику. Его тоже надо подвергнуть декомпозиции. Причем надо учесть тот факт, что AST уже лежит в отдельном проекте используемом самоей Nitra-ой. В прочем, возможна для AST декомпозиция и не так актуальная, так как там применяется схема наследования и каждый тип узла AST относительно независим.
Еще один вопрос в том делать ли все в рамках одной dll (сборки) или разделить на разные? Ну, да этот вопрос можно и отложить.
В принципе можно даже оба языка (и Nemerle, и Cx#) иметь в одной сборке. Но с точки зрения времени компиляции это может оказаться не здорово.
Вообще, компиляция больших языков воде Nemerle и Cx# будет занимать не мало времени. Причем чем дальше будет продвигаться работа над ними, тем больше будет занимать компиляция.
Учитывая, что модульность у нас может быть и на уровне сборок, наверно надо разбить проект на сборки содержащие разрабатываемые фичи и на сборки содержащие устаканившиеся фичи. При разработке и отладке можно будет добавлять новые фичи в экспериментальную (назовем ее так) сборку и за счет большей интерактивности быстрее их отлаживать. Далее переносить фичи в основные сборки и тем самым фиксировать их.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Кстати, очень плохо, что это заклинание надо всюду пихать. Надо бы сделать какое-то умолчание для него. Оно ведь для всего языка подходит.
Здравствуйте, s22, Вы писали:
VD>>Кстати, очень плохо, что это заклинание надо всюду пихать. Надо бы сделать какое-то умолчание для него. Оно ведь для всего языка подходит.
s22>только не надо хардить.
Надо просто сделать возможность импортировать это дело из других модулей и заставлять вписывать только при неоднозначном импорте. Не факт, кстати, что это не так. Может Вольфхунд просто не проверил. Надо посмотреть или его спросить.
Тогда можно будет запихать это определение в модуль Core и он будет всегда импортироваться.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Полностью согласен. Сделаешь?
Сделаю.
VD>1. Не всегда можно выделить фичу. Многое очень связано.
Например?
VD>3. Я не уверен, что море совсем мелких модулей не выйдет боком. Не ясно что будет с производительностью.
Ничего.
В случае с расширяемыми правилами и регексами код будет идентичен.
В случае с простыми правилами в некоторых случаях могут быть небольшие накладные расходы в несколько тактов на вызов.
VD>На мой взгляд разделять надо так: VD>1. Основной модуль (Core) в котором описаны базовые вещи (как у тебя), пространства имен и типы. Он будет общий для Cx# и Nemerle.
Вариантов в C# нет.
Синтаксис енумов сильно различается.
И стейтментов в немерле тоже нет.
Так что не думаю, что общий получится.
VD>В общем, поинт в том, чтобы не дробить модули до одурения. Иначе можно дойти до того, что в модуле будет ровно одна продукция.
Не вижу в этом большой проблемы.
Возьмём, например, вот такой модуль:
namespace CSharp
{
syntax module Goto
{
using CSharp.Core;
extend syntax Statement
{
| Labeled = Name ":" sm Statement;
}
extend syntax EmbeddedStatement
{
| GotoCase = "goto" sm "case"sm ConstantExpression ";" nl;
| GotoDefault = "goto" sm "default" ";" nl;
| GotoId = "goto" sm Label=Reference ";" nl;
}
}
}
Думаю, найдется не мало людей, которые захотят его отключить.
VD>Далее, все что ты говоришь относится к грамматике. Но кроме грамматики есть и AST описывающий семантику. Его тоже надо подвергнуть декомпозиции.
1)Это подразумевается.
2)Это не критично. Ибо если нет синтаксиса, то вся остальная машинерия просто не будет работать.
VD>Учитывая, что модульность у нас может быть и на уровне сборок, наверно надо разбить проект на сборки содержащие разрабатываемые фичи и на сборки содержащие устаканившиеся фичи. При разработке и отладке можно будет добавлять новые фичи в экспериментальную (назовем ее так) сборку и за счет большей интерактивности быстрее их отлаживать. Далее переносить фичи в основные сборки и тем самым фиксировать их.
Можно и так.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, WolfHound, Вы писали:
VD>>1. Не всегда можно выделить фичу. Многое очень связано. WH>Например?
Ну, вот ты сам не плохой пример нашел со связями лямбд и асинков. Вот дробить до маразма не надо, на мой взгляд.
Кроме того, не забывай, что кроме синтаксиса есть еще семантика (АСТ с рассчетами). Там завязки не хилые порой.
Например, все что связано с типами я бы оставил едином месте. В прочем, так модулей нет, так что речь скорее про единую длл.
WH>В случае с простыми правилами в некоторых случаях могут быть небольшие накладные расходы в несколько тактов на вызов.
Как бы эти такты не вылились в десятки секунд и секунды. При восстановлении там все и так на грани. Плюс семантика тоже серьезное время жрет.
VD>>1. Основной модуль (Core) в котором описаны базовые вещи (как у тебя), пространства имен и типы. Он будет общий для Cx# и Nemerle. WH>Вариантов в C# нет.
Ну, вот их "за скобки" вынести, т.е. в специализированный модуль.
Потом это C# нет. А у нас то точно будут. На фиг нам нужен тупой клон C#?
В прочем, тут действительно сам Бог велел в отдельный модуль такие расширения выносить.
Я больше говорю о базе. В базе ведь довольно много разных операторов. Надо какую-то разумную гранулярность выбрать.
Вот, например, тот же linq ведь можно и еще на подмодули раздробить. Но надо ли?
WH>Синтаксис енумов сильно различается.
Синтаксис энумов различается не больше чем синтаксис классов. Все различия в мемберах. А вот само описание энума идентично.
Я говорю именно про описание самих типов.
Я бы сделал так... Описал бы Коре только базовый тип для членов и сами типы. А в специфичных модулях уже члены для Шарпа и Немерла по отдельности. Причем все члены для одного языка я бы поместил в единый модуль. Тут логично по версии шарпа их называть, потому как в шарпе 7, например, появляются метод без блоков:
int Foo() => 42;
Короче, общий принцип, наверно, лучше принять следующий: создаем модули не для отдельных подправил, а для более-менее крупных их блоков.
Например, мы можем вынести каждый оператор в отдельный модель. Но надо ли это делать?
Наверно лучше все операторы C# 2.0 оставить в отдельном модуле. А уже остальные разбивать оп фичам или по версиям языка.
Иначе у нас будет этих модулей 100500 и просто на поиск нужного правило будет тратиться много времени.
WH>И стейтментов в немерле тоже нет.
В принципе экспрешон-стейтмет есть. Хотя, конечно, случай вырожденный. Плюс в реальности любое void-выражение — это тоже стейтмент. Вот только выявить это, в общем случае, можно только при типизации. Так что надо разделять синтаксис и АСТ. В Синтаксисе Немерла стейтментов почти не будет, а вот в АСТ почему бы и нет?
Например, зачем нам два раза АСТ (и генерацию кода для него) для циклов писать? Так что на уровне АСТ, наверно, стейтменты нужно оставить. Просто при типизации немерловых выражений придется немного повозиться и вывести стейтмент ли это или выражение. Это и для последющих проверок будет проще. А то анализы в Немерле 1.х были ужасно нечитабельными.
По сути блок Немерла может содержать или одно выражение, или список стейтментов. Типизатор должен это вывести.
WH>Так что не думаю, что общий получится.
Ну, на уровне до тел типов уж точно можно. А там, как не странно, довольно много общей типизации получается. В прочем, синтаксиса не так уж много.
У меня вообще была мысль... А не объединить ли два языка в один? Можно будет прямо в коде Шарпа кусок немерла встроить и наоборот.
VD>>В общем, поинт в том, чтобы не дробить модули до одурения. Иначе можно дойти до того, что в модуле будет ровно одна продукция. WH>Не вижу в этом большой проблемы.
Ну, вот, например, зачем те же описания типов по отдельным правилам раскладывать? У них там в телах, все равно, много общего.
WH>Возьмём, например, вот такой модуль: WH> | GotoCase = "goto" sm "case"sm ConstantExpression ";" nl; WH> | GotoDefault = "goto" sm "default" ";" nl; WH> | GotoId = "goto" sm Label=Reference ";" nl;
Ну, goto может и можно выделить. А надо ли разделять разделять арифметику?
Или зачем выделять отдельные циклы?
WH>Думаю, найдется не мало людей, которые захотят его отключить.
goto — да. А вот то что найдется кто-то кто захочит отключить умножение отдельно от сложения и вычитания — это вряд ли.
Вот как бы критерий и должен быть — нужно ли это дело отдельно подключать или отключать.
VD>>Далее, все что ты говоришь относится к грамматике. Но кроме грамматики есть и AST описывающий семантику. Его тоже надо подвергнуть декомпозиции. WH>1)Это подразумевается.
Дык, там все немного не так как в случае с правилами. Там неймспейсы, а не модули. И связанность там совсем иная выходит.
WH>2)Это не критично. Ибо если нет синтаксиса, то вся остальная машинерия просто не будет работать.
Не понял. Куда он делся?
VD>>Учитывая, что модульность у нас может быть и на уровне сборок, наверно надо разбить проект на сборки содержащие разрабатываемые фичи и на сборки содержащие устаканившиеся фичи. При разработке и отладке можно будет добавлять новые фичи в экспериментальную (назовем ее так) сборку и за счет большей интерактивности быстрее их отлаживать. Далее переносить фичи в основные сборки и тем самым фиксировать их. WH>Можно и так.
Это точно надо сделать, иначе разработка будет очень тормозиться. Уже сейчас компиляция шарпа идет довольно долго. Когда стипизируются выражения и добавится Немерл, все будет еще печальнее.
Но на первом этапе надо завести компиляцию отдельного солюшена содержащего только то, что нужно для разработки языков.
Я его уже создал (Nitra.DotNet.Languages.sln), но там есть какие-то проблемы с обновлением нюгет-модулей и прожект-референсами на другие проекты Нитры. Надо с ними разобраться. Буду признательен, если ты это сделаешь, так как я тут вожусь с интеграцией для самой Нитры.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Ну, вот ты сам не плохой пример нашел со связями лямбд и асинков. Вот дробить до маразма не надо, на мой взгляд.
А я и не предлагаю до маразма.
Но в данном случае дробление оправдано.
VD>Кроме того, не забывай, что кроме синтаксиса есть еще семантика (АСТ с рассчетами). Там завязки не хилые порой.
А вот это уже не важно.
Если у нас парсер не пропустит некоторую конструкцию. То это всё равно что пользователь никогда её не использует.
А значит есть типизация для данной конструкции или нет не имеет значения.
Она никогда не будет использована.
Так что требования к модульности типизации и кодогенарации ниже чем к модульности парсера.
VD>Как бы эти такты не вылились в десятки секунд и секунды. При восстановлении там все и так на грани. Плюс семантика тоже серьезное время жрет.
Там такие мелочи что я даже обсуждать это не хочу. А уж в сравнении с восстановлением ты эту разницу даже в микроскоп не увидишь. Даже если будешь очень сильно стараться.
VD>Вот, например, тот же linq ведь можно и еще на подмодули раздробить. Но надо ли?
Не знаю.
VD>Например, мы можем вынести каждый оператор в отдельный модель. Но надо ли это делать?
Да я и не предлагал каждый оператор в отдельный модуль выносить.
VD>Например, зачем нам два раза АСТ (и генерацию кода для него) для циклов писать? Так что на уровне АСТ, наверно, стейтменты нужно оставить. Просто при типизации немерловых выражений придется немного повозиться и вывести стейтмент ли это или выражение. Это и для последющих проверок будет проще. А то анализы в Немерле 1.х были ужасно нечитабельными.
Лично я думаю, что лучше пойти обратным путём и на уровне типизации всё привести к выражениям.
Стейтмент тупо конвертировать в выражение, которое приводится к void.
VD>А надо ли разделять разделять арифметику? VD>Или зачем выделять отдельные циклы?
А я хоть раз это предлагал?
VD>Вот как бы критерий и должен быть — нужно ли это дело отдельно подключать или отключать.
Вот и нужно подумать какие фичи нужно изолировать в отдельные модули.
VD>Я его уже создал (Nitra.DotNet.Languages.sln), но там есть какие-то проблемы с обновлением нюгет-модулей и прожект-референсами на другие проекты Нитры. Надо с ними разобраться. Буду признательен, если ты это сделаешь, так как я тут вожусь с интеграцией для самой Нитры.
Я про мсбилд и нугет не знаю вообще ничего от слова совсем.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, WolfHound, Вы писали:
VD>>Ну, вот ты сам не плохой пример нашел со связями лямбд и асинков. Вот дробить до маразма не надо, на мой взгляд. WH>А я и не предлагаю до маразма. WH>Но в данном случае дробление оправдано.
Оправданно вынести асинк в отдельный модуль, а второй вариант, с дроблением на 3 модуля — нет, по-моему.
WH>Так что требования к модульности типизации и кодогенарации ниже чем к модульности парсера.
Наверно ты прав.
WH>Там такие мелочи что я даже обсуждать это не хочу. А уж в сравнении с восстановлением ты эту разницу даже в микроскоп не увидишь. Даже если будешь очень сильно стараться.
Будем наедятся. Иначе придется укрупнять.
VD>>Вот, например, тот же linq ведь можно и еще на подмодули раздробить. Но надо ли? WH>Не знаю.
А я уверен, что — нет.
WH>Да я и не предлагал каждый оператор в отдельный модуль выносить.
А где принцип по которому что-то надо выносить?
Можно ведь поступить очень просто. Разбить на модули по версиям C# и все. Разве что вынести goto и unsafe в отдельные модули.
WH>Лично я думаю, что лучше пойти обратным путём и на уровне типизации всё привести к выражениям.
У стейтментов своя логика. Сведя все к выражениям мы теряем определенную информацию. Ее, конечно, можно вывести из типов, но зачем усложнять?
WH>Стейтмент тупо конвертировать в выражение, которое приводится к void.
А потом словим проблему вроде проблемы последнего return-а в Nemerle 1.x.
Я тебе говорю. Это упростило бы анализ.
VD>>А надо ли разделять разделять арифметику? VD>>Или зачем выделять отдельные циклы? WH>А я хоть раз это предлагал?
Вот я и пытаюсь понять, что ты предлагаешь. Критериев четких не вижу.
WH>Я про мсбилд и нугет не знаю вообще ничего от слова совсем.
Надо же когда-то узнать? Я с нюгетом тоже "на Вы". Никогда не понимал почему эта хрень автоматически модули не сосет. Вроде в проекте рядом все сосется, а тут что-то пишет не ясное.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
WH>>Да я и не предлагал каждый оператор в отдельный модуль выносить. VD>А где принцип по которому что-то надо выносить?
То, что люди могут захотеть отключить. Включая устаревший синтаксис типа анонимных методов
Язык нужно чистить от старого синтаксиса.
Мы в отличии от микрософта это делать можем.
VD>У стейтментов своя логика. Сведя все к выражениям мы теряем определенную информацию. Ее, конечно, можно вывести из типов, но зачем усложнять?
Какая?
VD>А потом словим проблему вроде проблемы последнего return-а в Nemerle 1.x.
Я тебе ещё тогда показал простое и железно работающие решение.
Всё что нужно сделать это завести тип, который означает что выражение никогда не может быть вычислено. И такой тип уже есть. Он используется дли типизации throw.
Но ты же меня не слушаешь.
VD>Я тебе говорю. Это упростило бы анализ.
Не вижу в каком месте.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, WolfHound, Вы писали:
WH>То, что люди могут захотеть отключить. Включая устаревший синтаксис типа анонимных методов
Не захотят. Это домыслы. На практике люди захотят не иметь проблем при компиляции имеющегося кода. А в новом тупо могут не использовать фичу. Если это им для отслеживания стиля кодирования нужно, они скорее захотят анализатор выдающий предупреждения но пропускающие код.
WH>Язык нужно чистить от старого синтаксиса.
Язык у которого есть стандартизированный синтаксис чистить не стоит. Это только проблемы создаст.
VD>>У стейтментов своя логика. Сведя все к выражениям мы теряем определенную информацию. Ее, конечно, можно вывести из типов, но зачем усложнять? WH>Какая?
Последовательность операций. Одно дело когда у тебя операции хранятся как стейтменты и ты знаешь, что это именно последовательность, а другое когда у тебя список выражений. В списке выражений, например, не должно быть if-ов без else-ов. В списке стейтментов — спокойно. В случае стейтментов все ясно из структуры. В случае выражений нужно анализировать их тип. А тип он не всегда сразу доступен. Так что анализ усложняется. А от туда еще какая-то завязка появиться может.
VD>>А потом словим проблему вроде проблемы последнего return-а в Nemerle 1.x. WH>Я тебе ещё тогда показал простое и железно работающие решение.
А ты не рассказывай. Ты сядь и сделай. А если не можешь, то не рассказывай как все просто.
WH>Но ты же меня не слушаешь.
И не буду. У меня дел по горло.
VD>>Я тебе говорю. Это упростило бы анализ. WH>Не вижу в каком месте.
Тут пока до конкретных низов не спустишься большинство деталей не видно. Как говорится: Гладко было на бумаге, да забыли про овраги. (ц)
Прочувствовать чем отличается работа с типами, которые черт знает когда появляются и структурой явно выражающей смысл можно только на практике. В теории то оно однофигственно.
ЗЫ
Если ты хочешь отрефакторить C#-ные модули, то сделай, плиз, это в ближайшее время. Не затягивай.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Язык у которого есть стандартизированный синтаксис чистить не стоит. Это только проблемы создаст.
Например, в стандарте С++ есть конструкции которые во многих компиляторах по умолчанию выключены.
Их нужно специальным ключом включать.
VD>Последовательность операций. Одно дело когда у тебя операции хранятся как стейтменты и ты знаешь, что это именно последовательность, а другое когда у тебя список выражений. В списке выражений, например, не должно быть if-ов без else-ов. В списке стейтментов — спокойно. В случае стейтментов все ясно из структуры. В случае выражений нужно анализировать их тип. А тип он не всегда сразу доступен. Так что анализ усложняется. А от туда еще какая-то завязка появиться может.
Звучит как полная чушь.
if без else просто выражение которое возвращает void.
Все выражения в списке выражений нужно тупо последовательно вычислить.
Если выражение кроме последнего возвращает не void выдать предупреждение что значение теряется и проигнорировать значение.
Типом и значением списка выражений является тип и значение последнего выражения.
Всё.
VD>А ты не рассказывай. Ты сядь и сделай. А если не можешь, то не рассказывай как все просто. VD>И не буду. У меня дел по горло.
Ты с этой задачей справишься в десятки раз быстрее чем я просто по тому что ты знаешь, как компилятор немерла работает, а я нет.
И если я захочу залезть в сложный код я лучше парсер нитры улучшу.
VD>Прочувствовать чем отличается работа с типами, которые черт знает когда появляются и структурой явно выражающей смысл можно только на практике. В теории то оно однофигственно.
Типы они не чёрт знает, когда появляются, а после типизации и до кодогенерации.
То, что в немерле эти фазы чёрт знает, как перемешаны это проблема немерла.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, WolfHound, Вы писали:
WH>Например, в стандарте С++ есть конструкции которые во многих компиляторах по умолчанию выключены. WH>Их нужно специальным ключом включать.
1. Мы не занимаемся С++.
2. Даже в его случае отключать разбор части синтаксиса — это плохое решение. В таком случае нужно вводить дополнительные проверки. Если использована такая-то конструкция и не включен такая-то опция, надо выдать сообщение об ошибке в котором объяснить, что проходит.
WH>Звучит как полная чушь.
Для тебя.
WH>if без else просто выражение которое возвращает void.
А мы не знаем, что оно возвращает на стадии парсинга и мапинга. Это знание появится только после типизации. А очень даже может статья, что имея эту информацию заранее, можно будет сделать что-то оптимальнее и упростить себе работу.
В Немерле 1 это сплошь и рядом. Сначала информация теряется, а кода она восстанавливается аналитическим путем, уже поздно.
WH>Все выражения в списке выражений нужно тупо последовательно вычислить.
1. Не всегда бывают списки. Иногда это одно выражение. В Шарпе мы точно знаем его суть. Нам не надо превращать if в тернарный оператор, а потом аналитическим путем его восстанавливать в if.
2. Кроме вычисления (которое, вообще-то, не требуется) нам еще надо делать проверки. Имея информацию о том, что это мы можем сделать проверки раньше. Это может повлиять на вывод типов и т.п.
WH>Если выражение кроме последнего возвращает не void выдать предупреждение что значение теряется и проигнорировать значение.
Вт тут начинаются нюансы. В Шарпе оно игнорируется, а в Немерле выдется предупреждение о потере значений. А в каком-нибудь другом языке предупреждение зависит от того является ли функция чистой (pure).
Далее в Шарпе никакое выражение не может вернуть значение из блока. Это может быть сделано только return-ом. И блок не может иметь тип и быть выражением. В Немреле все наоборот. Любой блок возвращает значение и имеет тип.
Стало быть имеем проблему можно ли включать блок в другое выражение.
На уровне АСТа вся эта инфа будет теряться и ее можно будет только восстанавливать аналитическим путем после типизации. А это требует дополнительных обходов АСТ-а Посетитилями, т.е. — гимор.
Ну, а имея инфу заранее можно все проверки сделать при типизации.
И главное, что ты опять пытаешься заранее предсказать все детали. А это невозможно. Их слишком много. Логика обстоятельств всегда сильнее.
VD>>А ты не рассказывай. Ты сядь и сделай. А если не можешь, то не рассказывай как все просто. VD>>И не буду. У меня дел по горло. WH>Ты с этой задачей справишься в десятки раз быстрее чем я просто по тому что ты знаешь, как компилятор немерла работает, а я нет.
Я не справлюсь. Я считаю ее довольно сложной и довольно не нужной, чтобы решать. А у тебя всегда так. На словах все просто, а на деле упираешься в мелочь и не можешь ее преодолеть. Ты не знаешь сколько всего и как там завязано. Меняя одно ты нарываешься на другое.
Так что уж извини, но тот кто считает, что это просто, тот пусть и делает. А мне проще удалить ретурн в конце.
Точно так же у тебя будет все просто когда сначала потеряешь информацию, а потом окажется, что это создает ряд других проблем.
WH>Типы они не чёрт знает, когда появляются, а после типизации и до кодогенерации.
Ну, вот казалось бы те же паттерны можно было бы сильно упростить выводя тип сплайсов, но на практике оказывается, что работать с квази-цитатами проще до типизации и все теоретические рассуждения идут лесом.
В общем, на бумаге всегда просто. Просто потому, что на бумаге овраги не видны.
WH>То, что в немерле эти фазы чёрт знает, как перемешаны это проблема немерла.
Да дел не в фазах. Там анализ идет в самом конце, когда уже вся информация есть. Только и код уже сгенерирован, и анализ приходится делать не локальный, а глобальный. И в этом анализе черт ногу сломит. По сему если можно сделать как-то проще, то лучше сразу делать так. Ну, при отсутствии прочих аргументов.
Сложность такая штука противная. Она складывается и даже умножается. И не все что в теории возможно (и даже кажется разумным) на практике осуществимо.
В общем, надо поэкспериментировать. Мне кажется, идея не терять информацию может дать более простое решение.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.