Доброго дня
Написал такой макрос. Все работает если в методах нет return или yield.
Как узнать что в методе используется ключевое слово yield?
Как побороть ошибку error : goto (block return?) is not allowed inside expressions
[MacroUsage(MacroPhase.WithTypedMembers, MacroTargets.Class)]
macro Flag(typeBuilder : TypeBuilder, params args : array[PExpr])
{
FlagImpl.DoTransform(Macros.ImplicitCTX(), typeBuilder, args)
}
module FlagImpl
{
[ParseParameters]
class Parameters
{
public Name:PExpr;
public Debug:bool;
public Property:bool;
public Include:list[PExpr];
}
public mcatch DoTransform(typer : Typer, typeBuilder : TypeBuilder, args : array[PExpr]) : void
{
Macros.DefineCTX(typer);
// TODO: Add implementation here.
_ = typeBuilder; _ = args;
def context = MacroContext(typer,typeBuilder);
def par = Parameters(args);
when(par.Debug) context.Debug = true;
def name =
switch{
| par.Property => Macros.NewSymbol("flag").ToStr();
| par.Name != null => par.Name.ToStr()
| _ => "_flag"
}
<[decl: mutable $(name:usesite):bool = false ]> |> context.DeclareMember;
when(par.Property) {
def pname = if(par.Name == null) "Flag" else par.Name.ToStr();
<[decl: public $(pname:usesite):bool { get { $(name:usesite) } } ]> |> context.DeclareMember;
}
foreach(m is MethodBuilder in typeBuilder.GetMethods())
{
when(!m.IsPublic) continue;
when(m.IsConstructor) continue;
if( m.ReturnType.TryRequire(<[ttype:void]>) )
{
m.Body = locate(m.Body.Location)
<[
{
try { $(name:usesite) = true; $(m.Body) } finally { $(name:usesite) = false; }
}
]>
}
else
{
m.Body = locate(m.Body.Location)
<[
{
mutable result;
try { $(name:usesite) = true; result = $(m.Body) } finally { $(name:usesite) = false; }
result;
}
]>
}
}
}
}
Здравствуйте, kaa_t, Вы писали:
_>Написал такой макрос. Все работает если в методах нет return или yield.
_>Как узнать что в методе используется ключевое слово yield?
Можно найти yield в коде метода с помощью класса Nemerle.Compiler.ExprWalker:
foreach(m is MethodBuilder in typeBuilder.GetMethods())
{
mutable hasYield = false;
def walker = ExprWalker();
def walk(info : ExprWalkInfo) : void
{
when (info.Node is PExpr.MacroCall(name=Name(Id="yield")))
{
hasYield = true;
info.Stop();
}
}
walker.Walk(m.Body, walk);
when (hasYield)
Message.Hint(m.Location, $"The method '$(m.Name)' call 'yield' macro.");
}
_>Как побороть ошибку error : goto (block return?) is not allowed inside expressions
Эта ошибка означает, что где-то есть нелокальный выход из функции или выражения. Например, если написать break внутри локальной функции находящейся в цикле, то может появиться такое сообщение. Или если написать return внутри выражения.
Часто это бывает связано с некорректной генерацией кода.
В приведенном фрагменте вроде ничего такого нет. Но в нем есть применение каких-то макросов. Возможно ошибка в них.
Вот в этом нет смысла:
_>_> <[
_> {
_> mutable result;
_> try { $(name:usesite) = true; result = $(m.Body) } finally { $(name:usesite) = false; }
_> result;
_> }
_> ]>
_>
блок try и так возвращает значение. Можно выбросить if и всегда возвращать первый вариант кода.