private ArgumentObject[] CreateArgumentArray(
DynamicMetaObjectBinder payload,
IEnumerable<Expression> parameters,
DynamicMetaObject[] args)
{
// Check the payloads to see whether or not we need to get the runtime types for
// these arguments.
List<ArgumentObject> list = new List<ArgumentObject>();
Func<DynamicMetaObjectBinder, CSharpArgumentInfo, Expression, DynamicMetaObject, int, Type> getArgumentType = null;
Func<DynamicMetaObjectBinder, int, CSharpArgumentInfo> getArgumentInfo = null;
// Quick delegate to set the type.
if (payload is ICSharpInvokeOrInvokeMemberBinder)
{
getArgumentInfo = (p, index) => (p as ICSharpInvokeOrInvokeMemberBinder).ArgumentInfo[index];
}
else if (payload is CSharpBinaryOperationBinder)
{
getArgumentInfo = (p, index) => (p as CSharpBinaryOperationBinder).ArgumentInfo[index];
}
else if (payload is CSharpUnaryOperationBinder)
{
getArgumentInfo = (p, index) => (p as CSharpUnaryOperationBinder).ArgumentInfo[index];
}
else if (payload is CSharpGetMemberBinder)
{
getArgumentInfo = (p, index) => (p as CSharpGetMemberBinder).ArgumentInfo[index];
}
else if (payload is CSharpSetMemberBinder)
{
getArgumentInfo = (p, index) => (p as CSharpSetMemberBinder).ArgumentInfo[index];
}
else if (payload is CSharpGetIndexBinder)
{
getArgumentInfo = (p, index) => (p as CSharpGetIndexBinder).ArgumentInfo[index];
}
else if (payload is CSharpSetIndexBinder)
{
getArgumentInfo = (p, index) => (p as CSharpSetIndexBinder).ArgumentInfo[index];
}
else if (payload is CSharpConvertBinder || payload is CSharpIsEventBinder)
{
getArgumentInfo = (p, index) => CSharpArgumentInfo.None;
}
else
{
Debug.Assert(false, "Unknown payload kind");
throw Error.InternalCompilerError();
}
getArgumentType = (p, argInfo, param, arg, index) =>
{
Type t = argInfo.UseCompileTimeType ? param.Type : arg.LimitType;
Debug.Assert(t != null);
if ((argInfo.Flags & (CSharpArgumentInfoFlags.IsRef | CSharpArgumentInfoFlags.IsOut)) != 0)
{
// If we have a ref our an out parameter, make the byref type.
// If we have the receiver of a call or invoke that is ref, it must be because of
// a struct caller. Don't persist the ref for that.
if (!(index == 0 && IsBinderThatCanHaveRefReceiver(p)))
{
t = t.MakeByRefType();
}
}
else if (!argInfo.UseCompileTimeType)
{
// If we don't have ref or out, then pick the best type to represent this value.
// If the runtime value has a type that is not accessible, then we pick an
// accessible type that is "closest" in some sense, where we recursively widen
// components of type that can validly vary covariantly.
// This ensures that the type we pick is something that the user could have written.
CType actualType = _symbolTable.GetCTypeFromType(t);
CType bestType;
bool res = _semanticChecker.GetTypeManager().GetBestAccessibleType(_semanticChecker, _bindingContext, actualType, out bestType);
// Since the actual type of these arguments are never going to be pointer
// types or ref/out types (they are in fact boxed into an object), we have
// a guarantee that we will always be able to find a best accessible type
// (which, in the worst case, may be object).
Debug.Assert(res, "Unexpected failure of GetBestAccessibleType in construction of argument array");
t = bestType.AssociatedSystemType;
}
return t;
};
int i = 0;
foreach (var curParam in parameters)
{
ArgumentObject a = new ArgumentObject();
a.Value = args[i].Value;
a.Info = getArgumentInfo(payload, i);
a.Type = getArgumentType(payload, a.Info, curParam, args[i], i);
Debug.Assert(a.Type != null);
list.Add(a);
++i;
}
return list.ToArray();
}