как работает лифтинг лямбд в линке?
От: xeno.by xeno.by
Дата: 28.09.11 19:10
Оценка:
Пытаюсь разобраться с тем, как работает линк в Немерле. Написал простенький код:

using System;
using System.Linq;
using System.Console;

def x = 11;
def a = [10];
PrintExpr(() => a.AsQueryable().Where(el => el < x));

// в другой единице компиляции есть вот такой макрос
macro PrintExpr(pexpr : expr)
{
    WriteLine(pexpr.GetType());
    WriteLine(pexpr.ToString());
    pexpr.Dump();

    def typer = Nemerle.Macros.ImplicitCTX();
    def texpr = typer.TypeExpr(pexpr);
    WriteLine(texpr.GetType());
    WriteLine(texpr.ToString());
//    texpr.Dump();
    <[ () ]>;
}


Если компилировать этот код, не ссылаясь на Nemerle.Linq.dll, т.е. ncc -no-color -nowarn:10003 -nowarn:10005 -nowarn:168 -debug+ -r System.Core.dll -m macro.dll play.n playhelper.n -out play.exe, то лифтинг не происходит:

Nemerle.Compiler.Parsetree.PExpr+Call
() => a.AsQueryable().Where(el => el < x)
Call(func = Ref(name = =>), parms = Literal(val = ()), Call(func = Member(obj = Call(func = Member(obj = Ref(name = a), member = AsQueryable), parms = ), member = Where), parms = Call(func = Ref(name = =>), parms = Ref(name = el), Call(func = Ref(name = <), parms = Ref(name = el), Ref(name = x)))))
Nemerle.Compiler.Typedtree.TExpr+MacroEnvelope
macro_Nemerle.Core._N_operator905413823_4226Macro:
  def _N_lambda__3794() : System.Collections.Generic.IEnumerable[int]-
{
    block (_N_return) :
      DEBUG_INFO(System.Linq.Enumerable.Where.[int] (System.Func[int, bool] (macro_Nemerle.Core._N_operator905413823_4226Macro:
        def _N_lambda__3798(el : int) : bool
{
          block (_N_return) :
            DEBUG_INFO(<.s (el, x))
        }
        _N_lambda__3798)))
  }
  _N_lambda__3794


Если добавить ссылку на Nemerle.Linq.dll, т.е. + ncc -no-color -nowarn:10003 -nowarn:10005 -nowarn:168 -debug+ -r System.Core.dll -r Nemerle.Linq.dll -m macro.dll play.n playhelper.n -out play.exe, то лифтинг таки-отрабатывает:

Nemerle.Compiler.Parsetree.PExpr+Call
() => a.AsQueryable().Where(el => el < x)
Call(func = Ref(name = =>), parms = Literal(val = ()), Call(func = Member(obj = Call(func = Member(obj = Ref(name = a), member = AsQueryable), parms = ), member = Where), parms = Call(func = Ref(name = =>), parms = Ref(name = el), Call(func = Ref(name = <), parms = Ref(name = el), Ref(name = x)))))
Nemerle.Compiler.Typedtree.TExpr+MacroEnvelope
macro_Nemerle.Core._N_operator905413823_4226Macro:
  def _N_lambda__4298() : System.Linq.IQueryable[int]-
{
    block (_N_return) :
      DEBUG_INFO(System.Linq.Queryable.Where.[int] (macro_Nemerle.Linq.ToExpressionMacro:
        def closureFunc() : System.Linq.Expressions.Expression[System.Func[int, bool]]
{
          block (_N_return) :
            def _N_param_el__5784 = System.Linq.Expressions.Expression.Parameter (typeof (int), "el");
            (System.Linq.Expressions.Expression.Lambda.[System.Func[int, bool]] (System.Linq.Expressions.Expression.MakeBinary ((20 :> System.Linq.Expressions.ExpressionType), _N_param_el__5784, System.Linq.Expressions.Expression.Field (System.Linq.Expressions.Expression.Constant (ClosureObjectOf (x)), ClosureFieldOf (x)), false, null), array  [_N_param_el__5784]) : System.Linq.Expressions.Expression[System.Func[int, bool]])
        }
        def closureFuncRef = closureFunc;
        closureFuncRef ()))
  }
  _N_lambda__4298


При этом хочу отметить, что using Nemerle.Linq я нигде не пишу, поэтому я в недоумении. Кто вызывает ToExpressionMacro? System.Linq.Queryable.Where, по идее, не может этого делать, ибо это метод из библиотеки фреймворка. Макросы никакие я не импортирую. Объясните, пожалуйста.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.