Рефакторинг Cx#
От: WolfHound  
Дата: 16.01.17 23:09
Оценка: +1
В данный момент грамматика Cx# хотя и разбита на несколько модулей представляет собой монолит.
Из-за того, что модули ссылаются друг на друга невозможно удалять/добавлять фичи языка независимо друг от друга.
За исключением модуля Linq который грамотно изолирован от остальной грамматики.
Поэтому предлагаю сделать модуль Core который будет выглядеть примерно вот так:
namespace CSharp
{
  syntax module Core
  {
    using Nitra.Core;
    using Nitra.CStyleComments;

    using CSharp.TokenNames;

    keyword regex ['A'..'Z', 'a'..'z', '_'..'_']+ rule S;

    [StartRule]
    syntax CompilationUnit = NamespaceMemberDeclaration* !Any;

    extend token IgnoreToken
    {
      | [SpanClass(InlineComment),    ExplicitSpaces] Preprocessor = Start='#' Body=(!NewLineCharacter Any)* End=NewLine?;
    }

    syntax Block    = nl "{" inl Statement* d "}" nl;

    syntax Statement
    {
      | EmbeddedStatement;
    }

    syntax EmbeddedStatement
    {
      | Empty       = ";" nl;
      | Block;
      | ExpressionStatement = Expression ";" nl;
    }

    [DynamicSyntaxExtentionPoint]
    syntax NamespaceMemberDeclaration
    {
    }

    syntax Modifiers = Modifier*;

    syntax Modifier
    {
    }
  }
}

Остальные модули должны ссылаться на этот модуль и те модули от которых непосредственно зависят.
В каждом модуле должна быть строго одна фича.
Например
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
    }
  }
}


namespace CSharp
{
  syntax module Unsafe
  {
    using CSharp.Core;

    keyword regex ['A'..'Z', 'a'..'z', '_'..'_']+ rule S;

    extend syntax Modifier
    {
      | Unsafe    = "unsafe"sm;
    }

    extend syntax Expression
    {
      | StackallocInitializer  = "stackalloc"sm AnyType "[" Expression "]"; // unsafe

      precedence Unary:
      | Addressof              = "&"  Expression;// unsafe
    }

    extend syntax EmbeddedStatement
    {
      | Unsafe      = "unsafe" Block; // unsafe
      | Fixed       = "fixed" sm "(" LocalVariableType sm VariableDeclarators ")"nl IndentedEmbeddedStatement; // unsafe
    }
  }
}

И так далее.

1)Это позволит легко собрать разные версии C#.
2)Это позволит людям иметь в языке только нужные им фичи.
Например, есть две команды одна пишет ядро системы вторая прикладную логику.
Первой команде доверить мощный язык не страшно. А вторая набрана по объявлениям за дёшево.
Первая команда выкидывает из языка всё лишнее (goto, unsafe,...), добавляет в язык прикладные ДСЛ. И отдаёт этот язык второй команде.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Отредактировано 17.01.2017 6:31 VladD2 . Предыдущая версия .
Re: Рефакторинг Cx#
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.01.17 08:31
Оценка:
Здравствуйте, 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# будет занимать не мало времени. Причем чем дальше будет продвигаться работа над ними, тем больше будет занимать компиляция.

Учитывая, что модульность у нас может быть и на уровне сборок, наверно надо разбить проект на сборки содержащие разрабатываемые фичи и на сборки содержащие устаканившиеся фичи. При разработке и отладке можно будет добавлять новые фичи в экспериментальную (назовем ее так) сборку и за счет большей интерактивности быстрее их отлаживать. Далее переносить фичи в основные сборки и тем самым фиксировать их.
http://nemerle.org/Banners/?g=dark
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Рефакторинг Cx#
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.01.17 08:33
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>
WH>    keyword regex ['A'..'Z', 'a'..'z', '_'..'_']+ rule S;
WH>


Кстати, очень плохо, что это заклинание надо всюду пихать. Надо бы сделать какое-то умолчание для него. Оно ведь для всего языка подходит.
http://nemerle.org/Banners/?g=dark
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Рефакторинг Cx#
От: s22  
Дата: 17.01.17 08:34
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Кстати, очень плохо, что это заклинание надо всюду пихать. Надо бы сделать какое-то умолчание для него. Оно ведь для всего языка подходит.


только не надо хардить.
Re[3]: Рефакторинг Cx#
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.01.17 08:52
Оценка:
Здравствуйте, s22, Вы писали:

VD>>Кстати, очень плохо, что это заклинание надо всюду пихать. Надо бы сделать какое-то умолчание для него. Оно ведь для всего языка подходит.


s22>только не надо хардить.


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

Тогда можно будет запихать это определение в модуль Core и он будет всегда импортироваться.
http://nemerle.org/Banners/?g=dark
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Рефакторинг Cx#
От: WolfHound  
Дата: 17.01.17 19:16
Оценка:
Здравствуйте, 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) А. Эйнштейн
Re[3]: Рефакторинг Cx#
От: VladD2 Российская Империя www.nemerle.org
Дата: 18.01.17 09:23
Оценка:
Здравствуйте, 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), но там есть какие-то проблемы с обновлением нюгет-модулей и прожект-референсами на другие проекты Нитры. Надо с ними разобраться. Буду признательен, если ты это сделаешь, так как я тут вожусь с интеграцией для самой Нитры.
http://nemerle.org/Banners/?g=dark
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Рефакторинг Cx#
От: WolfHound  
Дата: 18.01.17 20:46
Оценка:
Здравствуйте, 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) А. Эйнштейн
Re[5]: Рефакторинг Cx#
От: VladD2 Российская Империя www.nemerle.org
Дата: 19.01.17 08:56
Оценка:
Здравствуйте, 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>Я про мсбилд и нугет не знаю вообще ничего от слова совсем.


Надо же когда-то узнать? Я с нюгетом тоже "на Вы". Никогда не понимал почему эта хрень автоматически модули не сосет. Вроде в проекте рядом все сосется, а тут что-то пишет не ясное.
http://nemerle.org/Banners/?g=dark
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: Рефакторинг Cx#
От: s22  
Дата: 19.01.17 12:27
Оценка:
Здравствуйте, VladD2, Вы писали:


Кстати, типизатор без переделки сможет поддерживать зависимые типы?
Re[7]: Рефакторинг Cx#
От: VladD2 Российская Империя www.nemerle.org
Дата: 19.01.17 15:27
Оценка:
Здравствуйте, s22, Вы писали:

s22>Кстати, типизатор без переделки сможет поддерживать зависимые типы?


Может.
http://nemerle.org/Banners/?g=dark
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: Рефакторинг Cx#
От: WolfHound  
Дата: 20.01.17 20:49
Оценка:
Здравствуйте, VladD2, Вы писали:

WH>>Да я и не предлагал каждый оператор в отдельный модуль выносить.

VD>А где принцип по которому что-то надо выносить?
То, что люди могут захотеть отключить. Включая устаревший синтаксис типа анонимных методов
      | AnonymousFunction1     =            "delegate"sm ExplicitAnonymousFunctionSignature? nl "{" inl Statement* d "}";


Язык нужно чистить от старого синтаксиса.
Мы в отличии от микрософта это делать можем.

VD>У стейтментов своя логика. Сведя все к выражениям мы теряем определенную информацию. Ее, конечно, можно вывести из типов, но зачем усложнять?

Какая?

VD>А потом словим проблему вроде проблемы последнего return-а в Nemerle 1.x.

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

VD>Я тебе говорю. Это упростило бы анализ.

Не вижу в каком месте.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[7]: Рефакторинг Cx#
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.01.17 22:49
Оценка:
Здравствуйте, WolfHound, Вы писали:

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


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

WH>Язык нужно чистить от старого синтаксиса.


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

VD>>У стейтментов своя логика. Сведя все к выражениям мы теряем определенную информацию. Ее, конечно, можно вывести из типов, но зачем усложнять?

WH>Какая?

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

VD>>А потом словим проблему вроде проблемы последнего return-а в Nemerle 1.x.

WH>Я тебе ещё тогда показал простое и железно работающие решение.

А ты не рассказывай. Ты сядь и сделай. А если не можешь, то не рассказывай как все просто.

WH>Но ты же меня не слушаешь.


И не буду. У меня дел по горло.

VD>>Я тебе говорю. Это упростило бы анализ.

WH>Не вижу в каком месте.

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

ЗЫ

Если ты хочешь отрефакторить C#-ные модули, то сделай, плиз, это в ближайшее время. Не затягивай.
http://nemerle.org/Banners/?g=dark
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: Рефакторинг Cx#
От: WolfHound  
Дата: 21.01.17 01:29
Оценка:
Здравствуйте, VladD2, Вы писали:

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

Например, в стандарте С++ есть конструкции которые во многих компиляторах по умолчанию выключены.
Их нужно специальным ключом включать.

VD>Последовательность операций. Одно дело когда у тебя операции хранятся как стейтменты и ты знаешь, что это именно последовательность, а другое когда у тебя список выражений. В списке выражений, например, не должно быть if-ов без else-ов. В списке стейтментов — спокойно. В случае стейтментов все ясно из структуры. В случае выражений нужно анализировать их тип. А тип он не всегда сразу доступен. Так что анализ усложняется. А от туда еще какая-то завязка появиться может.

Звучит как полная чушь.
if без else просто выражение которое возвращает void.
Все выражения в списке выражений нужно тупо последовательно вычислить.
Если выражение кроме последнего возвращает не void выдать предупреждение что значение теряется и проигнорировать значение.
Типом и значением списка выражений является тип и значение последнего выражения.
Всё.

VD>А ты не рассказывай. Ты сядь и сделай. А если не можешь, то не рассказывай как все просто.

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

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

Типы они не чёрт знает, когда появляются, а после типизации и до кодогенерации.
То, что в немерле эти фазы чёрт знает, как перемешаны это проблема немерла.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[9]: Рефакторинг Cx#
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.01.17 16:53
Оценка:
Здравствуйте, 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>То, что в немерле эти фазы чёрт знает, как перемешаны это проблема немерла.


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

Сложность такая штука противная. Она складывается и даже умножается. И не все что в теории возможно (и даже кажется разумным) на практике осуществимо.

В общем, надо поэкспериментировать. Мне кажется, идея не терять информацию может дать более простое решение.
http://nemerle.org/Banners/?g=dark
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.