Только начал разбираться с макросами. В макросе как один из параметро вполучаю PExpr, в котором находится Tuple, GetType() возвращает PExpr+Tuple, мне надо во время работы макроса преобразовать этот Tuple в переменную и обработать ее (сгенерировать типы на основе Tuple). Можно ли это сделать и как?
Здравствуйте, Аноним, Вы писали:
А>Только начал разбираться с макросами. В макросе как один из параметро вполучаю PExpr, в котором находится Tuple, GetType() возвращает PExpr+Tuple, мне надо во время работы макроса преобразовать этот Tuple в переменную и обработать ее (сгенерировать типы на основе Tuple). Можно ли это сделать и как?
Сгенерировать переменную можно. Например, так:
match (expr)
{
| <[ ($(n : name), $type, $value) ]> => <[ def $(n : name) : $type = $value; ]>
| _ => Message.FatalError(expr.Location, "Expected tuple");
}
Но чтобы понять, что же конкретно нужно нужны дополнительные данные. Приведи код (хотя бы приблизительный).
Здравствуйте, VladD2, Вы писали:
VD>Сгенерировать переменную можно. Например, так:
VD>VD>match (expr)
VD>{
VD> | <[ ($(n : name), $type, $value) ]> => <[ def $(n : name) : $type = $value; ]>
VD> | _ => Message.FatalError(expr.Location, "Expected tuple");
VD>}
VD>
В expr сейчас содержимое кортежа.
VD>Но чтобы понять, что же конкретно нужно нужны дополнительные данные. Приведи код (хотя бы приблизительный).
Хочу сделать макрос, который будет генерировать код классов по их описанию (заодно еще в качестве побочного эффекта на уровне текста генерить код на другом языке, но это сейчас неважно).
Синтаксис вызова планирую примерно такой.
[assembly: Macro1((
("MyType1", ("MyField1", "MyField2")),
("MyType2", ("MyField3", "MyField4"))
))]
Кортежи нравятся тем, что по аналогии со списками Lisp допускают любой уровень вложенности.
Дейсвую по аналогии со скринкастом по генерации классов из БД — спасибо за представленное там видео. Так как классов будет много, то тип кортежа не хотелось бы править каждый раз в коде макроса. Хотелось бы автоматически вывести его, воспользовавшись выводом типов в Nemerle.
Здравствуйте, Аноним, Вы писали:
А>Синтаксис вызова планирую примерно такой.
А>[assembly: Macro1((
А> ("MyType1", ("MyField1", "MyField2")),
А> ("MyType2", ("MyField3", "MyField4"))
А> ))]
А>Кортежи нравятся тем, что по аналогии со списками Lisp допускают любой уровень вложенности.
Спискам Лиспа соответствует любой код немерла, так как он представляется в виде AST, что соответствует S-выражениям Лиспа. Так что нет никакого смысла упираться в кортежи или списки.
И уж точно лучше использовать идентификаторы вместо строковых литералов (как в твоем примере). Твой пример можно записать так:
[assembly: Macro1((
(MyType1, (MyField1, MyField2)),
(MyType2, (MyField3, MyField4))
))]
и распознавать его так:
match (expr)
{
| <[ (..$types) ]> =>
foreach (type in types)
{
| <[ ($(typeName : name), (..$fields)) ]> =>
foreach (field in fields)
{
| <[ $(fieldName : name) ]> =>
// обрабатываем описание полей
| _ => ...
}
| _ => ...
}
| _ => ...
}
А еще лучше так:
[assembly: Macro1({
MyType1(MyField1, MyField2);
MyType2(MyField3, MyField4);
})]
и распознавать это дело так:
match (expr)
{
| <[ { ..$types } ]> =>
foreach (type in types)
{
| <[ $(typeName : name)(..$fields) ]> =>
foreach (field in fields)
{
| <[ $(fieldName : name) ]> =>
// обрабатываем описание полей
| _ => ...
}
| _ => ...
}
| _ => ...
}