Сообщающиеся макросы
От: _Claus_  
Дата: 19.11.11 13:11
Оценка:
Недавно была дискуссия и ее фрагмент:

_С_ >> В Boo вложенный макрос видит своего содержателя через переменную с его именем, и соответственно может там менять дописывать все что вздумается.

VladD2 >> В немерле просто не понадобится вложенный макрос.
Тут другие принципы. Обычно в Н для таких случае создают макро-атрибут который вешают на сборку или тип и он распознает нужный синтаксис и формирует нужный код.

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

Самый быстрый механизм работы СУБД через MemoryMapped Files. в net 4.0 появилась возможность напрямую с ними работать, ессно с ограничениями,
но все же. Обмен данных возможен только структурами. У меня классы. Задача: по описанию класса сгенерить структуру + вспомогательный код.

У меня было в Boo так:
Persist X
{  
   VAL a as int
   REF b as string
   REFVAL values as SortList of X
   ..
}


Вложенные макросы VAL, REF,.. создавали защищенные свойства,
добавляли о себе инфу макросу Persist, который потом разворачивал ее в структуру с такими или другими полями и методы.

Теперь в Н я не вижу как сделать то же самое. Макросы отметаем, берем макроатрибуты. Имеет проблемы:
явно объявленное поле (избыточное объявление имеем сразу — mutable оно всегда) надо трансформировать в property
c кодом. вероятно возможно, но дальше, куда кидать информацию о себе ? — если Persist макрос отработал, она уже бесполезна,
если нет, то как ему передать нужные данные? Если все же возможно, все равно есть явная проблема,
если вложенные макроатрибуты работают до атрибута Persist, им некуда регистрировать информацию о себе, если после,
она уже бесполезна.

Что робыть?
Re: Сообщающиеся макросы
От: VladD2 Российская Империя www.nemerle.org
Дата: 19.11.11 20:45
Оценка:
Здравствуйте, _Claus_, Вы писали:

_C_>У меня было в Boo так:

_C_>Persist X
_C_>{  
_C_>   VAL a as int
_C_>   REF b as string
_C_>   REFVAL values as SortList of X
_C_>   ..
_C_>}


Можно даже воспроизвести 1 в 1 (с учетом синтаксических различий). Но проще и привычнее было бы сделать все на базе макро-атрибутов. Тогда это выглядело бы так:

[Persist]
class X
{  
   public [VAL]    a      : int         { get; set; }
   public [REF]    b      : string      { get; set; }
   public [REFVAL] values : SortList[X] { get; set; }
   ...
}


_C_>Вложенные макросы VAL, REF,.. создавали защищенные свойства,

_C_>добавляли о себе инфу макросу Persist, который потом разворачивал ее в структуру с такими или другими полями и методы.

Тут вариантов может быть масса.
1. VAL, REF и REFVAL могут быть обычными атрибутами. Макрос Persist может читать информацию о полях, и за одно, информацию об атрибутах VAL, REF и REFVAL.
2. VAL, REF и REFVAL можно сделать марками работающими на ранних стадиях. Они могут делать что вам надо плюс добавлять в UserData TypeBuilder-а для типа X необходимую информацию. Persist, работающий на более поздней стадии, сможет прочесть эту информацию и сгенерировать то что нужно (структуру и что угодно еще).

_C_>Теперь в Н я не вижу как сделать то же самое. Макросы отметаем, берем макроатрибуты. Имеет проблемы:

_C_>явно объявленное поле (избыточное объявление имеем сразу — mutable оно всегда) надо трансформировать в property c кодом.

Объявляй сразу свойства. Можешь и mutable сам подставить, если нужно. Только это может запутать других.

_C_>вероятно возможно, но дальше, куда кидать информацию о себе ?


В свойство UserData объекта в котором объявляются свойства и применяется атрибут Persist.

_C_>- если Persist макрос отработал, она уже бесполезна,

_C_>если нет, то как ему передать нужные данные?

Реализуй Persist на более поздней стадии и все будет ОК. Он сможет читать информацию из UserData. Засунь в UserData хэш-таблицу в которой заложи нужную информацию (ключ имя свойства, значение — нужная информация).

_C_> Если все же возможно, все равно есть явная проблема,

_C_>если вложенные макроатрибуты работают до атрибута Persist, им некуда регистрировать информацию о себе, если после,
_C_>она уже бесполезна.

Ну, я уже выше описал два подхода.
1. Сделать VAL обычными атрибутами и разбираться со всем в макросе Persist.
2. Выполнять Persist на более поздней стадии и передовать данные через TypeBuilder.UserData.
Выбор за тобой.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Сообщающиеся макросы
От: _Claus_  
Дата: 19.11.11 21:58
Оценка:
VD>Можно даже воспроизвести 1 в 1 (с учетом синтаксических различий).

Это как? простые макросы на уровне классов и полей не работают(кстати будет ли это устранено в Nemerle2?). а так конечно хочу.для полей это более адекватно, чем атрибуты.
VD>Но проще и привычнее было бы сделать все на базе макро-атрибутов. Тогда это выглядело бы так:

VD>
VD>[Persist]
VD>class X
VD>{  
VD>   public [VAL]    a      : int         { get; set; }
VD>   public [REF]    b      : string      { get; set; }
VD>   public [REFVAL] values : SortList[X] { get; set; }
VD>   ...
VD>}
VD>


так не очень подойдет, насколько я понимаю, у меня на get set вешается код, зависящий от типа переменной + тип внутренней переменной как правило не
совпадает с объявленным и вычисляется от типа(обычно — смещение в базе, но не всегда) + для некоторых типов доп. поле, отслеживающие была ли модификация. поэтому желательно чистое объявление, которое сделает все что нужно для поля. только вот не понял я как простым макросом..


VD>2. VAL, REF и REFVAL можно сделать марками работающими на ранних стадиях. Они могут делать что вам надо плюс добавлять в UserData TypeBuilder-а для типа X необходимую информацию. Persist, работающий на более поздней стадии, сможет прочесть эту информацию и сгенерировать то что нужно (структуру и что угодно еще).


именно так и нужно.

_C_>>Теперь в Н я не вижу как сделать то же самое. Макросы отметаем, берем макроатрибуты. Имеет проблемы:

_C_>>явно объявленное поле (избыточное объявление имеем сразу — mutable оно всегда) надо трансформировать в property c кодом.

VD>Объявляй сразу свойства. Можешь и mutable сам подставить, если нужно. Только это может запутать других.


поэтому и не стоит явно свойства объявлять. это внутреннее дело.

еще вот не получается трансформация, Н упорно подставляет лишние скобки ( в контексте выражения), как от них избавиться?

macro @REF (var) 
  syntax("REF",  var)
  {     
    <[mutable $var ]>     
  }


может проще показать boo макрокод, чтобы было яснее? там много разных моментов. если получится его умно портировать, у общества
будет резвая embedded db. а может еще и статья.
Re[3]: Сообщающиеся макросы
От: VladD2 Российская Империя www.nemerle.org
Дата: 19.11.11 23:20
Оценка:
Здравствуйте, _Claus_, Вы писали:


VD>>Можно даже воспроизвести 1 в 1 (с учетом синтаксических различий).


_C_>Это как?


Можно прикрутить синтаксис к макросам верхнего уровня. Не уверен, что это без проблем будет работать в IDE (никто не проверял). Смотри макрос abrakadabra и его применение.

_C_>простые макросы на уровне классов и полей не работают(кстати будет ли это устранено в Nemerle2?).


В Немерле другая идеология. Устранять тут нечего. К этому придется привыкнуть.

_C_>а так конечно хочу.для полей это более адекватно, чем атрибуты.


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

_C_>так не очень подойдет, насколько я понимаю, у меня на get set вешается код, зависящий от типа переменной + тип внутренней переменной как правило не совпадает с объявленным и вычисляется от типа(обычно — смещение в базе, но не всегда) + для некоторых типов доп. поле, отслеживающие была ли модификация. поэтому желательно чистое объявление, которое сделает все что нужно для поля. только вот не понял я как простым макросом..


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

_C_>поэтому и не стоит явно свойства объявлять. это внутреннее дело.


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

В немерле есть макрос Accessor. Он создает свойства-эксессоры для полей. Можешь поглядеть его реализацию. Но в последнее время его используют редка, так как автосвойства банально удобнее и красивее.

_C_>еще вот не получается трансформация, Н упорно подставляет лишние скобки ( в контексте выражения), как от них избавиться?


_C_>
_C_>macro @REF (var) 
_C_>  syntax("REF",  var)
_C_>  {     
_C_>    <[mutable $var ]>     
_C_>  }
_C_>


Что за скобки?

_C_>может проще показать boo макрокод, чтобы было яснее? там много разных моментов. если получится его умно портировать, у общества будет резвая embedded db. а может еще и статья.


Получится или нет — это зависит от тебя.
В макросах Бу я не силен. Но поглядеть можно.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Сообщающиеся макросы
От: _Claus_  
Дата: 20.11.11 00:37
Оценка:
VD>На мой взгляд, более адекватно не удивлять людей которые, в последствии, будут читать и править код написанный с использованием макросов. По сему, если описывается класс, то лучше чтобы он выглядел как класс, пусть даже и размеченный атрибутами. Лишний синтаксис — лишнее время на изучения. Все должно быть оправданным.

Если трансформация атрибутом поля в свойство удивляет Н-программистов, тогда оправдано, иначе — лишний код, в котором можно ошибиться.
Эта трансформация абсолютно невидима для прикладника.


_C_>>еще вот не получается трансформация, Н упорно подставляет лишние скобки ( в контексте выражения), как от них избавиться?


_C_>>
_C_>>macro @REF (var) 
_C_>>  syntax("REF",  var)
_C_>>  {     
_C_>>    <[mutable $var ]>     
_C_>>  }
_C_>>


VD>Что за скобки?


выдает mutable (z : int)
причем не исправляется если раскладываю на var.exp, var.type, все равно вылазят.

_C_>>может проще показать boo макрокод, чтобы было яснее? там много разных моментов. если получится его умно портировать, у общества будет резвая embedded db. а может еще и статья.


VD>Получится или нет — это зависит от тебя.



Не только от меня. например я плохо понимаю как добраться из макроса REF до макроса Persist.
перечень функций для подъема в дереве не видел в описании. массив блоков кода AST как умно сцепить в один, — не знаю.
элементарные вещи вроде тех, которые описаны выше работают с "особенностями". которые непонятно как преодолеть.
код макросов смотрю, но пока ясности в голове нет.
так что сам может и напишу, но показывать постесняюсь.

VD>В макросах Бу я не силен. Но поглядеть можно.

синтакс похож. макрокода немного. коменты есть еще добавлю. куда кидать?
Re[5]: Сообщающиеся макросы
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.11.11 01:45
Оценка:
Здравствуйте, _Claus_, Вы писали:

_C_>Если трансформация атрибутом поля в свойство удивляет Н-программистов, тогда оправдано, иначе — лишний код, в котором можно ошибиться.


Немерле-программист не обязан знать все ДСЛ-и на свете. Если можно обойтись штатным синтаксисом, то я предпочитаю так и поступать. ДСЛ должен давать явные приемущества. Здесь я таковых не вижу.

_C_>выдает mutable (z : int)


Значит ты туда суешь "z : int". Тебе нужно усложнить макрос, чтобы он распознавал случай "z : int" и обрабатывал его отдельно. Скобок там, скорее всего, нет. Просто при преобразовании в строку оно так отображается.

_C_>Не только от меня. например я плохо понимаю как добраться из макроса REF до макроса Persist.


Я же раз пять уже объяснил.

_C_>перечень функций для подъема в дереве не видел в описании.


Не понял этой фразы.

_C_> массив блоков кода AST как умно сцепить в один, — не знаю.


Преобразовать в список (list[T]) и в нужном месте подставить в квазицитату:
<[ { ..$exprs } ]>

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

_C_>элементарные вещи вроде тех, которые описаны выше работают с "особенностями". которые непонятно как преодолеть.

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

Стесняться тут нечего. Если возникают вопросы, мы поможем. Тут главное пробовать. Ну, почитать имеет смысл.

VD>>В макросах Бу я не силен. Но поглядеть можно.

_C_>синтакс похож. макрокода немного. коменты есть еще добавлю. куда кидать?

Если не много, то можешь просто прямо в сообщении показывать. Если там все же не мало кода, то можно закинуть на какой-нить http://pastebin.com.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Сообщающиеся макросы
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.11.11 01:52
Оценка:
Здравствуйте, _Claus_, Вы писали:

Да... очень советую почитать это
Автор: VladD2
Дата: 04.09.11
. Там как раз даются примеры создания нетривиальных макросов.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: Сообщающиеся макросы
От: catbert  
Дата: 20.11.11 07:05
Оценка:
Здравствуйте, _Claus_, Вы писали:

_C_>>>еще вот не получается трансформация, Н упорно подставляет лишние скобки ( в контексте выражения), как от них избавиться?


_C_>>>
_C_>>>macro @REF (var) 
_C_>>>  syntax("REF",  var)
_C_>>>  {     
_C_>>>    <[mutable $var ]>     
_C_>>>  }
_C_>>>



_C_>выдает mutable (z : int)

_C_>причем не исправляется если раскладываю на var.exp, var.type, все равно вылазят.

Приоритеты правильно задали?
Re: Сообщающиеся макросы
От: catbert  
Дата: 20.11.11 07:12
Оценка:
Здравствуйте, _Claus_, Вы писали:

_C_>Вложенные макросы VAL, REF,.. создавали защищенные свойства,

_C_>добавляли о себе инфу макросу Persist, который потом разворачивал ее в структуру с такими или другими полями и методы.

_C_>все равно есть явная проблема,

_C_>если вложенные макроатрибуты работают до атрибута Persist, им некуда регистрировать информацию о себе, если после,
_C_>она уже бесполезна.

_C_>Что робыть?


Посмотреть на код макросов Record или StructuralEquality, в которых есть похожий паттерн:

https://github.com/rsdn/nemerle/blob/master/macros/StructuralEquality.n
https://github.com/rsdn/nemerle/blob/master/macros/core.n#L864 (почему бы все макросы не разложить наконец по отдельным файлам?)

Там есть макроатрибуты RecordIgnore и, соответственно, EqualsIgnore, которые делают то, что вам нужно: выполняются до своих "родителей" и сообщают им про свои поля.
Re[6]: Сообщающиеся макросы
От: _Claus_  
Дата: 20.11.11 08:43
Оценка:
VD>Немерле-программист не обязан знать все ДСЛ-и на свете. Если можно обойтись штатным синтаксисом, то я предпочитаю так и поступать. ДСЛ должен давать явные приемущества. Здесь я таковых не вижу.

Здесь REF, REFVAL, .. это такие же описатели как mutable и def. Наличие последних просто избыточно, потому что описатели базы являются производными от mutable. но держаться за это не буду (в одном месте ты восхищенно рассказывал о том, что можно ; в конце метода не писать, а тут экономии больше).

_C_>>выдает mutable (z : int)


VD>Значит ты туда суешь "z : int". Тебе нужно усложнить макрос, чтобы он распознавал случай "z : int" и обрабатывал его отдельно. Скобок там, скорее всего, нет. Просто при преобразовании в строку оно так отображается.


От это не легче — код не компилируется.

_C_>>Не только от меня. например я плохо понимаю как добраться из макроса REF до макроса Persist.


VD>Я же раз пять уже объяснил.

VD>Не понял этой фразы.

Про DataUser я понял, не понял как до макроса добраться.

_C_>> массив блоков кода AST как умно сцепить в один, — не знаю.


VD>Стесняться тут нечего. Если возникают вопросы, мы поможем. Тут главное пробовать. Ну, почитать имеет смысл.


VD>Если не много, то можешь просто прямо в сообщении показывать. Если там все же не мало кода, то можно закинуть на какой-нить http://pastebin.com.


макросы — http://pastebin.com/4uikZiTA
back-end database для макросов — http://pastebin.com/DDcsGX7G

вместе они представляют завершенный комплект, позволяющий написать вот такой код:


Persist my_root:
    
    REFBLOCK words as List of iword
            
        ..
    
datamap_ = datamap_file(fname_datamap, size_datamap)
        
if datamap_.root_obj
            
     Instance = datamap_.root_obj
else
     datamap_.root_obj = my_root(datamap_ )

     datamap_.save_root()

my_root.x_obj = Obj(datamap_)
 
my_root.list_obj = List[Obj]()

my_root.list_obj.AddRange(..)

my_root.save()



и дальше работать с кодом почти так же как без СУБД, при изменении объектов, находящихся вне контейнеров, надо им
вызывать save. транзакций нет, их не поддерживает .Net для memmapfiles. но в конце изменений надо вызывать save_root,
там хранится смещение на блоки свободной памяти, которое может измениться.
основное и главное достоинство — скорость. она в десяток раз больше, чем у быстрейшей встроенной .Net субд Perst.
вторичное достоинство — предельная простота, расширяемость и бесплатность.
Re[6]: Сообщающиеся макросы
От: _Claus_  
Дата: 20.11.11 09:23
Оценка:
Здравствуйте, catbert, Вы писали:

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


_C_>>>>еще вот не получается трансформация, Н упорно подставляет лишние скобки ( в контексте выражения), как от них избавиться?


_C_>>>>
_C_>>>>macro @REF (var) 
_C_>>>>  syntax("REF",  var)
_C_>>>>  {     
_C_>>>>    <[mutable $var ]>     
_C_>>>>  }
_C_>>>>



_C_>>выдает mutable (z : int)

_C_>>причем не исправляется если раскладываю на var.exp, var.type, все равно вылазят.

C>Приоритеты правильно задали?


а какие? я пишу

REF x : int

и ожидаю

mutable x : int

вместо этого имею

mutable (x : int)
Re[2]: Сообщающиеся макросы
От: _Claus_  
Дата: 20.11.11 09:25
Оценка:
Здравствуйте, catbert, Вы писали:

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


_C_>>Вложенные макросы VAL, REF,.. создавали защищенные свойства,

_C_>>добавляли о себе инфу макросу Persist, который потом разворачивал ее в структуру с такими или другими полями и методы.

_C_>>все равно есть явная проблема,

_C_>>если вложенные макроатрибуты работают до атрибута Persist, им некуда регистрировать информацию о себе, если после,
_C_>>она уже бесполезна.

_C_>>Что робыть?


C>Посмотреть на код макросов Record или StructuralEquality, в которых есть похожий паттерн:


C>https://github.com/rsdn/nemerle/blob/master/macros/StructuralEquality.n

C>https://github.com/rsdn/nemerle/blob/master/macros/core.n#L864 (почему бы все макросы не разложить наконец по отдельным файлам?)

C>Там есть макроатрибуты RecordIgnore и, соответственно, EqualsIgnore, которые делают то, что вам нужно: выполняются до своих "родителей" и сообщают им про свои поля.


Ух ты.. премного благодарны!
Re[7]: Сообщающиеся макросы
От: catbert  
Дата: 20.11.11 10:57
Оценка: +1
Здравствуйте, _Claus_, Вы писали:

C>>Приоритеты правильно задали?


_C_>а какие? я пишу


_C_>REF x : int


_C_>и ожидаю


_C_>mutable x : int


_C_>вместо этого имею


_C_>mutable (x : int)


Ну да, это потому что REF захватывает все выражение x : int и подставляет его как имя переренной для mutable. Не знаю, зачем вам указывать тип после REF (ведь он все равно выведется), но если очень надо, советую сделать вот так:

  macro @REF (var)
    syntax ("REF", var)
  {
      match (var)
      {
      | <[ $x : $y ]> => <[mutable $x : $y; ]>
      | <[ $x = $y ]> => <[mutable $x = $y; ]>
      | _ => <[ mutable $var; ]>
      }
  }


Макрос будет расковыривать var и заковыривать его назад в mutable.

Более "кошерный" подход в том, чтобы задать приоритет связывания оператора REF выше чем у двоеточия.
Re[2]: Сообщающиеся макросы
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.11.11 17:27
Оценка:
Здравствуйте, catbert, Вы писали:

C>почему бы все макросы не разложить наконец по отдельным файлам?


Займись.

ЗЫ

Почему все говорят о том, что нужно сделать что-то полезное, а не делают?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: Сообщающиеся макросы
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.11.11 18:05
Оценка:
Здравствуйте, _Claus_, Вы писали:

_C_>>>выдает mutable (z : int)


VD>>Значит ты туда суешь "z : int". Тебе нужно усложнить макрос, чтобы он распознавал случай "z : int" и обрабатывал его отдельно. Скобок там, скорее всего, нет. Просто при преобразовании в строку оно так отображается.


_C_>От это не легче — код не компилируется.


Ну, дык, если ничего не менять, то ничего и не изменится .

Покажи код. В прочем, здесь
Автор: catbert
Дата: 20.11.11
уже дан верный ответ.

_C_>Про DataUser я понял, не понял как до макроса добраться.


Я раз пять объяснял. Одни макросы выполняются на более ранней стадии, например, BeforeInherence. Пишут нужную информацию в в свойство UserData объекта TypeBuilder (передаваемый им в качестве параметра). Другой выполняется на более поздней стадии. Он читает данные из UserData и формирует нужный код.

_C_>макросы — http://pastebin.com/4uikZiTA

_C_>back-end database для макросов — http://pastebin.com/DDcsGX7G

Поглядел бегло. Конечно же не все понятно. Но в общем сложилось впечатление, что это какой-то сериализатор списка объектов в файл. На СУБД это мало похоже. Возможно, конечно, что я что-то пропустил. Букв много...
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: Сообщающиеся макросы
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.11.11 19:16
Оценка:
Здравствуйте, _Claus_, Вы писали:

_C_>Про DataUser я понял, не понял как до макроса добраться.


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

Helpers.n — тут описана извлекающая (и инициализирующая) значение из typeBuilder.UserData["Persist_FieldsMap"]:
  Скрытый текст
using Nemerle.Collections;
using Nemerle.Compiler;
using Nemerle.Imperative;

namespace MacroLibrary
{
  type MapType = Hashtable[Parsetree.ClassMember.Property, string];
  
  module Helpers
  {
   public GetFieldsMap(typeBuilder : TypeBuilder) : MapType
    {
      def fieldsMap = typeBuilder.UserData["Persist_FieldsMap"] :> MapType;
      
      when (fieldsMap != null)
        return fieldsMap;
        
      def fieldsMap = MapType();
      typeBuilder.UserData["Persist_FieldsMap"] = fieldsMap;
      fieldsMap
    }
  }
}


Ref.n — содержит реализацию макро-атрибута Ref. Он вешается на свойство и закладывает информацию в typeBuilder.UserData["Persist_FieldsMap"]:
  Скрытый текст
using Nemerle;
using Nemerle.Collections;
using Nemerle.Compiler;
using Nemerle.Compiler.Parsetree;
using Nemerle.Compiler.Typedtree;
using Nemerle.Text;
using Nemerle.Utility;

using System;
using System.Collections.Generic;
using System.Linq;

namespace MacroLibrary
{
  [MacroUsage(MacroPhase.BeforeInheritance, MacroTargets.Property)]
  macro Ref(typeBuilder : TypeBuilder, property : ClassMember.Property)
  {
    RefImpl.DoTransform(Macros.ImplicitCTX(), typeBuilder, property)
  }
  
  module RefImpl
  {
    public DoTransform(typer : Typer, typeBuilder : TypeBuilder, property : ClassMember.Property) : void
    {
      Macros.DefineCTX(typer);
      def fieldsMap = Helpers.GetFieldsMap(typeBuilder);
      fieldsMap[property] = "REF"; // запоминаем, что к данному свойству был применен макрос Ref
    }
  }
}


Persist.n — основной макрос Persist. В нем выводится информация о всех свойствах. Если есть дополнительная информация, то выводится и она:
  Скрытый текст
using Nemerle;
using Nemerle.Collections;
using Nemerle.Compiler;
using Nemerle.Compiler.Parsetree;
using Nemerle.Compiler.Typedtree;
using Nemerle.Text;
using Nemerle.Utility;

using System;
using System.Collections.Generic;
using System.Linq;

using BF = System.Reflection.BindingFlags;

namespace MacroLibrary
{
  [MacroUsage(MacroPhase.WithTypedMembers, MacroTargets.Class)]
  macro Persist(typeBuilder : TypeBuilder)
  {
    PersistImpl.DoTransform(Macros.ImplicitCTX(), typeBuilder)
  }
  
  module PersistImpl
  {
    public DoTransform(typer : Typer, typeBuilder : TypeBuilder) : void
    {
      Macros.DefineCTX(typer);
      
      def props = typeBuilder.GetProperties(BF.DeclaredOnly | BF.Public | BF.NonPublic | BF.Instance);
      
      foreach (prop is PropertyBuilder in props)
      {
        def fieldsMap = Helpers.GetFieldsMap(typeBuilder);
        def kind = fieldsMap.Get(prop.Ast) ?? "none"; // Получаем доп.информацию о свойстве или "none".
        
        Message.Hint(prop.NameLocation, $"Property $(prop.Name) : $(prop.Getter?.ReturnType) ($kind)");
      }
    }
  }
}


Использование:
  Скрытый текст
using System;
using MacroLibrary;

[Persist]
class TestClass
{
        public Prop1 : int      { get; set; }
  [Ref] public Prop2 : string   { get; set; }
        public Prop3 : DateTime { get; set; }
}
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: Сообщающиеся макросы
От: _Claus_  
Дата: 21.11.11 07:07
Оценка:
ух! спасибо!

При переписывании наткнулся на проблему, с которой гугление не помогло.
демокод:
class x
  public load[ T](delta : int) : List[T]                         
    List[T]()

module Program

  Main() : void
        
    mutable f = x()
    
    def s = f.load[int](2) //вариант 1
    
    def s : List[int]  = f.load(2) //вариант 2


оба не помогают
некоторые методы, например load в datamap принимают шаблон struct, который в параметрах метода не обозначен.
компилятор обзывается:
cannot find any suitable indexer in 'List' (type is ? -> ?)
и еще всякое по мелочи..
Re[9]: Сообщающиеся макросы
От: _nn_ www.nemerleweb.com
Дата: 21.11.11 08:28
Оценка:
Здравствуйте, _Claus_, Вы писали:

_C_>ух! спасибо!


_C_>При переписывании наткнулся на проблему, с которой гугление не помогло.

_C_>демокод:
_C_>class x
_C_>  public load[ T](delta : int) : List[T]                         
_C_>    List[T]()

_C_>module Program

_C_>  Main() : void
        
_C_>    mutable f = x()
    
_C_>    def s = f.load[int](2) //вариант 1
    
_C_>    def s : List[int]  = f.load(2) //вариант 2

_C_>оба не помогают
_C_>некоторые методы, например load в datamap принимают шаблон struct, который в параметрах метода не обозначен.
_C_>компилятор обзывается:
_C_>cannot find any suitable indexer in 'List' (type is ? -> ?)
_C_>и еще всякое по мелочи..

В Nemerle синтаксис a[b] это вызов индексера, а генерик тип это будет a.[b] (обратить внимание на точку).

В некоторых случаях эту точку можно не писать и компилятор сам определяет, что это не индексер, а в некоторых случаях писать нужно.
Точка в генерик типе
Автор: _nn_
Дата: 21.09.11


В данном случае нужно просто указать точку либо не писать тип:
// Самый предпочтительный
def s = f.load(2);

// Указание генерика
def s : List.[int] = f.load.[int](2); 
def s  = f.load.[int](2); 
def s  : List.[int] = f.load(2);
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[10]: Сообщающиеся макросы
От: _Claus_  
Дата: 21.11.11 08:42
Оценка:
__>// Указание генерика
__>def s : List.[int] = f.load.[int](2);
__>def s = f.load.[int](2);
__>def s : List.[int] = f.load(2);
__>[/nemerle]

спасибо, помогло!
Re[11]: Сообщающиеся макросы
От: _nn_ www.nemerleweb.com
Дата: 21.11.11 09:22
Оценка:
Здравствуйте, _Claus_, Вы писали:

__>>// Указание генерика

__>>def s : List.[int] = f.load.[int](2);
__>>def s = f.load.[int](2);
__>>def s : List.[int] = f.load(2);
__>>[/nemerle]

_C_>спасибо, помогло!


А чем плох вариант: "def s = f.load(2)" ?
Писать меньше и типы автоматически выводятся.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.