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; }
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); 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); }
public override Expression DoResolveLValue(ResolveContext rc, Expression right_side) { if (right_side == EmptyExpression.OutAccess.Instance) { right_side.DoResolveLValue (rc, this); return null; } if (DoResolveCore (rc)) { setter_args = new Arguments (Arguments.Count + 1); setter_args.AddRange (Arguments); setter_args.Add (new Argument (right_side)); setter = CreateCallSiteBinder (rc, setter_args, true); } eclass = ExprClass.Variable; return this; }
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; }
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)); }
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; } if (target is EventExpr) return new EventAddOrRemove (target, op, right, loc).Resolve (ec); // // 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 DynamicMemberBinder) { Arguments targs = ((DynamicMemberBinder) target).Arguments; source = source.Resolve (ec); Arguments args = new Arguments (2); args.AddRange (targs); args.Add (new Argument (source)); source = new DynamicMemberBinder (ma.Name, args, loc).ResolveLValue (ec, right); // Handles possible event addition/subtraction if (op == Binary.Operator.Addition || op == Binary.Operator.Subtraction) { args = new Arguments (2); 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 (1); args.AddRange (targs); source = new DynamicEventCompoundAssign (ma.Name, args, (ExpressionStatement) source, (ExpressionStatement) invoke, loc).Resolve (ec); } return source; } return base.DoResolve (ec); }
/// /// Determines if the candidate method is applicable (section 14.4.2.1) /// to the given set of arguments /// A return value rates candidate method compatibility, /// 0 = the best, int.MaxValue = the worst /// public int IsApplicable(ResolveContext ec, ref Arguments arguments, int arg_count, ref MethodSpec method, ref bool params_expanded_form) { var candidate = method; AParametersCollection pd = candidate.Parameters; int param_count = GetApplicableParametersCount (candidate, pd); int optional_count = 0; if (arg_count != param_count) { for (int i = 0; i < pd.Count; ++i) { if (pd.FixedParameters [i].HasDefaultValue) { optional_count = pd.Count - i; break; } } int args_gap = System.Math.Abs (arg_count - param_count); if (optional_count != 0) { if (args_gap > optional_count) return int.MaxValue - 10000 + args_gap - optional_count; // Readjust expected number when params used if (pd.HasParams) { optional_count--; if (arg_count < param_count) param_count--; } else if (arg_count > param_count) { return int.MaxValue - 10000 + args_gap; } } else if (arg_count != param_count) { if (!pd.HasParams) return int.MaxValue - 10000 + args_gap; if (arg_count < param_count - 1) return int.MaxValue - 10000 + args_gap; } // Initialize expanded form of a method with 1 params parameter params_expanded_form = param_count == 1 && pd.HasParams; // Resize to fit optional arguments if (optional_count != 0) { Arguments resized; if (arguments == null) { resized = new Arguments (optional_count); } else { resized = new Arguments (param_count); resized.AddRange (arguments); } for (int i = arg_count; i < param_count; ++i) resized.Add (null); arguments = resized; } } if (arg_count > 0) { // // Shuffle named arguments to the right positions if there are any // if (arguments [arg_count - 1] is NamedArgument) { arg_count = arguments.Count; for (int i = 0; i < arg_count; ++i) { bool arg_moved = false; while (true) { NamedArgument na = arguments[i] as NamedArgument; if (na == null) break; int index = pd.GetParameterIndexByName (na.Name); // Named parameter not found or already reordered if (index <= i) break; // When using parameters which should not be available to the user if (index >= param_count) break; if (!arg_moved) { arguments.MarkReorderedArgument (na); arg_moved = true; } Argument temp = arguments[index]; arguments[index] = arguments[i]; arguments[i] = temp; if (temp == null) break; } } } else { arg_count = arguments.Count; } } else if (arguments != null) { arg_count = arguments.Count; } // // 1. Handle generic method using type arguments when specified or type inference // if (candidate.IsGeneric) { if (type_arguments != null) { var g_args_count = candidate.Arity; if (g_args_count != type_arguments.Count) return int.MaxValue - 20000 + System.Math.Abs (type_arguments.Count - g_args_count); method = candidate.MakeGenericMethod (type_arguments.Arguments); candidate = method; pd = candidate.Parameters; } else { int score = TypeManager.InferTypeArguments (ec, arguments, ref candidate); if (score != 0) return score - 20000; pd = candidate.Parameters; } } else { if (type_arguments != null) return int.MaxValue - 15000; } // // 2. Each argument has to be implicitly convertible to method parameter // method = candidate; Parameter.Modifier p_mod = 0; TypeSpec pt = null; for (int i = 0; i < arg_count; i++) { Argument a = arguments [i]; if (a == null) { if (!pd.FixedParameters [i].HasDefaultValue) throw new InternalErrorException (); Expression e = pd.FixedParameters [i].DefaultValue as Constant; if (e == null) e = new DefaultValueExpression (new TypeExpression (pd.Types [i], loc), loc).Resolve (ec); arguments [i] = new Argument (e, Argument.AType.Default); continue; } if (p_mod != Parameter.Modifier.PARAMS) { p_mod = pd.FixedParameters [i].ModFlags & ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK); pt = pd.Types [i]; } else { params_expanded_form = true; } Parameter.Modifier a_mod = a.Modifier & ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK); int score = 1; if (!params_expanded_form) score = IsArgumentCompatible (ec, a_mod, a, p_mod & ~Parameter.Modifier.PARAMS, pt); if (score != 0 && (p_mod & Parameter.Modifier.PARAMS) != 0 && delegate_type == null) { // It can be applicable in expanded form score = IsArgumentCompatible (ec, a_mod, a, 0, TypeManager.GetElementType (pt)); if (score == 0) params_expanded_form = true; } if (score != 0) { if (params_expanded_form) ++score; return (arg_count - i) * 2 + score; } } if (arg_count != param_count) params_expanded_form = true; return 0; }
Expression ResolveAccessor (ResolveContext ec, Expression right_side) { CommonResolve (ec); bool dynamic; arguments.Resolve (ec, out dynamic); if (dynamic || TypeManager.IsDynamicType (indexer_type)) { int additional = right_side == null ? 1 : 2; Arguments args = new Arguments (arguments.Count + additional); if (is_base_indexer) { ec.Report.Error (1972, loc, "The indexer base access cannot be dynamically dispatched. Consider casting the dynamic arguments or eliminating the base access"); } else { args.Add (new Argument (instance_expr)); } args.AddRange (arguments); if (right_side != null) args.Add (new Argument (right_side)); return new DynamicIndexBinder (right_side != null, args, loc).Resolve (ec); } Indexers ilist = Indexers.GetIndexersForType (current_type, indexer_type); if (ilist.Methods == null) { ec.Report.Error (21, loc, "Cannot apply indexing with [] to an expression of type `{0}'", TypeManager.CSharpName (indexer_type)); return null; } MethodGroupExpr mg = new IndexerMethodGroupExpr (ilist, loc); mg = mg.OverloadResolve (ec, ref arguments, false, loc); if (mg == null) return null; MethodInfo mi = (MethodInfo) mg; PropertyInfo pi = null; for (int i = 0; i < ilist.Methods.Count; ++i) { if (ilist.Methods [i] == mi) { pi = (PropertyInfo) ilist.Properties [i]; break; } } type = TypeManager.TypeToCoreType (pi.PropertyType); if (type.IsPointer && !ec.IsUnsafe) UnsafeError (ec, loc); MethodInfo accessor; if (right_side == null) { accessor = get = pi.GetGetMethod (true); } else { accessor = set = pi.GetSetMethod (true); if (accessor == null && pi.GetGetMethod (true) != null) { ec.Report.SymbolRelatedToPreviousError (pi); ec.Report.Error (200, loc, "The read only property or indexer `{0}' cannot be assigned to", TypeManager.GetFullNameSignature (pi)); return null; } set_expr = Convert.ImplicitConversion (ec, right_side, type, loc); } if (accessor == null) { ec.Report.SymbolRelatedToPreviousError (pi); ec.Report.Error (154, loc, "The property or indexer `{0}' cannot be used in this context because it lacks a `{1}' accessor", TypeManager.GetFullNameSignature (pi), GetAccessorName (right_side != null)); return null; } // // Only base will allow this invocation to happen. // if (accessor.IsAbstract && this is BaseIndexerAccess) { Error_CannotCallAbstractBase (ec, TypeManager.GetFullNameSignature (pi)); } bool must_do_cs1540_check; if (!IsAccessorAccessible (ec.CurrentType, accessor, out must_do_cs1540_check)) { if (set == null) set = pi.GetSetMethod (true); else get = pi.GetGetMethod (true); if (set != null && get != null && (set.Attributes & MethodAttributes.MemberAccessMask) != (get.Attributes & MethodAttributes.MemberAccessMask)) { ec.Report.SymbolRelatedToPreviousError (accessor); ec.Report.Error (271, loc, "The property or indexer `{0}' cannot be used in this context because a `{1}' accessor is inaccessible", TypeManager.GetFullNameSignature (pi), GetAccessorName (right_side != null)); } else { ec.Report.SymbolRelatedToPreviousError (pi); ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (pi), ec.Report); } } instance_expr.CheckMarshalByRefAccess (ec); eclass = ExprClass.IndexerAccess; return this; }
public 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); } if (target is EventExpr) { return(new EventAddOrRemove(target, op, right, loc).DoResolve(ec)); } // // 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); // TODO: TargetExpression breaks MemberAccess composition if (target is DynamicMemberBinder) { Arguments targs = ((DynamicMemberBinder)target).Arguments; source = source.Resolve(ec); Arguments args = new Arguments(2); args.AddRange(targs); args.Add(new Argument(source)); source = new DynamicMemberBinder(true, ma.Name, args, loc).Resolve(ec); // Handles possible event addition/subtraction if (op == Binary.Operator.Addition || op == Binary.Operator.Subtraction) { args = new Arguments(2); args.AddRange(targs); args.Add(new Argument(right)); string method_prefix = op == Binary.Operator.Addition ? Event.AEventAccessor.AddPrefix : Event.AEventAccessor.RemovePrefix; Expression invoke = new DynamicInvocation( new MemberAccess(right, method_prefix + ma.Name, loc), args, loc).Resolve(ec); args = new Arguments(1); args.AddRange(targs); source = new DynamicEventCompoundAssign(ma.Name, args, (ExpressionStatement)source, (ExpressionStatement)invoke, loc).Resolve(ec); } return(source); } return(base.DoResolve(ec)); }