RuntimeBinder
struct RuntimeBinder
using Microsoft.CSharp.RuntimeBinder.Errors;
using Microsoft.CSharp.RuntimeBinder.Semantics;
using Microsoft.CSharp.RuntimeBinder.Syntax;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Dynamic;
using System.Linq.Expressions;
namespace Microsoft.CSharp.RuntimeBinder
{
internal readonly struct RuntimeBinder
{
private static readonly object s_bindLock = new object();
private readonly ExpressionBinder _binder;
internal bool IsChecked => _binder.Context.Checked;
public RuntimeBinder(Type contextType, bool isChecked = false)
{
AggregateSymbol context = default(AggregateSymbol);
if (contextType != (Type)null) {
lock (s_bindLock) {
context = ((AggregateType)SymbolTable.GetCTypeFromType(contextType)).OwningAggregate;
}
} else
context = null;
_binder = new ExpressionBinder(new BindingContext(context, isChecked));
}
public Expression Bind(ICSharpBinder payload, Expression[] parameters, DynamicMetaObject[] args, out DynamicMetaObject deferredBinding)
{
lock (s_bindLock) {
return BindCore(payload, parameters, args, out deferredBinding);
}
}
private Expression BindCore(ICSharpBinder payload, Expression[] parameters, DynamicMetaObject[] args, out DynamicMetaObject deferredBinding)
{
ArgumentObject[] array = CreateArgumentArray(payload, parameters, args);
payload.PopulateSymbolTableWithName(array[0].Type, array);
AddConversionsForArguments(array);
Scope pScope = SymFactory.CreateScope();
LocalVariableSymbol[] locals = PopulateLocalScope(payload, pScope, array, parameters);
if (DeferBinding(payload, array, args, locals, out deferredBinding))
return null;
Expr pResult = payload.DispatchPayload(this, array, locals);
return CreateExpressionTreeFromResult(parameters, pScope, pResult);
}
private bool DeferBinding(ICSharpBinder payload, ArgumentObject[] arguments, DynamicMetaObject[] args, LocalVariableSymbol[] locals, out DynamicMetaObject deferredBinding)
{
CSharpInvokeMemberBinder cSharpInvokeMemberBinder = payload as CSharpInvokeMemberBinder;
if (cSharpInvokeMemberBinder != null) {
Type[] typeArguments = cSharpInvokeMemberBinder.TypeArguments;
int arity = (typeArguments != null) ? typeArguments.Length : 0;
MemberLookup mem = new MemberLookup();
Expr callingObject = CreateCallingObjectForCall(cSharpInvokeMemberBinder, arguments, locals);
SymWithType symWithType = SymbolTable.LookupMember(cSharpInvokeMemberBinder.Name, callingObject, _binder.Context.ContextForMemberLookup, arity, mem, (cSharpInvokeMemberBinder.Flags & CSharpCallFlags.EventHookup) != CSharpCallFlags.None, true);
if (symWithType != (SymWithType)null && symWithType.Sym.getKind() != SYMKIND.SK_MethodSymbol) {
CSharpGetMemberBinder cSharpGetMemberBinder = new CSharpGetMemberBinder(cSharpInvokeMemberBinder.Name, false, cSharpInvokeMemberBinder.CallingContext, new CSharpArgumentInfo[1] {
cSharpInvokeMemberBinder.GetArgumentInfo(0)
}).TryGetExisting();
CSharpArgumentInfo[] array = cSharpInvokeMemberBinder.ArgumentInfoArray();
array[0] = CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null);
CSharpInvokeBinder cSharpInvokeBinder = new CSharpInvokeBinder(cSharpInvokeMemberBinder.Flags, cSharpInvokeMemberBinder.CallingContext, array).TryGetExisting();
DynamicMetaObject[] array2 = new DynamicMetaObject[args.Length - 1];
Array.Copy(args, 1, array2, 0, args.Length - 1);
deferredBinding = cSharpInvokeBinder.Defer(cSharpGetMemberBinder.Defer(args[0], Array.Empty<DynamicMetaObject>()), array2);
return true;
}
}
deferredBinding = null;
return false;
}
private static Expression CreateExpressionTreeFromResult(Expression[] parameters, Scope pScope, Expr pResult)
{
ExprBoundLambda expr = GenerateBoundLambda(pScope, pResult);
ExprBinOp binOp = ExpressionTreeRewriter.Rewrite(expr);
return ExpressionTreeCallRewriter.Rewrite(binOp, parameters);
}
private Type GetArgumentType(ICSharpBinder p, CSharpArgumentInfo argInfo, Expression param, DynamicMetaObject arg, int index)
{
Type type = argInfo.UseCompileTimeType ? param.Type : arg.LimitType;
if (argInfo.IsByRefOrOut) {
if (index != 0 || !p.IsBinderThatCanHaveRefReceiver)
type = type.MakeByRefType();
} else if (!argInfo.UseCompileTimeType) {
CType cTypeFromType = SymbolTable.GetCTypeFromType(type);
CType bestAccessibleType = TypeManager.GetBestAccessibleType(_binder.Context.ContextForMemberLookup, cTypeFromType);
type = bestAccessibleType.AssociatedSystemType;
}
return type;
}
private ArgumentObject[] CreateArgumentArray(ICSharpBinder payload, Expression[] parameters, DynamicMetaObject[] args)
{
ArgumentObject[] array = new ArgumentObject[parameters.Length];
for (int i = 0; i < parameters.Length; i++) {
CSharpArgumentInfo argumentInfo = payload.GetArgumentInfo(i);
array[i] = new ArgumentObject(args[i].Value, argumentInfo, GetArgumentType(payload, argumentInfo, parameters[i], args[i], i));
}
return array;
}
internal static void PopulateSymbolTableWithPayloadInformation(ICSharpInvokeOrInvokeMemberBinder callOrInvoke, Type callingType, ArgumentObject[] arguments)
{
Type type;
if (callOrInvoke.StaticCall) {
type = (arguments[0].Value as Type);
if (type == (Type)null)
throw Error.BindStaticRequiresType(arguments[0].Info.Name);
} else
type = callingType;
SymbolTable.PopulateSymbolTableWithName(callOrInvoke.Name, callOrInvoke.TypeArguments, type);
if (callOrInvoke.Name.StartsWith("set_", StringComparison.Ordinal) || callOrInvoke.Name.StartsWith("get_", StringComparison.Ordinal))
SymbolTable.PopulateSymbolTableWithName(callOrInvoke.Name.Substring(4), callOrInvoke.TypeArguments, type);
}
private static void AddConversionsForArguments(ArgumentObject[] arguments)
{
foreach (ArgumentObject argumentObject in arguments) {
SymbolTable.AddConversionsForType(argumentObject.Type);
}
}
internal ExprWithArgs DispatchPayload(ICSharpInvokeOrInvokeMemberBinder payload, ArgumentObject[] arguments, LocalVariableSymbol[] locals)
{
return BindCall(payload, CreateCallingObjectForCall(payload, arguments, locals), arguments, locals);
}
private static LocalVariableSymbol[] PopulateLocalScope(ICSharpBinder payload, Scope pScope, ArgumentObject[] arguments, Expression[] parameterExpressions)
{
LocalVariableSymbol[] array = new LocalVariableSymbol[parameterExpressions.Length];
for (int i = 0; i < parameterExpressions.Length; i++) {
Expression expression = parameterExpressions[i];
CType cType = SymbolTable.GetCTypeFromType(expression.Type);
if (i != 0 || !payload.IsBinderThatCanHaveRefReceiver) {
ParameterExpression parameterExpression = expression as ParameterExpression;
if (parameterExpression != null && parameterExpression.IsByRef) {
CSharpArgumentInfo info = arguments[i].Info;
if (info.IsByRefOrOut)
cType = TypeManager.GetParameterModifier(cType, info.IsOut);
}
}
LocalVariableSymbol localVariableSymbol = array[i] = SymFactory.CreateLocalVar(NameManager.Add("p" + i.ToString()), pScope, cType);
}
return array;
}
private static ExprBoundLambda GenerateBoundLambda(Scope pScope, Expr call)
{
AggregateType predefindType = SymbolLoader.GetPredefindType(PredefinedType.PT_FUNC);
return ExprFactory.CreateAnonymousMethod(predefindType, pScope, call);
}
private Expr CreateLocal(Type type, bool isOut, LocalVariableSymbol local)
{
CType dest = (!isOut) ? SymbolTable.GetCTypeFromType(type) : TypeManager.GetParameterModifier(SymbolTable.GetCTypeFromType(type.GetElementType()), true);
ExprLocal expr = ExprFactory.CreateLocal(local);
Expr expr2 = _binder.tryConvert(expr, dest) ?? _binder.mustCast(expr, dest);
expr2.Flags |= EXPRFLAG.EXF_LVALUE;
return expr2;
}
internal Expr CreateArgumentListEXPR(ArgumentObject[] arguments, LocalVariableSymbol[] locals, int startIndex, int endIndex)
{
Expr first = null;
Expr last = null;
if (arguments != null) {
for (int i = startIndex; i < endIndex; i++) {
ArgumentObject argument = arguments[i];
Expr expr = CreateArgumentEXPR(argument, locals[i]);
if (first == null) {
first = expr;
last = first;
} else
ExprFactory.AppendItemToList(expr, ref first, ref last);
}
}
return first;
}
private Expr CreateArgumentEXPR(ArgumentObject argument, LocalVariableSymbol local)
{
Expr expr = argument.Info.LiteralConstant ? ((argument.Value != null) ? ExprFactory.CreateConstant(SymbolTable.GetCTypeFromType(argument.Type), ConstVal.Get(argument.Value)) : ((!argument.Info.UseCompileTimeType) ? ExprFactory.CreateNull() : ExprFactory.CreateConstant(SymbolTable.GetCTypeFromType(argument.Type), default(ConstVal)))) : ((argument.Info.UseCompileTimeType || argument.Value != null) ? CreateLocal(argument.Type, argument.Info.IsOut, local) : ExprFactory.CreateNull());
if (argument.Info.NamedArgument)
expr = ExprFactory.CreateNamedArgumentSpecification(NameManager.Add(argument.Info.Name), expr);
if (!argument.Info.UseCompileTimeType && argument.Value != null) {
expr.RuntimeObject = argument.Value;
expr.RuntimeObjectActualType = SymbolTable.GetCTypeFromType(argument.Value.GetType());
}
return expr;
}
private static ExprMemberGroup CreateMemberGroupExpr(string Name, Type[] typeArguments, Expr callingObject, SYMKIND kind)
{
Name name = NameManager.Add(Name);
CType type = callingObject.Type;
AggregateType aggregateType;
if (type is ArrayType)
aggregateType = SymbolLoader.GetPredefindType(PredefinedType.PT_ARRAY);
else {
NullableType nullableType = type as NullableType;
aggregateType = ((nullableType == null) ? ((AggregateType)type) : nullableType.GetAts());
}
HashSet<CType> hashSet = new HashSet<CType>();
List<CType> list = new List<CType>();
symbmask_t mask = symbmask_t.MASK_MethodSymbol;
switch (kind) {
case SYMKIND.SK_PropertySymbol:
case SYMKIND.SK_IndexerSymbol:
mask = symbmask_t.MASK_PropertySymbol;
break;
case SYMKIND.SK_MethodSymbol:
mask = symbmask_t.MASK_MethodSymbol;
break;
}
bool flag = name == NameManager.GetPredefinedName(PredefinedName.PN_CTOR);
foreach (AggregateType item in aggregateType.TypeHierarchy) {
if (SymbolTable.AggregateContainsMethod(item.OwningAggregate, Name, mask) && hashSet.Add(item))
list.Add(item);
if (flag)
break;
}
if (aggregateType.IsWindowsRuntimeType) {
CType[] items = aggregateType.WinRTCollectionIfacesAll.Items;
for (int i = 0; i < items.Length; i++) {
AggregateType aggregateType2 = (AggregateType)items[i];
if (SymbolTable.AggregateContainsMethod(aggregateType2.OwningAggregate, Name, mask) && hashSet.Add(aggregateType2))
list.Add(aggregateType2);
}
}
EXPRFLAG eXPRFLAG = EXPRFLAG.EXF_USERCALLABLE;
if (Name == "Invoke" && callingObject.Type.IsDelegateType)
eXPRFLAG |= EXPRFLAG.EXF_GOTONOTBLOCKED;
if (Name == ".ctor")
eXPRFLAG |= EXPRFLAG.EXF_CTOR;
if (Name == "$Item$")
eXPRFLAG |= EXPRFLAG.EXF_INDEXER;
TypeArray typeArgs = (typeArguments != null && typeArguments.Length != 0) ? TypeArray.Allocate(SymbolTable.GetCTypeArrayFromTypes(typeArguments)) : TypeArray.Empty;
ExprMemberGroup exprMemberGroup = ExprFactory.CreateMemGroup(eXPRFLAG, name, typeArgs, kind, aggregateType, null, new CMemberLookupResults(TypeArray.Allocate(list.ToArray()), name));
if (!(callingObject is ExprClass))
exprMemberGroup.OptionalObject = callingObject;
return exprMemberGroup;
}
private Expr CreateProperty(SymWithType swt, Expr callingObject, BindingFlag flags)
{
PropertySymbol propertySymbol = swt.Prop();
AggregateType type = swt.GetType();
PropWithType pwt = new PropWithType(propertySymbol, type);
ExprMemberGroup pMemGroup = CreateMemberGroupExpr(propertySymbol.name.Text, null, callingObject, SYMKIND.SK_PropertySymbol);
return _binder.BindToProperty((callingObject is ExprClass) ? null : callingObject, pwt, flags, null, pMemGroup);
}
private ExprWithArgs CreateIndexer(SymWithType swt, Expr callingObject, Expr arguments, BindingFlag bindFlags)
{
IndexerSymbol indexerSymbol = swt.Sym as IndexerSymbol;
ExprMemberGroup grp = CreateMemberGroupExpr(indexerSymbol.name.Text, null, callingObject, SYMKIND.SK_PropertySymbol);
ExprWithArgs result = _binder.BindMethodGroupToArguments(bindFlags, grp, arguments);
ReorderArgumentsForNamedAndOptional(callingObject, result);
return result;
}
private Expr CreateArray(Expr callingObject, Expr optionalIndexerArguments)
{
return _binder.BindArrayIndexCore(callingObject, optionalIndexerArguments);
}
private Expr CreateField(SymWithType swt, Expr callingObject)
{
FieldSymbol field = swt.Field();
AggregateType type = swt.GetType();
FieldWithType fwt = new FieldWithType(field, type);
return _binder.BindToField((callingObject is ExprClass) ? null : callingObject, fwt, (BindingFlag)0);
}
private Expr CreateCallingObjectForCall(ICSharpInvokeOrInvokeMemberBinder payload, ArgumentObject[] arguments, LocalVariableSymbol[] locals)
{
Expr expr;
if (payload.StaticCall) {
Type type = arguments[0].Value as Type;
expr = ExprFactory.CreateClass(SymbolTable.GetCTypeFromType(type));
} else {
if (!arguments[0].Info.UseCompileTimeType && arguments[0].Value == null)
throw Error.NullReferenceOnMemberException();
expr = _binder.mustConvert(CreateArgumentEXPR(arguments[0], locals[0]), SymbolTable.GetCTypeFromType(arguments[0].Type));
if (arguments[0].Type.IsValueType && expr is ExprCast)
expr.Flags |= EXPRFLAG.EXF_USERCALLABLE;
}
return expr;
}
private ExprWithArgs BindCall(ICSharpInvokeOrInvokeMemberBinder payload, Expr callingObject, ArgumentObject[] arguments, LocalVariableSymbol[] locals)
{
if (payload is InvokeBinder && !callingObject.Type.IsDelegateType)
throw Error.BindInvokeFailedNonDelegate();
Type[] typeArguments = payload.TypeArguments;
int arity = (typeArguments != null) ? typeArguments.Length : 0;
MemberLookup memberLookup = new MemberLookup();
string name = payload.Name;
BindingContext context = _binder.Context;
SymWithType symWithType = SymbolTable.LookupMember(name, callingObject, context.ContextForMemberLookup, arity, memberLookup, (payload.Flags & CSharpCallFlags.EventHookup) != CSharpCallFlags.None, true);
if (symWithType == (SymWithType)null)
throw memberLookup.ReportErrors();
if (symWithType.Sym.getKind() != SYMKIND.SK_MethodSymbol)
throw Error.InternalCompilerError();
ExprMemberGroup exprMemberGroup = CreateMemberGroupExpr(payload.Name, payload.TypeArguments, callingObject, symWithType.Sym.getKind());
if ((payload.Flags & CSharpCallFlags.SimpleNameCall) != 0)
callingObject.Flags |= EXPRFLAG.EXF_UNREALIZEDGOTO;
if ((payload.Flags & CSharpCallFlags.EventHookup) != 0) {
memberLookup = new MemberLookup();
string name2 = payload.Name.Split(new char[1] {
'_'
})[1];
context = _binder.Context;
SymWithType symWithType2 = SymbolTable.LookupMember(name2, callingObject, context.ContextForMemberLookup, arity, memberLookup, (payload.Flags & CSharpCallFlags.EventHookup) != CSharpCallFlags.None, true);
if (symWithType2 == (SymWithType)null)
throw memberLookup.ReportErrors();
CType typeSrc = null;
if (symWithType2.Sym.getKind() == SYMKIND.SK_FieldSymbol)
typeSrc = symWithType2.Field().GetType();
else if (symWithType2.Sym.getKind() == SYMKIND.SK_EventSymbol) {
typeSrc = symWithType2.Event().type;
}
Type associatedSystemType = TypeManager.SubstType(typeSrc, symWithType2.Ats).AssociatedSystemType;
if (associatedSystemType != (Type)null)
BindImplicitConversion(new ArgumentObject[1] {
arguments[1]
}, associatedSystemType, locals, false);
exprMemberGroup.Flags &= ~EXPRFLAG.EXF_USERCALLABLE;
if (symWithType2.Sym.getKind() == SYMKIND.SK_EventSymbol && symWithType2.Event().IsWindowsRuntimeEvent)
return BindWinRTEventAccessor(new EventWithType(symWithType2.Event(), symWithType2.Ats), callingObject, arguments, locals, payload.Name.StartsWith("add_", StringComparison.Ordinal));
}
if ((payload.Name.StartsWith("set_", StringComparison.Ordinal) && ((MethodSymbol)symWithType.Sym).Params.Count > 1) || (payload.Name.StartsWith("get_", StringComparison.Ordinal) && ((MethodSymbol)symWithType.Sym).Params.Count > 0))
exprMemberGroup.Flags &= ~EXPRFLAG.EXF_USERCALLABLE;
ExprCall exprCall = _binder.BindMethodGroupToArguments(BindingFlag.BIND_RVALUEREQUIRED | BindingFlag.BIND_STMTEXPRONLY, exprMemberGroup, CreateArgumentListEXPR(arguments, locals, 1, arguments.Length)) as ExprCall;
CheckForConditionalMethodError(exprCall);
ReorderArgumentsForNamedAndOptional(callingObject, exprCall);
return exprCall;
}
private ExprWithArgs BindWinRTEventAccessor(EventWithType ewt, Expr callingObject, ArgumentObject[] arguments, LocalVariableSymbol[] locals, bool isAddAccessor)
{
Type associatedSystemType = ewt.Event().type.AssociatedSystemType;
MethPropWithInst method = new MethPropWithInst(ewt.Event().methRemove, ewt.Ats);
ExprMemberGroup exprMemberGroup = ExprFactory.CreateMemGroup(callingObject, method);
exprMemberGroup.Flags &= ~EXPRFLAG.EXF_USERCALLABLE;
Type eventRegistrationTokenType = SymbolTable.EventRegistrationTokenType;
Type actionType = Expression.GetActionType(eventRegistrationTokenType);
Expr expr = _binder.mustConvert(exprMemberGroup, SymbolTable.GetCTypeFromType(actionType));
Expr expr2 = CreateArgumentEXPR(arguments[1], locals[1]);
ExprList args;
string text;
if (isAddAccessor) {
MethPropWithInst method2 = new MethPropWithInst(ewt.Event().methAdd, ewt.Ats);
ExprMemberGroup exprMemberGroup2 = ExprFactory.CreateMemGroup(callingObject, method2);
exprMemberGroup2.Flags &= ~EXPRFLAG.EXF_USERCALLABLE;
Type funcType = Expression.GetFuncType(associatedSystemType, eventRegistrationTokenType);
Expr op = _binder.mustConvert(exprMemberGroup2, SymbolTable.GetCTypeFromType(funcType));
args = ExprFactory.CreateList(op, expr, expr2);
text = NameManager.GetPredefinedName(PredefinedName.PN_ADDEVENTHANDLER).Text;
} else {
args = ExprFactory.CreateList(expr, expr2);
text = NameManager.GetPredefinedName(PredefinedName.PN_REMOVEEVENTHANDLER).Text;
}
Type windowsRuntimeMarshalType = SymbolTable.WindowsRuntimeMarshalType;
SymbolTable.PopulateSymbolTableWithName(text, new List<Type> {
associatedSystemType
}, windowsRuntimeMarshalType);
ExprClass callingObject2 = ExprFactory.CreateClass(SymbolTable.GetCTypeFromType(windowsRuntimeMarshalType));
ExprMemberGroup grp = CreateMemberGroupExpr(text, new Type[1] {
associatedSystemType
}, callingObject2, SYMKIND.SK_MethodSymbol);
return _binder.BindMethodGroupToArguments(BindingFlag.BIND_RVALUEREQUIRED | BindingFlag.BIND_STMTEXPRONLY, grp, args);
}
private static void CheckForConditionalMethodError(ExprCall call)
{
MethodSymbol methodSymbol = call.MethWithInst.Meth();
object[] customAttributes = methodSymbol.AssociatedMemberInfo.GetCustomAttributes(typeof(ConditionalAttribute), true);
if (customAttributes.Length != 0)
throw Error.BindCallToConditionalMethod(methodSymbol.name);
}
private void ReorderArgumentsForNamedAndOptional(Expr callingObject, ExprWithArgs result)
{
Expr optionalArguments = result.OptionalArguments;
ExprCall exprCall = result as ExprCall;
AggregateType ats;
ExprMemberGroup memberGroup;
TypeArray typeArgsMeth;
MethodOrPropertySymbol methodOrPropertySymbol;
if (exprCall != null) {
ats = exprCall.MethWithInst.Ats;
methodOrPropertySymbol = exprCall.MethWithInst.Meth();
memberGroup = exprCall.MemberGroup;
typeArgsMeth = exprCall.MethWithInst.TypeArgs;
} else {
ExprProperty exprProperty = result as ExprProperty;
ats = exprProperty.PropWithTypeSlot.Ats;
methodOrPropertySymbol = exprProperty.PropWithTypeSlot.Prop();
memberGroup = exprProperty.MemberGroup;
typeArgsMeth = null;
}
ArgInfos argInfos = new ArgInfos {
carg = ExpressionBinder.CountArguments(optionalArguments)
};
ExpressionBinder.FillInArgInfoFromArgList(argInfos, optionalArguments);
TypeArray typeArray = TypeManager.SubstTypeArray(methodOrPropertySymbol.Params, ats, typeArgsMeth);
methodOrPropertySymbol = ExpressionBinder.GroupToArgsBinder.FindMostDerivedMethod(methodOrPropertySymbol, callingObject.Type);
ExpressionBinder.GroupToArgsBinder.ReOrderArgsForNamedArguments(methodOrPropertySymbol, typeArray, ats, memberGroup, argInfos);
Expr expr = null;
for (int num = argInfos.carg - 1; num >= 0; num--) {
Expr pArg = argInfos.prgexpr[num];
pArg = StripNamedArgument(pArg);
pArg = _binder.tryConvert(pArg, typeArray[num]);
expr = ((expr == null) ? pArg : ExprFactory.CreateList(pArg, expr));
}
result.OptionalArguments = expr;
}
private Expr StripNamedArgument(Expr pArg)
{
ExprNamedArgumentSpecification exprNamedArgumentSpecification = pArg as ExprNamedArgumentSpecification;
if (exprNamedArgumentSpecification != null)
pArg = exprNamedArgumentSpecification.Value;
else {
ExprArrayInit exprArrayInit = pArg as ExprArrayInit;
if (exprArrayInit != null)
exprArrayInit.OptionalArguments = StripNamedArguments(exprArrayInit.OptionalArguments);
}
return pArg;
}
private Expr StripNamedArguments(Expr pArg)
{
ExprList exprList = pArg as ExprList;
if (exprList != null) {
while (true) {
exprList.OptionalElement = StripNamedArgument(exprList.OptionalElement);
ExprList exprList2 = exprList.OptionalNextListNode as ExprList;
if (exprList2 == null)
break;
exprList = exprList2;
}
exprList.OptionalNextListNode = StripNamedArgument(exprList.OptionalNextListNode);
}
return StripNamedArgument(pArg);
}
internal Expr BindUnaryOperation(CSharpUnaryOperationBinder payload, ArgumentObject[] arguments, LocalVariableSymbol[] locals)
{
OperatorKind operatorKind = GetOperatorKind(payload.Operation);
Expr expr = CreateArgumentEXPR(arguments[0], locals[0]);
expr.ErrorString = Operators.GetDisplayName(GetOperatorKind(payload.Operation));
if (operatorKind == OperatorKind.OP_TRUE || operatorKind == OperatorKind.OP_FALSE) {
Expr expr2 = _binder.tryConvert(expr, SymbolLoader.GetPredefindType(PredefinedType.PT_BOOL));
if (expr2 != null && operatorKind == OperatorKind.OP_FALSE)
expr2 = _binder.BindStandardUnaryOperator(OperatorKind.OP_LOGNOT, expr2);
return expr2 ?? _binder.bindUDUnop((operatorKind == OperatorKind.OP_TRUE) ? ExpressionKind.True : ExpressionKind.False, expr) ?? _binder.mustConvert(expr, SymbolLoader.GetPredefindType(PredefinedType.PT_BOOL));
}
return _binder.BindStandardUnaryOperator(operatorKind, expr);
}
internal Expr BindBinaryOperation(CSharpBinaryOperationBinder payload, ArgumentObject[] arguments, LocalVariableSymbol[] locals)
{
ExpressionKind expressionKind = Operators.GetExpressionKind(GetOperatorKind(payload.Operation, payload.IsLogicalOperation));
Expr expr = CreateArgumentEXPR(arguments[0], locals[0]);
Expr expr2 = CreateArgumentEXPR(arguments[1], locals[1]);
expr.ErrorString = Operators.GetDisplayName(GetOperatorKind(payload.Operation, payload.IsLogicalOperation));
expr2.ErrorString = Operators.GetDisplayName(GetOperatorKind(payload.Operation, payload.IsLogicalOperation));
if (expressionKind > ExpressionKind.MultiOffset)
expressionKind -= 71;
return _binder.BindStandardBinop(expressionKind, expr, expr2);
}
private static OperatorKind GetOperatorKind(ExpressionType p)
{
return GetOperatorKind(p, false);
}
private static OperatorKind GetOperatorKind(ExpressionType p, bool bIsLogical)
{
switch (p) {
default:
throw Error.InternalCompilerError();
case ExpressionType.Add:
return OperatorKind.OP_ADD;
case ExpressionType.Subtract:
return OperatorKind.OP_SUB;
case ExpressionType.Multiply:
return OperatorKind.OP_MUL;
case ExpressionType.Divide:
return OperatorKind.OP_DIV;
case ExpressionType.Modulo:
return OperatorKind.OP_MOD;
case ExpressionType.LeftShift:
return OperatorKind.OP_LSHIFT;
case ExpressionType.RightShift:
return OperatorKind.OP_RSHIFT;
case ExpressionType.LessThan:
return OperatorKind.OP_LT;
case ExpressionType.GreaterThan:
return OperatorKind.OP_GT;
case ExpressionType.LessThanOrEqual:
return OperatorKind.OP_LE;
case ExpressionType.GreaterThanOrEqual:
return OperatorKind.OP_GE;
case ExpressionType.Equal:
return OperatorKind.OP_EQ;
case ExpressionType.NotEqual:
return OperatorKind.OP_NEQ;
case ExpressionType.And:
if (!bIsLogical)
return OperatorKind.OP_BITAND;
return OperatorKind.OP_LOGAND;
case ExpressionType.ExclusiveOr:
return OperatorKind.OP_BITXOR;
case ExpressionType.Or:
if (!bIsLogical)
return OperatorKind.OP_BITOR;
return OperatorKind.OP_LOGOR;
case ExpressionType.AddAssign:
return OperatorKind.OP_ADDEQ;
case ExpressionType.SubtractAssign:
return OperatorKind.OP_SUBEQ;
case ExpressionType.MultiplyAssign:
return OperatorKind.OP_MULEQ;
case ExpressionType.DivideAssign:
return OperatorKind.OP_DIVEQ;
case ExpressionType.ModuloAssign:
return OperatorKind.OP_MODEQ;
case ExpressionType.AndAssign:
return OperatorKind.OP_ANDEQ;
case ExpressionType.ExclusiveOrAssign:
return OperatorKind.OP_XOREQ;
case ExpressionType.OrAssign:
return OperatorKind.OP_OREQ;
case ExpressionType.LeftShiftAssign:
return OperatorKind.OP_LSHIFTEQ;
case ExpressionType.RightShiftAssign:
return OperatorKind.OP_RSHIFTEQ;
case ExpressionType.Negate:
return OperatorKind.OP_NEG;
case ExpressionType.UnaryPlus:
return OperatorKind.OP_UPLUS;
case ExpressionType.Not:
return OperatorKind.OP_LOGNOT;
case ExpressionType.OnesComplement:
return OperatorKind.OP_BITNOT;
case ExpressionType.IsTrue:
return OperatorKind.OP_TRUE;
case ExpressionType.IsFalse:
return OperatorKind.OP_FALSE;
case ExpressionType.Increment:
return OperatorKind.OP_PREINC;
case ExpressionType.Decrement:
return OperatorKind.OP_PREDEC;
}
}
internal Expr BindProperty(ICSharpBinder payload, ArgumentObject argument, LocalVariableSymbol local, Expr optionalIndexerArguments)
{
Expr expr = argument.Info.IsStaticType ? ExprFactory.CreateClass(SymbolTable.GetCTypeFromType(argument.Value as Type)) : CreateLocal(argument.Type, argument.Info.IsOut, local);
if (!argument.Info.UseCompileTimeType && argument.Value == null)
throw Error.NullReferenceOnMemberException();
if (argument.Type.IsValueType && expr is ExprCast)
expr.Flags |= EXPRFLAG.EXF_USERCALLABLE;
string name = payload.Name;
BindingFlag bindingFlags = payload.BindingFlags;
MemberLookup memberLookup = new MemberLookup();
SymWithType symWithType = SymbolTable.LookupMember(name, expr, _binder.Context.ContextForMemberLookup, 0, memberLookup, false, false);
if (!(symWithType == (SymWithType)null)) {
switch (symWithType.Sym.getKind()) {
case SYMKIND.SK_MethodSymbol:
throw Error.BindPropertyFailedMethodGroup(name);
case SYMKIND.SK_PropertySymbol:
if (symWithType.Sym is IndexerSymbol)
return CreateIndexer(symWithType, expr, optionalIndexerArguments, bindingFlags);
expr.Flags |= EXPRFLAG.EXF_LVALUE;
return CreateProperty(symWithType, expr, payload.BindingFlags);
case SYMKIND.SK_FieldSymbol:
return CreateField(symWithType, expr);
case SYMKIND.SK_EventSymbol:
throw Error.BindPropertyFailedEvent(name);
default:
throw Error.InternalCompilerError();
}
}
if (optionalIndexerArguments != null) {
int num = ExpressionIterator.Count(optionalIndexerArguments);
Type type = argument.Type;
if (type.IsArray) {
if (type.IsArray && type.GetArrayRank() != num)
throw ErrorHandling.Error(ErrorCode.ERR_BadIndexCount, type.GetArrayRank());
return CreateArray(expr, optionalIndexerArguments);
}
}
throw memberLookup.ReportErrors();
}
internal Expr BindImplicitConversion(ArgumentObject[] arguments, Type returnType, LocalVariableSymbol[] locals, bool bIsArrayCreationConversion)
{
SymbolTable.AddConversionsForType(returnType);
Expr expr = CreateArgumentEXPR(arguments[0], locals[0]);
CType cTypeFromType = SymbolTable.GetCTypeFromType(returnType);
if (bIsArrayCreationConversion) {
CType dest = _binder.ChooseArrayIndexType(expr);
return _binder.mustCast(_binder.mustConvert(expr, dest), cTypeFromType, CONVERTTYPE.NOUDC | CONVERTTYPE.CHECKOVERFLOW);
}
return _binder.mustConvert(expr, cTypeFromType);
}
internal Expr BindExplicitConversion(ArgumentObject[] arguments, Type returnType, LocalVariableSymbol[] locals)
{
SymbolTable.AddConversionsForType(returnType);
Expr expr = CreateArgumentEXPR(arguments[0], locals[0]);
CType cTypeFromType = SymbolTable.GetCTypeFromType(returnType);
return _binder.mustCast(expr, cTypeFromType);
}
internal Expr BindAssignment(ICSharpBinder payload, ArgumentObject[] arguments, LocalVariableSymbol[] locals)
{
string name = payload.Name;
CSharpSetIndexBinder cSharpSetIndexBinder = payload as CSharpSetIndexBinder;
Expr optionalIndexerArguments;
bool isCompoundAssignment;
if (cSharpSetIndexBinder != null) {
optionalIndexerArguments = CreateArgumentListEXPR(arguments, locals, 1, arguments.Length - 1);
isCompoundAssignment = cSharpSetIndexBinder.IsCompoundAssignment;
} else {
optionalIndexerArguments = null;
isCompoundAssignment = (payload as CSharpSetMemberBinder).IsCompoundAssignment;
}
SymbolTable.PopulateSymbolTableWithName(name, null, arguments[0].Type);
Expr op = BindProperty(payload, arguments[0], locals[0], optionalIndexerArguments);
int num = arguments.Length - 1;
Expr op2 = CreateArgumentEXPR(arguments[num], locals[num]);
return _binder.BindAssignment(op, op2, isCompoundAssignment);
}
internal Expr BindIsEvent(CSharpIsEventBinder binder, ArgumentObject[] arguments, LocalVariableSymbol[] locals)
{
Expr callingObject = CreateLocal(arguments[0].Type, false, locals[0]);
MemberLookup mem = new MemberLookup();
CType predefindType = SymbolLoader.GetPredefindType(PredefinedType.PT_BOOL);
bool value = false;
if (arguments[0].Value == null)
throw Error.NullReferenceOnMemberException();
SymWithType symWithType = SymbolTable.LookupMember(binder.Name, callingObject, _binder.Context.ContextForMemberLookup, 0, mem, false, false);
if (symWithType != (SymWithType)null) {
if (symWithType.Sym.getKind() == SYMKIND.SK_EventSymbol)
value = true;
else {
FieldSymbol fieldSymbol = symWithType.Sym as FieldSymbol;
if (fieldSymbol != null && fieldSymbol.isEvent)
value = true;
}
}
return ExprFactory.CreateConstant(predefindType, ConstVal.Get(value));
}
}
}