private Expression BindCore(
DynamicMetaObjectBinder payload,
IEnumerable<Expression> parameters,
DynamicMetaObject[] args,
out DynamicMetaObject deferredBinding)
{
if (args.Length < 1)
{
throw Error.BindRequireArguments();
}
InitializeCallingContext(payload);
ArgumentObject[] arguments = CreateArgumentArray(payload, parameters, args);
// On any given bind call, we populate the symbol table with any new
// conversions that we find for any of the types specified. We keep a
// running SymbolTable so that we don't have to reflect over types if
// we've seen them already in the table.
//
// Once we've loaded all the standard conversions into the symbol table,
// we can call into the binder to bind the actual call.
ICSharpInvokeOrInvokeMemberBinder callOrInvoke = payload as ICSharpInvokeOrInvokeMemberBinder;
PopulateSymbolTableWithPayloadInformation(payload, arguments[0].Type, arguments);
AddConversionsForArguments(arguments);
// When we do any bind, we perform the following steps:
//
// 1) Create a local variable scope which contains local variable symbols
// for each of the parameters, and the instance argument.
// 2) If we have operators, then we don't need to do lookup. Otherwise,
// look for the name and switch on the result - dispatch according to
// the symbol kind. This results in an EXPR being bound that is the expression.
// 3) Create the EXPRRETURN which returns the call and wrap it in
// an EXPRBOUNDLAMBDA which uses the local variable scope
// created in step (1) as its local scope.
// 4) Call the ExpressionTreeRewriter to generate a set of EXPRCALLs
// that call the static ExpressionTree factory methods.
// 5) Call the EXPRTreeToExpressionTreeVisitor to generate the actual
// Linq expression tree for the whole thing and return it.
// (1) - Create the locals
Dictionary<int, LocalVariableSymbol> dictionary = new Dictionary<int, LocalVariableSymbol>();
Scope pScope = _semanticChecker.GetGlobalMiscSymFactory().CreateScope(null);
PopulateLocalScope(payload, pScope, arguments, parameters, dictionary);
// (1.5) - Check to see if we need to defer.
DynamicMetaObject o = null;
if (DeferBinding(payload, arguments, args, dictionary, out o))
{
deferredBinding = o;
return null;
}
// (2) - look the thing up and dispatch.
EXPR pResult = DispatchPayload(payload, arguments, dictionary);
Debug.Assert(pResult != null);
deferredBinding = null;
Expression e = CreateExpressionTreeFromResult(parameters, arguments, pScope, pResult);
return e;
}
#region Helpers