this.Expr = expr;
}
- public TypeSpec Type {
- get { return Expr.Type; }
+ #region Properties
+
+ public bool IsByRef {
+ get { return ArgType == AType.Ref || ArgType == AType.Out; }
+ }
+
+ public bool IsDefaultArgument {
+ get { return ArgType == AType.Default; }
}
public Parameter.Modifier Modifier {
}
}
+ public TypeSpec Type {
+ get { return Expr.Type; }
+ }
+
+ #endregion
+
+ public Argument Clone (Expression expr)
+ {
+ Argument a = (Argument) MemberwiseClone ();
+ a.Expr = expr;
+ return a;
+ }
+
+ public Argument Clone (CloneContext clonectx)
+ {
+ return Clone (Expr.Clone (clonectx));
+ }
+
public virtual Expression CreateExpressionTree (ResolveContext ec)
{
if (ArgType == AType.Default)
return TypeManager.CSharpName (Expr.Type);
}
- public bool IsByRef {
- get { return ArgType == AType.Ref || ArgType == AType.Out; }
- }
-
- public bool IsDefaultArgument {
- get { return ArgType == AType.Default; }
- }
-
public bool ResolveMethodGroup (ResolveContext ec)
{
SimpleName sn = Expr as SimpleName;
IMemoryLocation ml = (IMemoryLocation) Expr;
ml.AddressOf (ec, mode);
}
-
- public Argument Clone (CloneContext clonectx)
- {
- Argument a = (Argument) MemberwiseClone ();
- a.Expr = Expr.Clone (clonectx);
- return a;
- }
}
public class NamedArgument : Argument
if (!dup_args)
continue;
- if (a.Expr is Constant) {
+ if (a.Expr is Constant || a.Expr is This) {
//
// No need to create a temporary variable for constants
//
class DynamicIndexBinder : DynamicMemberAssignable
{
+ bool can_be_mutator;
+
public DynamicIndexBinder (Arguments args, Location loc)
: base (args, loc)
{
base.flags = flags;
}
+ protected override Expression DoResolve (ResolveContext ec)
+ {
+ can_be_mutator = true;
+ return base.DoResolve (ec);
+ }
+
protected override Expression CreateCallSiteBinder (ResolveContext ec, Arguments args, bool isSet)
{
Arguments binder_args = new Arguments (3);
isSet |= (flags & CSharpBinderFlags.ValueFromCompoundAssignment) != 0;
return new Invocation (GetBinder (isSet ? "SetIndex" : "GetIndex", loc), binder_args);
}
+
+ protected override Arguments CreateSetterArguments (ResolveContext rc, Expression rhs)
+ {
+ //
+ // Indexer has arguments which complicates things as the setter and getter
+ // are called in two steps when unary mutator is used. We have to make a
+ // copy of all variable arguments to not duplicate any side effect.
+ //
+ // ++d[++arg, Foo ()]
+ //
+
+ if (!can_be_mutator)
+ return base.CreateSetterArguments (rc, rhs);
+
+ var setter_args = new Arguments (Arguments.Count + 1);
+ for (int i = 0; i < Arguments.Count; ++i) {
+ var expr = Arguments[i].Expr;
+
+ if (expr is Constant || expr is VariableReference || expr is This) {
+ setter_args.Add (Arguments [i]);
+ continue;
+ }
+
+ LocalVariable temp = LocalVariable.CreateCompilerGenerated (expr.Type, rc.CurrentBlock, loc);
+ expr = new SimpleAssign (temp.CreateReferenceExpression (rc, expr.Location), expr).Resolve (rc);
+ Arguments[i].Expr = temp.CreateReferenceExpression (rc, expr.Location).Resolve (rc);
+ setter_args.Add (Arguments [i].Clone (expr));
+ }
+
+ setter_args.Add (new Argument (rhs));
+ return setter_args;
+ }
}
class DynamicInvocation : DynamicExpressionStatement, IDynamicBinder
protected abstract Expression CreateCallSiteBinder (ResolveContext ec, Arguments args, bool isSet);
+ protected virtual Arguments CreateSetterArguments (ResolveContext rc, Expression rhs)
+ {
+ var setter_args = new Arguments (Arguments.Count + 1);
+ setter_args.AddRange (Arguments);
+ setter_args.Add (new Argument (rhs));
+ return setter_args;
+ }
+
public override Expression DoResolveLValue (ResolveContext rc, Expression right_side)
{
if (right_side == EmptyExpression.OutAccess.Instance) {
}
if (DoResolveCore (rc)) {
- setter_args = new Arguments (Arguments.Count + 1);
- setter_args.AddRange (Arguments);
- setter_args.Add (new Argument (right_side));
+ setter_args = CreateSetterArguments (rc, right_side);
setter = CreateCallSiteBinder (rc, setter_args, true);
}