Пытаюсь разобраться с тем, как работает линк в Немерле. Написал простенький код:
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, по идее, не может этого делать, ибо это метод из библиотеки фреймворка. Макросы никакие я не импортирую. Объясните, пожалуйста.