Размышления о типизаторе для Н2
От: WolfHound  
Дата: 31.05.11 14:54
Оценка: 10 (1)
Сразу оговорюсь, что я считаю схему
Автор: VladD2
Дата: 21.05.11
предложенную Владом неадекватно переусложненной и крайне не гибкой.
Поэтому я не буду делить AST на AST, SST, TSST, TAST.
У меня будет AST это то что выдает парсер и TAST это то что получается при типизации AST.

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

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

Также нужно не забыть про "многослойные" системы типов.
Это нужно, например для:
http://scholar.google.com/scholar?q=type+refinements+programming

Вывод типов производится в два этапа.
Сначала выводятся основные типы.
Потом "рафинированные".

2)Описание поиска имен.
Весь поиск имен во всех языках, которые я помню сводиться к очень простой схеме:
а) Поиск имени в иерархии областей видимости.
Смотрим в текущей области. Если не нашли, поднимаемся этажом выше. И так пока не найдем или не достигнем последней области видимости.

Требование объявления перед использованием решается заведением новой области видимости при объявлении переменной.

б) Доступ к члену объекта/пространства имен/...

3)Собственно язык описания правил вывода типов.
Мои мысли в данный момент крутяться вокруг Mercury.
Несколько упрощенный Mercury будет отличной основой для создания языка описания типизации.
Я выбрал Mercury ибо типизация это поиск с откатами. Как раз то вокруг чего построен этот язык.
Пролог пошёл лесом, ибо Mercury это пролог сделанный правильно.

Примеры пойдут ответами на это сообщение.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re: Размышления о типизаторе для Н2
От: catbert  
Дата: 31.05.11 15:00
Оценка:
А я думал, Н2 будет просто отрефакторенный Н1.
Re[2]: Размышления о типизаторе для Н2
От: hardcase Пират http://nemerle.org
Дата: 31.05.11 15:03
Оценка: :))
Здравствуйте, catbert, Вы писали:

C>А я думал, Н2 будет просто отрефакторенный Н1.


Нет. Отрефакторенный N1 будет называеться N1.5 (т.е. без полторашки не разобраться).
/* иЗвиНите зА неРовнЫй поЧерК */
Re: Размышления о типизаторе для Н2
От: WolfHound  
Дата: 31.05.11 16:18
Оценка: 51 (1)
Здравствуйте, WolfHound, Вы писали:

В общем случае одному типу АСТ могут соответствовать несколько разных типов ТАСТ.
Наиболее яркий пример это ComputationExpressions. Там кроме стандартного использования через билдер могут быть и более тесно интегрированные решения. В частности array, list, enumerable, async,... Но об этом в другой раз.

Начем с простенького:
abstract ast Expression;

ast If : Expression
{
    syntax "if" "(" condition ")" trueExpression "else" falseExpression;
    condition       : Expression;
    trueExpression  : Expression;
    falseExpression : Expression;
}


Теперь заведем вспомогательные предикаты.
Эти и еще куча других предикатов будут в стандартной поставке.
pred ConvertibleTo(from : Type, itemType : Type)
mode (in, in) is semidet //Проверяет что один тип приводим к другому.
mode (in, out) is multi  //При помощи бектрекинга перебирает все типы к которым можно привести данный.
//multi по пому что тип как минимум можно привести к самому себе.
//Так что хоть один результат да будет.
//Реализацию выдумавать лень.

//Пытается найти тип к которому можно привести все типы из списка.
pred Unify(types : list[Type], result : Type)
mode (in, out) is semidet


abstract tast TypedExpression
for Expression//Сообщаем системе какой узел ast типизировать данным tast
{
    ExpressionType : out Type;
}

tast TypedIf : TypedExpression
for If
{
    trueType      = trueExpression.ExpressionType;//Локальные переменные.
    falseType     = falseExpression.ExpressionType;//Для краткости.
    conditionType = condition.ExpressionType;
    
    ConvertibleTo(conditionType, type(bool))
        @@@ $"Type of condition must be convertible to bool. But $(conditionType) not convertible to bool." condition.Location;

    Unify([trueType, falseType], ExpressionType)
        @@@ $"Typef of branches must be competible. $trueType and $falseType incompatible" this.Location;
}
rewrite//Понижение уровня языка.
//В режиме ИДЕ никогда не выполняется.
{
    <[
        match ($condition)
        {
            | true  => $trueExpression;
            | false => $falseExpression;
        }
    ]>
}

После @@@ сообщение об ошибке которое показывается, если данное правило обламалось.

rewrite может генерировать недотипизированный АСТ.
В этом случае производится локальная дотипизация.
Если она выявила ошибки, то они считаются ошибками реализации и доводятся до пользователя с соответствующей пометкой.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[2]: Размышления о типизаторе для Н2
От: catbert  
Дата: 31.05.11 16:54
Оценка:
Здравствуйте, WolfHound, Вы писали:

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


WH>В общем случае одному типу АСТ могут соответствовать несколько разных типов ТАСТ.

WH>Наиболее яркий пример это ComputationExpressions. Там кроме стандартного использования через билдер могут быть и более тесно интегрированные решения. В частности array, list, enumerable, async,... Но об этом в другой раз.

WH>Теперь заведем вспомогательные предикаты.

WH>Эти и еще куча других предикатов будут в стандартной поставке.


WH>rewrite может генерировать недотипизированный АСТ.

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

А что тут, собственно, делается?
Re[3]: Размышления о типизаторе для Н2
От: WolfHound  
Дата: 31.05.11 16:58
Оценка:
Здравствуйте, catbert, Вы писали:

C>А что тут, собственно, делается?

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

C>>А что тут, собственно, делается?

WH>Парсится и типизируется выражение if.

Ужас! Такую регрессию никто не оценит.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: Размышления о типизаторе для Н2
От: WolfHound  
Дата: 31.05.11 17:25
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Ужас! Такую регрессию никто не оценит.

Какую регрессию?
Все что добавилось по сравнению с твоим подходом это нормальные сообщения об ошибках.
В прочем если хочешь получать мутные сообщения в стиле Н1 можно все сильно сократить.
tast TypedIf : TypedExpression
for If
{
    ConvertibleTo(condition.ExpressionType, type(bool));
    Unify([trueExpression.ExpressionType, falseExpression.ExpressionType], ExpressionType);
}

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

Потом сравнивать на наномакросе не имеет смысла.
Подожди пока я до foreach дойду.

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

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

Сразу оговорюсь, что оценка не за решение, а за то, что оно наконец то озвучено.

WH>
WH>abstract tast TypedExpression
WH>for Expression//Сообщаем системе какой узел ast типизировать данным tast
WH>{
WH>    ExpressionType : out Type;
WH>}

WH>tast TypedIf : TypedExpression
WH>for If
WH>{
WH>    trueType      = trueExpression.ExpressionType;//Локальные переменные.
WH>    falseType     = falseExpression.ExpressionType;//Для краткости.
WH>    conditionType = condition.ExpressionType;
    
WH>    ConvertibleTo(conditionType, type(bool))
WH>        @@@ $"Type of condition must be convertible to bool. But $(conditionType) not convertible to bool." condition.Location;

WH>    Unify([trueType, falseType], ExpressionType)
WH>        @@@ $"Typef of branches must be competible. $trueType and $falseType incompatible" this.Location;
WH>}
WH>rewrite//Понижение уровня языка.
WH>//В режиме ИДЕ никогда не выполняется.
WH>{
WH>    <[
WH>        match ($condition)
WH>        {
WH>            | true  => $trueExpression;
WH>            | false => $falseExpression;
WH>        }
WH>    ]>
WH>}
WH>

WH>После @@@ сообщение об ошибке которое показывается, если данное правило обламалось.

Здорово! Но какие проблемы (по сравнению с имеющимся подходом) решает эта куча кода? Я вижу только одну проблему — улучшение качества сообщений об ошибках.

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

Текущий путь — подстановка уточнения типа — приводит к не очень информативному сообщению.

Если убрать идеологические предрассудки, то решение этого должно быть простым, прямолинейным и удобным, а значит декларативным. Я бы описал этот макрос так:
macro If : Expression // по умолчанию типы параметров совпадающие с типом возвращаемого значения можно опускать
  syntax "if" "(" condition ")" trueExpr "else" falseExpr;
  // задаем условие на тип одного из параметров макроса
  requires condition.Type is bool otherwise Error(condition, "the expression cannot be converted to a 'bool'")
{
  <[
    match ($condition)
    {
      | true  => $trueExpr;
      | false => $falseExpr; // второе сообщение получается в результате типизации выражений в рамках match-а
    }
  ]>
}


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

WH>rewrite может генерировать недотипизированный АСТ.


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

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

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

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

Приведи, плиз, пример макроса которому нужна типизация на стадии SST. Только чтобы она действительно была нужна (чтобы без нее нельзя было обойтись).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: Размышления о типизаторе для Н2
От: WolfHound  
Дата: 31.05.11 17:35
Оценка:
Здравствуйте, WolfHound, Вы писали:

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

WH>Твой подход на такое принципиально не способен.
Правда для foreach нужно еще кое что придумать.
Я ща if расширю:
Пример совершенно бредовый но просто демонстрация.
tast TypedStringIf : TypedExpression
for If
{
    trueType      = trueExpression.ExpressionType;//Локальные переменные.
    falseType     = falseExpression.ExpressionType;//Для краткости.
    conditionType = condition.ExpressionType;

    ConvertibleTo(conditionType, type(string))
        @@@ $"Type of condition must be convertible to string. But $conditionType not convertible to string." condition.Location;

    Unify([trueType, falseType], ExpressionType)
        @@@ $"Typef of branches must be competible. $trueType and $falseType incompatible" this.Location;
}
rewrite
{
    <[
        match ($condition)
        {
            | null | "" => $falseExpression;
            | _         => $trueExpression;
        }
    ]>
}
//задаем приоритет нашему расширению меньше чем стандартному if'у.
order TypedStringIf < TypedIf;

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

WH>Теперь заведем вспомогательные предикаты.

WH>Эти и еще куча других предикатов будут в стандартной поставке.
WH>
WH>pred ConvertibleTo(from : Type, itemType : Type)
WH>mode (in, in) is semidet //Проверяет что один тип приводим к другому.
WH>mode (in, out) is multi  //При помощи бектрекинга перебирает все типы к которым можно привести данный.
WH>//multi по пому что тип как минимум можно привести к самому себе.
WH>//Так что хоть один результат да будет.
WH>//Реализацию выдумавать лень.

WH>//Пытается найти тип к которому можно привести все типы из списка.
WH>pred Unify(types : list[Type], result : Type)
WH>mode (in, out) is semidet
WH>


Вот это вот вообще не понятно. "semidet" так просто какое-то шифрование. Что это значит то?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Размышления о типизаторе для Н2
От: WolfHound  
Дата: 31.05.11 17:49
Оценка:
Здравствуйте, VladD2, Вы писали:

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

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


VD>Все эти навороты с rewrite, tast, for и т.п. — это никому не нужная пурга которая превратит написание макросов в сущий ад.

Ад это то, что сейчас и то, что предлагаешь ты.
Сейчас компилятор не предлагает никаких механизмов для создания чего-то сложнее, чем if.
В твоем решении их тоже нет.
Совсем.

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

Не сделает.

VD>Приведи, плиз, пример макроса которому нужна типизация на стадии SST.

foreach, lock, ?.,...

VD>Только чтобы она действительно была нужна (чтобы без нее нельзя было обойтись).

Нет таких. Ибо макросы полны по Тьюрингу и с помощью такойто матери можно сделать что угодно.
Но я не хочу кучу возни на ровном месте.
Вот тебе ярчайший пример твоего подхода:
  macro @?. (expr1, expr2)
  {
    def makeMemberAccess(loc, n) { PExpr.Member(loc,  <[ e1 ]>, Splicable.Name(loc, n)) }
    def makeComplation  (loc, n) { PExpr.Member(loc,  <[ e1 ]>, Splicable.HalfId(loc, n)) }
    def loc = expr2.Location;
    def e2 = 
      match (expr2)
      {
        | Ref(n)                    => makeMemberAccess(loc, n)
        | Call(Ref(n), parms)       => PExpr.Call(loc, makeMemberAccess(loc, n), parms)
        | Indexer(Ref(n), parms)    => PExpr.Indexer(loc, makeMemberAccess(loc, n), parms)
        | ToComplete(n)             => makeComplation(loc, n)
        | Call(ToComplete(n), _)    => makeComplation(loc, n)
        | Indexer(ToComplete(n), _) => makeMemberAccess(loc, n)
        | _ => Message.FatalError(expr2.Location, $"The expression of this ($(expr2.GetType())) type not supported with operator '?.'");
      };

    <[ 
      def e1 = $expr1;
      
      if (e1 == null)
        $(Typedtree.TExpr.DefaultValue() : typed)
      else
        $e2
    ]>
  }

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

VD>Вот это вот вообще не понятно. "semidet" так просто какое-то шифрование. Что это значит то?

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

WH>tast TypedIf : TypedExpression

WH>for If
WH>{
WH> trueType = trueExpression.ExpressionType;//Локальные переменные.
WH> falseType = falseExpression.ExpressionType;//Для краткости.
WH> conditionType = condition.ExpressionType;

WH> ConvertibleTo(conditionType, type(bool))

WH> @@@ $"Type of condition must be convertible to bool. But $(conditionType) not convertible to bool." condition.Location;

WH> Unify([trueType, falseType], ExpressionType)

WH> @@@ $"Typef of branches must be competible. $trueType and $falseType incompatible" this.Location;
WH>}

А как это дело вяжется с выводом типов? Ты еще не забыл, что типы невозможно вывести за один проход?

Вот даже если взять приведенный тобой (казалось бы простой!) код, то в нем уже заложена ошибка! Почему? Да потому, что некоторые языки (Немерл, Шарп, Васки...) используют неявное приведение типов. Ты тут используешь унификацию, но она не пройдет для всех случаев. Предположим что в trueExpression попало выражение типа A, а falseExpression типа B. Эти типы не унифицируются, так как у них нет общего предка за исключением object! Но для в типе B объявлен оператор неявного приведения типов (:>). Реальный код компилятора делает анализ всех возможных ситуаций и в случае необходимости меняет код получаемый в результате типизации. В данном случае для сочетания типов A и B будет добавлен вызов функции приведения типов (A к B).

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

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

Как будет выглядит типизация вызова функции в условиях поддержки языком перегрузки? Мы это тоже заставим делать "пациента"?

WH>rewrite//Понижение уровня языка.

WH>//В режиме ИДЕ никогда не выполняется.

А что будем делать с linq который кроме как через такое переписываиние никак не реализуется? Ведь без переписывания мы не сможем вычислить правильны тип. Прочитай внимательно спецификацию C# 3.0:

26.7.1 Query expression translation

The C# 3.0 language does not specify the exact execution semantics of query expressions. Rather, C# 3.0 translates query expressions into invocations of methods that adhere to the query expression pattern. Specifically, query expressions are translated into invocations of methods named Where, Select, SelectMany, OrderBy, OrderByDescending, ThenBy, ThenByDescending, and GroupBy that are expected to have particular signatures and result types, as described in §26.7.2. These methods can be instance methods of the object being queried or extension methods that are external to the object, and they implement the actual execution of the query.

The translation from query expressions to method invocations is a syntactic mapping that occurs before any type binding or overload resolution has been performed. The translation is guaranteed to be syntactically correct, but it is not guaranteed to produce semantically correct C# code. Following translation of query expressions, the resulting method invocations are processed as regular method invocations, and this may in turn uncover errors, for example if the methods do not exist, if arguments have wrong types, or if the methods are generic and type inference fails.
The translation of query expressions is demonstrated through a series of examples in the following. A formal description of the translation rules is provided in a later section.


Таким образом твое предложение не проходит критики даже при не глубоком изучении.

Предлагаю пойти другим путем.

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

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

На мой взгляд, более реалистичной идеей является идея декларативного указания компилятору необходимости типизировать отдельные части SST путем их раскрытия в AST и стандартной типизации. Вычисленные таким образом типы могут помещаться в SST (вместе со ссылками на произведенные AST и TAST) и могут использоваться внутри макросов.

В этой схеме макрос делится на две стадии. При парсинге всегда порождается SST. SST порожденное макросом закладывается в общее дерево проекта. При этом ветки SST помещается в специальные ветки-обертки AST. Когда типизиатор доходит до типизации таких веток, запускается код макроса (тот что находится внутри тела). При этом анализируются декларативные предикаты (вроде requires приведенный мною здесь) и, если надо, производится предварительная типизация отдельных параметров макросов. Это может изменять порядок типизации.

В общем, моя основная мысль очень проста. Вместо того чтобы выдумывать какие-то новые схемы типизации (не выдерживающие критики) лучше осмыслить ошибки текущего дизайна и сделать новый дизайн на основе старого, но без ошибок. Старый дизайн показал свою работоспособность на практике. Его проблемы — это проблемы реализации. Их не трудно обойти.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Размышления о типизаторе для Н2
От: VladD2 Российская Империя www.nemerle.org
Дата: 31.05.11 18:11
Оценка:
Здравствуйте, WolfHound, Вы писали:

VD>>Вот это вот вообще не понятно. "semidet" так просто какое-то шифрование. Что это значит то?

WH>Я ссылку на Mercury зачем дал?

Ща мы обсуждая твое сообщение за одно быстренько изучим все что касается Меркури. Это птичий язык который на фиг не уперся. И если ты его приводишь, то будь добр пояснять. Иначе тебя никто не поймет.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Размышления о типизаторе для Н2
От: VladD2 Российская Империя www.nemerle.org
Дата: 31.05.11 18:32
Оценка:
Здравствуйте, WolfHound, Вы писали:

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


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

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

Какой синтаксис? Это вот эта гора непонятных наворотов — это синтаксис? Ау! Меня не слышат?
То что ты привел — никуда не годится.

WH>Сахара я могу насыпать не меньше твоего.


Напиши. Результат должен быть не длиннее, и не сложнее моего. ОК?

VD>>Все эти навороты с rewrite, tast, for и т.п. — это никому не нужная пурга которая превратит написание макросов в сущий ад.

WH>Ад это то, что сейчас и то, что предлагаешь ты.

Да? Ну, тогда тебе не составит труда конструктивно раскритиковать мое решение.

WH>Сейчас компилятор не предлагает никаких механизмов для создания чего-то сложнее, чем if.


Мы не ведем разговор про сейчас.

WH>В твоем решении их тоже нет.


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

WH>Совсем.


Аргументы?

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

WH>Не сделает.

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

VD>>Приведи, плиз, пример макроса которому нужна типизация на стадии SST.

WH>foreach, lock, ?.,...

Не, не. Меня не интересует перечисление. Меня интересует псевдокод реализации с комментариями. Реализацию foreach я тебе уже приводил. В прочем, вот она еще раз:
macro module Nemerle
{
  macro ForEach : Ast.Expression
    syntax: "foreach" "(" pattern "in" collection ")" body
      where: pattern    = Ast.PatternWithGuard,
             collection = Ast.Expression,
             body       = Ast.Expression;
    require: IsTyped(collection) // требуем чтобы перед вызовом тела макроса был типизирован параметр collection
  {
    match (GetKind(collection.Type))
    {
      | TypeKind.Array        => IterateByArrayImpl(pattern, collection, body)
      | TypeKind.List         => IterateByListImpl(pattern, collection, body)
      | TypeKind.IEnumarableT => IterateByIEnumarableTImpl(pattern, collection, body)
      | TypeKind.IEnumarable  => IterateByIEnumarableImpl(pattern, collection, body)
      | _                     => TryIterateByEnumaratorPatternImpl(pattern, collection, body)
    }
  }

  IterateByArrayImpl(pattern : Ast.PatternWithGuard, collection : Ast.Expression, body : Ast.Expression) : Ast.Expression
  {
    match (pattern)
    {
      | <[ $(x : name) ]> => // pattern - это просто имя переменной (простой случай)
        <[ Nemerle: // указываем, что квази-цитата задается в грамматике Nemerle. 
           def loop(i : int, ary) : void
           {
             when (i < ary.Lenght)
             {
               def $x = ary[i];
               $body;
               loop(i + 1, ary)
             }
           } 

           loop(0, $collection);
        ]>
      ... // случаи с применением паттерн-матчинга опущены
    }
  }
  ...
}

Детали можно найти по ссылке сверху.
А вот так вот в моем варианте будет выглядить макрос lock:
  macro @lock : Ast.Expression
    syntax "lock" "(" lockOnExpr ")" body
    require: IsTyped(lockOnExpr)
  {
    if (lockOnTExpr.Type.IsValueType)
      Error (lockOnExpr, $"`$(lockOnTExpr.Type)' is not a reference type as required by the lock expression")
    else
      <[
        def toLock = $(lockOnTExpr : typed);
        System.Threading.Monitor.Enter(toLock);
        try { $body }
        finally { System.Threading.Monitor.Exit(toLock); }
      ]>
  }


Приведи свои реализации для них, тогда и обсудим.

VD>>Только чтобы она действительно была нужна (чтобы без нее нельзя было обойтись).

WH>Нет таких. Ибо макросы полны по Тьюрингу и с помощью такойто матери можно сделать что угодно.

Не, ну, достаточно примера который просто показал бы, что твое решение существенно проще и/или короче.

WH>Но я не хочу кучу возни на ровном месте.

WH>Вот тебе ярчайший пример твоего подхода:

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

То же как типизировать этот код ровным счетом никак не повлияет на наличие в нем "кучу возни на ровном месте".

WH>У тебя в макросе автокомплит обрабатывается.

WH>И ты ничего не предлагаешь, чтобы с этим бороться.

Может не надо демагогии то?

Когда проектировался Н1 о вещах вроде комплейшона и тем более об IDE никто не думал. Потому эта задница и нарисовалась.

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

Если мы хотим получить качественное решение, то надо их искать (предлагать), а не аппелировать черт знает к чему.

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

WH>Правда для foreach нужно еще кое что придумать.


Придумай и покажи. Я уже показал.

Пример с if в два раза сложнее и длиннее предложенного мной. Пока что счет 1 : 0 в пользу моего решения. Допускаю (хотя и сомневаюсь), что дело в простоте макроса. Возможно макросы по сложнее у тебя удадутся по лучше. ОК, ждем.

WH>Я ща if расширю:

WH>Пример совершенно бредовый но просто демонстрация.
WH>
WH>tast TypedStringIf : TypedExpression
WH>for If
WH>{
WH>    trueType      = trueExpression.ExpressionType;//Локальные переменные.
WH>    falseType     = falseExpression.ExpressionType;//Для краткости.
WH>    conditionType = condition.ExpressionType;

WH>    ConvertibleTo(conditionType, type(string))
WH>        @@@ $"Type of condition must be convertible to string. But $conditionType not convertible to string." condition.Location;

WH>    Unify([trueType, falseType], ExpressionType)
WH>        @@@ $"Typef of branches must be competible. $trueType and $falseType incompatible" this.Location;
WH>}
WH>rewrite
WH>{
WH>    <[
WH>        match ($condition)
WH>        {
WH>            | null | "" => $falseExpression;
WH>            | _         => $trueExpression;
WH>        }
WH>    ]>
WH>}
WH>//задаем приоритет нашему расширению меньше чем стандартному if'у.
WH>order TypedStringIf < TypedIf;
WH>

WH>Теперь если в if передать строку то все будет работать.
WH>Вот такая вот перегрузка макросов по типам параметров.

Пример похоже настолько бредовый, что я него не понял. Что он добивается то?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: Размышления о типизаторе для Н2
От: WolfHound  
Дата: 31.05.11 18:58
Оценка:
Здравствуйте, VladD2, Вы писали:

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

Изучить меркури в любом случае полезно.
Это очень хороший язык.
http://www.mercury.csse.unimelb.edu.au/information/doc-release/mercury_ref/Determinism-categories.html#Determinism-categories
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[3]: Размышления о типизаторе для Н2
От: WolfHound  
Дата: 31.05.11 18:58
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>А как это дело вяжется с выводом типов? Ты еще не забыл, что типы невозможно вывести за один проход?

Отлично.

VD>Вот даже если взять приведенный тобой (казалось бы простой!) код, то в нем уже заложена ошибка!

Ох.
Ты еще к запятым начни цепляться.

VD>Кроме того не надо забывать про то что типизатор не может работать в один проход! В общем случае вывод типов многопроходный да еще и с кучей спекулятивных типизаций (разветвлений типизации до облома... тот самый бэктрекинг).

Вот это все и нужно спрятать за формальную систему.
Ибо то, что есть сейчас это смерть мозгу.

VD>Как будет выглядит типизация вызова функции в условиях поддержки языком перегрузки? Мы это тоже заставим делать "пациента"?

Оно будет написано один раз и "пациент" если ему оно понадобиться сможет это использовать.
Хотя зачем ему это может понадобиться не ясно.

VD>А что будем делать с linq который кроме как через такое переписываиние никак не реализуется? Ведь без переписывания мы не сможем вычислить правильны тип. Прочитай внимательно спецификацию C# 3.0:

Хватит уже эту страшилку в сотый раз повторять.
Это решаемая задача.
Я просто думаю, как это сделать получше.

VD>Таким образом твое предложение не проходит критики даже при не глубоком изучении.

Особенно учитывая то, что ты ни слова из написанного не понял...

VD>Во-первых, нужно обосновать необходимость типизации SST.

Да ты на свой ?. посмотри.
Это же просто феерия.
Ты пойми никто кроме тебя его не напишет.
НИКТО!
Ибо никто не понимает что за возня там с автокомплитом.

VD>Для этого нужно привести хотя бы один пример где типизация по SST дает зримое преимущество над аналогичной реализации без типизации SST.

foreach, lock,...
А такие макросы как PegGrammar вообще без этого сделать нельзя.
Совсем.
Никак.
Сейчас SST типизируется руками.
Информация для IDE о том, что к чему относиться задается руками.
Автокомплита нет и не предвидеться.

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

Я тебя уже заколебался в них носом тыкать.
А ты все нету да нету.

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

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

VD>Пример похоже настолько бредовый, что я него не понял. Что он добивается то?

Чтобы string можно было в if засунуть.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.