Пытаюсь сделать простой макрос, который вычислит тип поля и добавит родителя в класс.
Но что-то не работает, выдает 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());
}
}
Здравствуйте, _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:
Здравствуйте, CodingUnit, Вы писали:
CU>Че то ты здесь намудрил, пытаешься добавить на этапе BeforeInheritance а задействуешь типизацию, немудрено NRE получить, обычно на этой фазе добавляют с помощью метода AddImplementedInterface, через обычный PExpr:
Я хочу вычислить тип A.a и его добавить в базовый класс.
Получается парадокс, тип получить до стадии WithTypedMembers нельзя, а добавить базовый класс на этой стадии уже поздно.
Здравствуйте, _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]: Макрос добавить родителя в класс на базе типа поля
Здравствуйте, CodingUnit, Вы писали:
CU>Здравствуйте, _NN_, Вы писали:
_NN>>Получается парадокс, тип получить до стадии WithTypedMembers нельзя, а добавить базовый класс на этой стадии уже поздно.
CU>Все можно, можно и с типами работать на этой фазе, но безопасным способом, то что ты делал так делать нельзя, поэтому компилятор ругнулся. А добавить тип можно так, я сделал несколько опущений, ты можешь восстановить у себя, и переписать так как тебе нужно, надеюсь идея ясна:
Я уже подумывал над поиском символа, но надеялся, что есть более красивый способ.
Здравствуйте, _NN_, Вы писали:
_NN>Я уже подумывал над поиском символа, но надеялся, что есть более красивый способ.
Поиск символа здесь единственное решение, поскольку типы еще не связаны, а типизация выражения A.a ничего не даст как типизированный вариант PExpr обращения к полю, которое тоже еще не связано, может быть бы проще если при поиске символа можно было бы задавать полное имя члена, без поиска его родителя, а так все логично, чтобы выяснить содержимое АСТ некоего класса надо искать его в дереве.