Re: Написание DSL на Nemerle и создание Enum в макросах
От: VladD2 Российская Империя www.nemerle.org
Дата: 03.02.10 14:36
Оценка:
Здравствуйте, 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, можно ли решить как то эту задачу?


Удалаять нельзя. Но нужную метаинформацию можно описать в другом виде. Например в виде доп-синтаксиса, или в виде мета-атрибутов.

В общем, лучше опиши стоящую задачу (без ее реализации), а мы попробуем как ее лучше реализовать.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.