Вопрос по макросам
От: evilbeaver  
Дата: 06.04.10 05:32
Оценка:
Каким образом в макросе на тип при обработке FieldBuilder'ов можно получить информацию о типе поля. Допустим получить TypeBuilder этого типа.
Re: Вопрос по макросам
От: hardcase Пират http://nemerle.org
Дата: 06.04.10 07:48
Оценка:
Здравствуйте, evilbeaver, Вы писали:

E>Каким образом в макросе на тип при обработке FieldBuilder'ов можно получить информацию о типе поля. Допустим получить TypeBuilder этого типа.


Вроде-бы так:
def fixed_ty = fb.GetMemType();
match(fixed_ty.TypeInfo) {
  | tb is TypeBuilder => ......
  | _ => () // тип из внешней сборки
}


Правда не уверен, что будет в случаях генериков:
class Foo[T] { x : T }
http://nemerle.org/Banners/?t=Developer!&g=dark /* иЗвиНите зА неРовнЫй поЧерК */
Как получить информацию о типе в метаатрибуте?
От: VladD2 Российская Империя www.nemerle.org
Дата: 06.04.10 16:02
Оценка:
#Имя: FAQ.nemerle.TypeInfoInMetaattribute001
Здравствуйте, evilbeaver, Вы писали:

E>Каким образом в макросе на тип при обработке FieldBuilder'ов можно получить информацию о типе поля. Допустим получить TypeBuilder этого типа.


На стадии MacroPhase.WithTypedMembers, то как правильно заметил hardcase, типы можно получать непосредственно из FieldBuilder через GetMemType().

Если на других стадиях, то типы придется связать вручную. На этих стадиях в качестве параметра макроса передается TypeDeclaration.Field. У него есть поле ty и ParsedType. ParsedType — это тип спарсеный из исходника. Он не может быть изменен макросом. "ty" — это изменяемое поле. Оно может быть изменено макросами.

Так вот чтобы связать тип нужно наприсать примерно такой код:
def tType : FixedType = typer.BindFixedType(field.ty);


FixedType — это тип описывающий информацию о типах внутри Немерла.

ЗЫ

Не стоит пытаться получить System.Type, так как он будет доступен только для типов импортированных из других сборок. Всю информацию о типах нужно получать из FixedType. Его описание можно найти здесь.
http://nemerle.org/Banners/?g=dark
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Вопрос по макросам
От: evilbeaver  
Дата: 07.04.10 15:22
Оценка:
Здравствуйте, hardcase, Вы писали:

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


E>>Каким образом в макросе на тип при обработке FieldBuilder'ов можно получить информацию о типе поля. Допустим получить TypeBuilder этого типа.


H>Вроде-бы так:

H>
H>def fixed_ty = fb.GetMemType();
H>match(fixed_ty.TypeInfo) {
H>  | tb is TypeBuilder => ......
H>  | _ => () // тип из внешней сборки
H>}
H>


Спасибо, то что нужно.
По поводу дженериков.
t — TypeBuilder. Мне нужно проверить, что тип поля совпадает с t, либо является списком t
пишу вот так
match(item.GetMemType().TypeInfo)
        {
          | tb is TypeBuilder => tb.Equals(t) || tb.Equals(<[ttype: list[t] ]>)
          | _ => false
        }


На одиночный тип прокатывает, а вот на список нет.
Подскажите, пожалуйста, что делать в таком случае
Re[3]: Вопрос по макросам
От: VladD2 Российская Империя www.nemerle.org
Дата: 07.04.10 16:09
Оценка:
Здравствуйте, evilbeaver, Вы писали:

E>Спасибо, то что нужно.

E>По поводу дженериков.
E>t — TypeBuilder. Мне нужно проверить, что тип поля совпадает с t, либо является списком t
E>пишу вот так
E>
E>match(item.GetMemType().TypeInfo)
E>        {
E>          | tb is TypeBuilder => tb.Equals(t) || tb.Equals(<[ttype: list[t] ]>)
E>          | _ => false
E>        }
E>


E>На одиночный тип прокатывает, а вот на список нет.

E>Подскажите, пожалуйста, что делать в таком случае

А откуда берется "t"?

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

Собственно это — "<[ttype: list[t] ]>" точно не верная конструкция, так как "t" не будет воспринят как переменная. Кроме того TypeBuilder — это тип объявленный в компилируемой сборке. Он точно не может являться списком, так как список объявлен в Nemerle.dll.

Судя по тому, что "t" сопоставляется с TypeInfo — "t" берется не верно.

Работать надо с FixedType или с TypeVar.

Чтобы выснить тип списка нужно сделать примерно следующее:
matgch (somyType.Hint)
{
  | FixedType.Class(tc, [ty]) when tc.Equals(tc.InternalType.Nemerle_list_tc) && ty.Equals(t) => ...
  | _ => ...
}

Таким образом общий код должен быть примерно таким:
def testType(t : TypeVar) : bool
{
  matgch (somyType.Hint)
  {
    // Пороверяем не является известный тип t типом элемента списка
    | Some(FixedType.Class(tc, [ty]) when tc.Equals(tc.InternalType.Nemerle_list_tc) && ty.Equals(t)) => true
    | Some(ty) => ty.Equals(t)
    | None => assert(false) // Тип еще не вычислен! Эту ситуацию нужно разбирать отдельно!!!
  }
}
http://nemerle.org/Banners/?g=dark
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Вопрос по макросам
От: evilbeaver  
Дата: 07.04.10 18:18
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Таким образом общий код должен быть примерно таким:

VD>
VD>def testType(t : TypeVar) : bool
VD>{
VD>  matgch (somyType.Hint)
VD>  {
VD>    // Пороверяем не является известный тип t типом элемента списка
VD>    | Some(FixedType.Class(tc, [ty]) when tc.Equals(tc.InternalType.Nemerle_list_tc) && ty.Equals(t)) => true
VD>    | Some(ty) => ty.Equals(t)
VD>    | None => assert(false) // Тип еще не вычислен! Эту ситуацию нужно разбирать отдельно!!!
VD>  }
VD>}
VD>



Спасибо за помощь. Мне не хватало вот этого
     tc.Equals(tc.InternalType.Nemerle_list_tc)

С остальным разобрался, работает как и должно

Вопросы вдогонку:
1. Аналогичным способом можно ли проверить, что тип реализует конкретный дженериковый интерфейс (например IEnumerable['a])?
     tc.Equals(tc.InternalType.IEnumerable_tc)

Вышеприведенный вариант будет истинным только если поле объявлено как IEnumerable['a], а что делать в случае, если оно например IList['a]?
Я предполагаю, что это можно сделать как-то так, только не знаю, что подставить вместо вопросов
     tc.GetMemType().TryRequire(???)


2. Правильно ли я понимаю, что описанным Вами способ применим только лишь для типов, указанных в InternalTypeClass'е ? есть ли возможность проверки на произвольный дженерик?
Re[5]: Вопрос по макросам
От: VladD2 Российская Империя www.nemerle.org
Дата: 07.04.10 20:40
Оценка:
Здравствуйте, evilbeaver, Вы писали:

E>Вопросы вдогонку:

E>1. Аналогичным способом можно ли проверить, что тип реализует конкретный дженериковый интерфейс (например IEnumerable['a])?
E>
E>     tc.Equals(tc.InternalType.IEnumerable_tc)
E>


Не совсем. Для проверки того является ли тип подтипом другого типа нужно использовать методы TryRequire или TryProvide.
Но это методы VarType и FixedType.

Советую прочесть 4-ю часть Макросы Nemerle – расширенный курс
Автор(ы): Владислав Юрьевич Чистяков
Дата: 03.09.2009
В данной части статьи рассказывается о том, как работает система вывода типов Nemerle, о том, как с ней могут взаимодействовать макросы Nemerle, и что это дает
. Там все рассказано и даны примеры.

E>Вышеприведенный вариант будет истинным только если поле объявлено как IEnumerable['a], а что делать в случае, если оно например IList['a]?

E>Я предполагаю, что это можно сделать как-то так, только не знаю, что подставить вместо вопросов
E>
E>     tc.GetMemType().TryRequire(???)
E>


Нет. Вместо tc (который имеет тип TypeInfo), нужно подставить значение типа VarType. Их можно сконструировать вручную:
def ty = FixedType.Class(tc.InternalType.IEnumerable_tc, [t])


E>2. Правильно ли я понимаю, что описанным Вами способ применим только лишь для типов, указанных в InternalTypeClass'е ? есть ли возможность проверки на произвольный дженерик?


Другие типы можно получить динамически через Manager.Lookup(type_name) (для TypeInfo) или с помощью typer.BindMonoType().
http://nemerle.org/Banners/?g=dark
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: Вопрос по макросам
От: VladD2 Российская Империя www.nemerle.org
Дата: 08.04.10 00:39
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Другие типы можно получить динамически через Manager.Lookup(type_name) (для TypeInfo) или с помощью typer.BindMonoType().


Забыл сказать... Тип можно получить и с помощью квази-цитаты ttype. Но при этом вместо параметра типа нужно указывать "_". Например, так:
def iEnumerableType = <[ ttype: System.Collections.Generic.IEnumerable[_] ]>;

Пример его использования можно увидеть в стандартной библиотеке: core.n#507.
http://nemerle.org/Banners/?g=dark
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.