protected override Expression DoResolve(ResolveContext ec)
{
right = right.Resolve(ec);
if (right == null)
{
return(null);
}
MemberAccess ma = target as MemberAccess;
using (ec.Set(ResolveContext.Options.CompoundAssignmentScope)) {
target = target.Resolve(ec);
}
if (target == null)
{
return(null);
}
if (target is MethodGroupExpr)
{
ec.Report.Error(1656, loc,
"Cannot assign to `{0}' because it is a `{1}'",
((MethodGroupExpr)target).Name, target.ExprClassName);
return(null);
}
var event_expr = target as EventExpr;
if (event_expr != null)
{
source = Convert.ImplicitConversionRequired(ec, right, target.Type, loc);
if (source == null)
{
return(null);
}
Expression rside;
if (op == Binary.Operator.Addition)
{
rside = EmptyExpression.EventAddition;
}
else if (op == Binary.Operator.Subtraction)
{
rside = EmptyExpression.EventSubtraction;
}
else
{
rside = null;
}
target = target.ResolveLValue(ec, rside);
if (target == null)
{
return(null);
}
eclass = ExprClass.Value;
type = event_expr.Operator.ReturnType;
return(this);
}
//
// Only now we can decouple the original source/target
// into a tree, to guarantee that we do not have side
// effects.
//
if (left == null)
{
left = new TargetExpression(target);
}
source = new Binary(op, left, right, true, loc);
if (target is DynamicMemberAssignable)
{
Arguments targs = ((DynamicMemberAssignable)target).Arguments;
source = source.Resolve(ec);
Arguments args = new Arguments(targs.Count + 1);
args.AddRange(targs);
args.Add(new Argument(source));
var binder_flags = CSharpBinderFlags.ValueFromCompoundAssignment;
//
// Compound assignment does target conversion using additional method
// call, set checked context as the binary operation can overflow
//
if (ec.HasSet(ResolveContext.Options.CheckedScope))
{
binder_flags |= CSharpBinderFlags.CheckedContext;
}
if (target is DynamicMemberBinder)
{
source = new DynamicMemberBinder(ma.Name, binder_flags, args, loc).Resolve(ec);
// Handles possible event addition/subtraction
if (op == Binary.Operator.Addition || op == Binary.Operator.Subtraction)
{
args = new Arguments(targs.Count + 1);
args.AddRange(targs);
args.Add(new Argument(right));
string method_prefix = op == Binary.Operator.Addition ?
Event.AEventAccessor.AddPrefix : Event.AEventAccessor.RemovePrefix;
var invoke = DynamicInvocation.CreateSpecialNameInvoke(
new MemberAccess(right, method_prefix + ma.Name, loc), args, loc).Resolve(ec);
args = new Arguments(targs.Count);
args.AddRange(targs);
source = new DynamicEventCompoundAssign(ma.Name, args,
(ExpressionStatement)source, (ExpressionStatement)invoke, loc).Resolve(ec);
}
}
else
{
source = new DynamicIndexBinder(binder_flags, args, loc).Resolve(ec);
}
return(source);
}
return(base.DoResolve(ec));
}