Макрос добавить родителя в класс на базе типа поля
От: _NN_ www.nemerleweb.com
Дата: 01.11.13 19:09
Оценка:
Пытаюсь сделать простой макрос, который вычислит тип поля и добавит родителя в класс.
Но что-то не работает, выдает NullReferenceException в недрах компилятора.
Может я не правильно делаю ?

Использование:
class A 
{
  public static a : A;
}

[Inherits(A.a)]
class B { }


Сам макрос:
using Nemerle;
using Nemerle.Collections;
using Nemerle.Compiler;
using Nemerle.Compiler.Parsetree;

namespace MacroLibrary1
{
  [MacroUsage(MacroPhase.BeforeInheritance, MacroTargets.Class)]
  macro Inherits(typeBuilder : TypeBuilder, variable : PExpr)
  {
    InheritsImpl.DoTransform(Macros.ImplicitCTX(), typeBuilder, variable)
  }
  
  module InheritsImpl
  {
    public DoTransform(typer : Typer, typeBuilder : TypeBuilder, variable : PExpr) : void
    {
      Macros.DefineCTX(typer);
      
       def c = typeBuilder.Ast :> TopDeclaration.Class;
       
       def typedVariable = typer.TypeExpr(variable);
       when (!typedVariable.ty.IsFree)
        Message.Error(variable.Location, "expected expression with inferred type");
     
      c.t_extends ::= PExpr.TypedType(typedVariable.Type.Fix());
    }
  
}
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: Макрос добавить родителя в класс на базе типа поля
От: CodingUnit Россия  
Дата: 01.11.13 22:48
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Пытаюсь сделать простой макрос, который вычислит тип поля и добавит родителя в класс.

_NN>Но что-то не работает, выдает NullReferenceException в недрах компилятора.
_NN>Может я не правильно делаю ?



_NN> def c = typeBuilder.Ast :> TopDeclaration.Class;


_NN> def typedVariable = typer.TypeExpr(variable);

_NN> when (!typedVariable.ty.IsFree)
_NN> Message.Error(variable.Location, "expected expression with inferred type");

_NN> c.t_extends ::= PExpr.TypedType(typedVariable.Type.Fix());

_NN> }

_NN>}


Че то ты здесь намудрил, пытаешься добавить на этапе BeforeInheritance а задействуешь типизацию, немудрено NRE получить, обычно на этой фазе добавляют с помощью метода AddImplementedInterface, через обычный PExpr:


typeBuilder.AddImplementedInterface(<[ BaseType[TType] ]>);
Re[2]: Макрос добавить родителя в класс на базе типа поля
От: _NN_ www.nemerleweb.com
Дата: 02.11.13 08:17
Оценка:
Здравствуйте, CodingUnit, Вы писали:

CU>Че то ты здесь намудрил, пытаешься добавить на этапе BeforeInheritance а задействуешь типизацию, немудрено NRE получить, обычно на этой фазе добавляют с помощью метода AddImplementedInterface, через обычный PExpr:


Я хочу вычислить тип A.a и его добавить в базовый класс.

Получается парадокс, тип получить до стадии WithTypedMembers нельзя, а добавить базовый класс на этой стадии уже поздно.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[3]: Макрос добавить родителя в класс на базе типа поля
От: CodingUnit Россия  
Дата: 02.11.13 15:37
Оценка: 1 (1)
Здравствуйте, _NN_, Вы писали:

_NN>Получается парадокс, тип получить до стадии WithTypedMembers нельзя, а добавить базовый класс на этой стадии уже поздно.


Все можно, можно и с типами работать на этой фазе, но безопасным способом, то что ты делал так делать нельзя, поэтому компилятор ругнулся. А добавить тип можно так, я сделал несколько опущений, ты можешь восстановить у себя, и переписать так как тебе нужно, надеюсь идея ясна:


    public DoTransform(typer : Typer, typeBuilder : TypeBuilder, variable : PExpr) : void
    {
      Macros.DefineCTX(typer);
      
      def symb = variable.ToString().SplitToList('.');
      def type = symb.FirstN(symb.Length - 1);
      def type = typeBuilder.GlobalEnv.LookupType(type);
      match (type)
      {
        | Some(TypeBuilder as t) => def decl = t.Ast.GetMembers();
                                    def decl = decl.Find(x => x.Name == symb.Last());
                                    match (decl)
                                    {
                                      | Some(ClassMember.Field as type) => typeBuilder.AddImplementedInterface(type.ty);
                                      | _                               => ()
                                    }
                     
        | _       => ()
      }
    }
Re[4]: Макрос добавить родителя в класс на базе типа поля
От: _NN_ www.nemerleweb.com
Дата: 02.11.13 18:40
Оценка:
Здравствуйте, CodingUnit, Вы писали:

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


_NN>>Получается парадокс, тип получить до стадии WithTypedMembers нельзя, а добавить базовый класс на этой стадии уже поздно.


CU>Все можно, можно и с типами работать на этой фазе, но безопасным способом, то что ты делал так делать нельзя, поэтому компилятор ругнулся. А добавить тип можно так, я сделал несколько опущений, ты можешь восстановить у себя, и переписать так как тебе нужно, надеюсь идея ясна:


Я уже подумывал над поиском символа, но надеялся, что есть более красивый способ.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[5]: Макрос добавить родителя в класс на базе типа поля
От: CodingUnit Россия  
Дата: 02.11.13 20:12
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Я уже подумывал над поиском символа, но надеялся, что есть более красивый способ.


Поиск символа здесь единственное решение, поскольку типы еще не связаны, а типизация выражения A.a ничего не даст как типизированный вариант PExpr обращения к полю, которое тоже еще не связано, может быть бы проще если при поиске символа можно было бы задавать полное имя члена, без поиска его родителя, а так все логично, чтобы выяснить содержимое АСТ некоего класса надо искать его в дереве.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.