Ошибка в макросе приведения типа
От: STDray http://stdray.livejournal.com
Дата: 21.02.13 17:33
Оценка:
Написал макрос, который типизирует тело вызываемого метода, сравнивает полученный тип с формально описанным и если они не совпадают, то делает даункаст.
public macro Deanon(funCall : PExpr) 
    syntax ("deanon", funCall) {
        ExtendedAnonTypesImpl.Deanon(Macros.ImplicitCTX(), funCall)
    }
    [ManagerAccess(ManagerClass.Instance)]
    module ExtendedAnonTypesImpl{
        withType(typer: Typer, expr: PExpr, transform : TExpr -> PExpr, errMsg : string="") : PExpr{
            def errText = if(!string.IsNullOrEmpty(errMsg)) errMsg
                          else $"Can not infer the type of $expr";
            def type = typer.TypeExpr(expr);
            typer.DelayMacro(lt => match(type.Type.Hint) {
                | None when lt => Message.FatalError(expr.Location, errText)
                | None         => None();
                | Some         => type |> transform |> Some
            });
        }
        public Deanon(typer : Typer, funCall : PExpr) : PExpr {
            Macros.DefineCTX(typer);
            def wt = withType(typer, _, _);
            def (fname, _) = match(funCall) {
                | <[ $f(..$args) ]> => (f, args)
                | _                 => Message.FatalError(funCall.Location, "Function call expected");
            }
            def makeCast(callType, t) {
                def method = match(t) {
                    | TExpr.StaticRef(_, method, _)     => method;
                    | TExpr.MethodRef(_, method, _ , _) => method;
                    | _                                 => Message.FatalError(t.Location, "Only method call supperted");
                }
                def methodBuilder = method :> MethodBuilder;
                methodBuilder.RunBodyTyper();
                def bodyType = methodBuilder.BodyTyped.Type;
                if(callType.Type.TryProvide <| bodyType) <[ $funCall ]>
                else                                     <[ $funCall :> $(bodyType: typed) ]>
            }
            wt(funCall, ct => wt(fname, makeCast(ct,_)));
        }
    }


На словах, то есть с точки зрения интеграции, все отрабатывает


Но при сборке проекта валится с ошибкой
Main.n(26,18): error : AssertionException has occurred when expanding macro 'deanon' confused by earlier errors bailing out

Хотя отладкой студии в студии смотрел — никаких ошибок там не сыпалось. И что делать с подобным ассертом не имею ни малейшего представления. Куда посоветуете копать?
Re: Ошибка в макросе приведения типа
От: STDray http://stdray.livejournal.com
Дата: 22.02.13 15:24
Оценка:
Переписал реализацию макроса

        public Deanon(typer : Typer, funCall : PExpr) : PExpr {
            Macros.DefineCTX(typer);
            def wt = withType(typer, _, _);
            def (fname, _) = match(funCall) {
                | <[ $f(..$args) ]> => (f, args)
                | _                 => Message.FatalError(funCall.Location, "Function call expected");
            }
            def makeCast(callType, t) {
                def method = match(t) {
                    | TExpr.StaticRef(_, method, _)     => method;
                    | TExpr.MethodRef(_, method, _ , _) => method;
                    | _                                 => Message.FatalError(t.Location, "Only method call supported");
                }
                def methodBuilder = method :> MethodBuilder;

                def methodTyper = Typer(methodBuilder);

                withType(methodTyper, methodBuilder.Body, bt => {
                    def bodyType = bt.Type;
                    if(callType.Type.TryRequire <| bodyType) <[ $funCall ]>
                    else                                     <[ $funCall :> $(bodyType: typed) ]>
                });
            }
            wt(funCall, ct => wt(fname, makeCast(ct,_)));
        }


сыпется с ошибкой

{"assertion ``!solver.InUse'' failed in file ncc\\typing\\Typer.n, line 145"}


Подскажите, что же я неправильно делаю? В первом варианте даже корректно раскрывалось все.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.