[n2] Создание типов в макросах уровня выражения
От: VladD2 Российская Империя www.nemerle.org
Дата: 04.01.11 00:08
Оценка:
Создание и манипуляция типами из макросов уровня выражений приводит к проблемам при попытке распараллелить типизацию тел методов.

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

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

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

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

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

Разберем идею на примере:

Предположим нам нужно разработать макрос который ссылается на новое поле некоторого динамически создаваемого типа из макроса уровня выражения. Скажем это будет макрос локализации "L".
macro class Localization
{
  macro L(strLit)
    syntax: "L" str:StringLiteral
  {
    def str       = strLit.ToString();
    def fieldName = $"Value$(Typer.NextId())";

    Typer.AfterCurrentPhase += _ => // событие вызываемое после окончания текущей фазы типизации (в главном потоке)
     {
       def tb = Typer.UserData["Localization"] :> TypeBuilder; // тип определен ранее в макро-атрибуте
       tb.Define(<[ member: mutable $(fieldName : dyn) = $(str : string); ]>)
     };

    
    <[ Localization.$(fieldName : dyn[Typer.CurrentPhase]) ]> // сообщаем компилятору, что поле будет доступно позже (после текущего этапа)
  }
}
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: [n2] Создание типов в макросах уровня выражения
От: seregaa Ниоткуда http://blogtani.ru
Дата: 04.01.11 01:44
Оценка: 1 (1)
Здравствуйте, VladD2, Вы писали:

VD>Создание и манипуляция типами из макросов уровня выражений приводит к проблемам при попытке распараллелить типизацию тел методов.

Что за проблемы?

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

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

Боюсь, что самая тяжелая часть макроса переползет в этот обработчик и тогда выгоды от распаралеливания не будет. Это касается даже твоего примера. Плюс появилась необходимость в дополнительном проходе типизатора (((

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

macro class Localization
{
  macro L(strLit)
    syntax: "L" str:StringLiteral
  {
    def str       = strLit.ToString();
    def fieldName = $"Value$(Typer.NextId())";

    def tb = Typer.UserData["Localization"] :> TypeBuilder; // тип определен ранее в макро-атрибуте

    def delayedField = Typer.DefineMemberFor(tb, <[ member: mutable $(fieldName : dyn) = $(str : string); ]>); // компилятор регистрирует "заявку" на создание поля и возвращает отложенное определение

    <[ $(delayedField ) ]> //отложенное определение хранит ссылку на "заявку". Это облегчит работу типизатору, позволив ему определить тип поля и момент, когда его уже можно типизовать.
}
Мобильная версия сайта RSDN — http://rsdn.org/forum/rsdn/6938747
Автор: sergeya
Дата: 19.10.17
Re: [n2] Создание типов в макросах уровня выражения
От: hi_octane Беларусь  
Дата: 04.01.11 09:27
Оценка:
VD>Создание и манипуляция типами из макросов уровня выражений приводит к проблемам при попытке распараллелить типизацию тел методов.

Выглядит слишком сложно. А что мешает сделать фазы типизации наподобии yield? Типа как (псевдокод):

macro class Localization
{
  macro L(strLit)
    syntax: "L" str:StringLiteral
  {
    def str       = strLit.ToString();
    def fieldName = $"Value$(Typer.NextId())";

    def tb = ...;//здесь создаётся какой-то тип
    yield tb;//в этот момет поток типизации метода понимает что дальше типизировать нельзя, ложит новый тип в очередь Typer'a и откладывает типизацию этого метода до следующей версии AST в которой тип уже будет

    //когда доходим до этой итерации - тип уже есть, можно использовать
  }
}
Re[2]: [n2] Создание типов в макросах уровня выражения
От: hardcase Пират http://nemerle.org
Дата: 04.01.11 09:47
Оценка: +1
Здравствуйте, hi_octane, Вы писали:

VD>>Создание и манипуляция типами из макросов уровня выражений приводит к проблемам при попытке распараллелить типизацию тел методов.


_>Выглядит слишком сложно. А что мешает сделать фазы типизации наподобии yield? Типа как (псевдокод):


Это не на yield походит. Это на по сути механизм продолжений, реализованый в ComputationExpressions.
Т.е. заявка на создание мембера:
def field = member <[ mutable x : SomeType; ]>;
foo(field);

переписывается в
context.DefineMember(<[ member: mutable x : SomeType; ]>, fun(field : TypeMember)
{
  // вызываемся на следующей версии AST 
  foo(field);
})
/* иЗвиНите зА неРовнЫй поЧерК */
Re[3]: [n2] Создание типов в макросах уровня выражения
От: VladD2 Российская Империя www.nemerle.org
Дата: 04.01.11 12:16
Оценка:
Здравствуйте, hardcase, Вы писали:

H>Это не на yield походит. Это на по сути механизм продолжений, реализованый в ComputationExpressions.


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