Здравствуйте, CodingUnit, Вы писали:
CU>Еще встала другая проблема, надо определить во время компиляции в макросе перечисление на основе кода, например так:
CU>CU>[MacroUsage(MacroPhase.BeforeTypedMembers,MacroTargets.Class,Inherited=true)]
CU>macro statemachine(ty : TypeBuilder)
CU>{
CU>// определяем перечисление, нормально
CU>def stateid=ty.DefineNestedType(<[ decl:
CU> public enum StateID
CU> {
CU> }
CU> ]>);
CU>..
CU>def states : list[TypeBuilder]= ty.DeclaredNestedTypes; // получаем лист TypeBuilder-ов для внутренних типов
CU>// для каждого типа добавляем имя в качестве константы к перечислению
CU>states.Iter( x => stateid.Define(<[ $(x.Name)]>)); // не компилируется
CU>// также просто если попробовать
CU>stateid.Define(<[decl: | ABC ]>); // компилируется, но при выполнении ничего не происходит, новый член не добавляется
CU>}
CU>stateid.Compile(); // компилируем тип
CU>
CU>CU>// при этом если написать сразу список членов, то он определяется правильно:
CU>def stateid=ty.DefineNestedType(<[ decl:
CU> public enum StateID
CU> {
CU> | ABC
CU> | BCD
CU> }
CU> ]>); // если бы была возможность как то в цитату вставить строки с описанием членов
CU>
CU>Вопрос такой, как определить перечисление в макросе и добавить как подтип в классе?
Что-то вроде этого:
[MacroUsage(MacroPhase.BeforeTypedMembers,MacroTargets.Class,Inherited=true)]
macro statemachine(ty : TypeBuilder)
{
// генерируем список определений полей перечисления
def cases = ty.DeclaredNestedTypes.Map(t => <[ decl: | $(t.ParsedName : name); ]>);
def enumTypeBuilder = ty.DefineNestedType( // вложенные типы нужно добавлять только с помощью DefineNestedType
<[ decl:
public enum StateID
{
..$cases
}
]>, true);
enumTypeBuilder.Compile();
}
CU> Как добавить динамически в макросе элементы в список перечисления, есть ли такая возможность?
Или как показал я, или с помощью методов DefineXxx() класса TypeBuilder.
CU>И последний вопрос, если писать DSL то потребуется много ключевых слов, при этом они как то должны взаимодействовать между собой, проходит синтаксические и семантические проверки, для этого надо чтобы текст разбирался и получалось некое описание на DSL, для этого нужен какой то объект который хранит в себе все состояние описанной структуры, то есть должен быть доступен на этапе компиляции и при вызове макроса через помеченные объекты или описание в методе, добавлять информацию в этот объект, то есть должен создаваться один раз и жить в остальное время.
Это все очень сильно зависит от задачи говорить о чем-то в ообщем невозможно.
CU>Еще может потребоваться некоторые члены удалять, которые не несут в себе никакой информации для приложения, например классы для описания вложенной иерархии нужные макросу, но ненужные в рантайме, было бы хорошо удалить чтобы они были не видны, но TypeBuilder допускает объявлять члены, но не допускает удалять и многие внутренние поля компилятора read-only, можно ли решить как то эту задачу?
Удалаять нельзя. Но нужную метаинформацию можно описать в другом виде. Например в виде доп-синтаксиса, или в виде мета-атрибутов.
В общем, лучше опиши стоящую задачу (без ее реализации), а мы попробуем как ее лучше реализовать.