{
Ref = 1, // ref modifier used
Out = 2, // out modifier used
- Default = 3 // argument created from default value
+ Default = 3 // argument created from default parameter value
}
public readonly AType ArgType;
return TypeManager.CSharpName (Expr.Type);
}
+ public bool IsDefaultArgument {
+ get { return ArgType == AType.Default; }
+ }
+
public bool ResolveMethodGroup (EmitContext ec)
{
SimpleName sn = Expr as SimpleName;
}
}
- public void Emit (EmitContext ec)
+ public virtual void Emit (EmitContext ec)
{
if (ArgType != AType.Ref && ArgType != AType.Out) {
Expr.Emit (ec);
}
}
- class NamedArgument : Argument
+ public class NamedArgument : Argument
{
public readonly LocatedToken Name;
+ LocalTemporary variable;
public NamedArgument (LocatedToken name, Expression expr)
: base (expr)
public override Expression CreateExpressionTree (EmitContext ec)
{
Report.Error (853, Name.Location, "An expression tree cannot contain named argument");
- return null;
+ return base.CreateExpressionTree (ec);
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ // TODO: Should guard against multiple emits
+ base.Emit (ec);
+
+ // Release temporary variable when used
+ if (variable != null)
+ variable.Release (ec);
+ }
+
+ public void EmitAssign (EmitContext ec)
+ {
+ Expr.Emit (ec);
+ variable = new LocalTemporary (Expr.Type);
+ variable.Store (ec);
+
+ Expr = variable;
}
}
public class Arguments
{
- // TODO: This should really be linked list
- ArrayList args;
+ ArrayList args; // TODO: This should really be linked list
+ ArrayList reordered; // TODO: LinkedList
public Arguments (int capacity)
{
//
public void Emit (EmitContext ec, bool dup_args, LocalTemporary this_arg)
{
- int top = Count;
LocalTemporary[] temps = null;
- if (dup_args && top != 0)
- temps = new LocalTemporary [top];
+ if (dup_args && Count != 0)
+ temps = new LocalTemporary [Count];
- int argument_index = 0;
- Argument a;
- for (int i = 0; i < top; i++) {
- a = this [argument_index++];
+ if (reordered != null && Count > 1) {
+ foreach (NamedArgument na in reordered)
+ na.EmitAssign (ec);
+ }
+
+ int i = 0;
+ foreach (Argument a in args) {
a.Emit (ec);
if (dup_args) {
ec.ig.Emit (OpCodes.Dup);
- (temps [i] = new LocalTemporary (a.Type)).Store (ec);
+ (temps [i++] = new LocalTemporary (a.Type)).Store (ec);
}
}
if (this_arg != null)
this_arg.Emit (ec);
- for (int i = 0; i < top; i++) {
+ for (i = 0; i < temps.Length; i++) {
temps[i].Emit (ec);
temps[i].Release (ec);
}
args.Insert (index, arg);
}
+ public void MarkReorderedArgument (NamedArgument a)
+ {
+ //
+ // Constant expression can have no effect on left-to-right execution
+ //
+ if (a.Expr is Constant)
+ return;
+
+ if (reordered == null)
+ reordered = new ArrayList ();
+
+ reordered.Add (a);
+ }
+
public void Resolve (EmitContext ec)
{
foreach (Argument a in args)
public Argument this [int index] {
get { return (Argument) args [index]; }
+ set { args [index] = value; }
}
}
}
\ No newline at end of file
arguments = new Arguments (1);
arguments.Insert (0, new Argument (ExtensionExpression));
- MethodGroupExpr mg = ResolveOverloadExtensions (ec, arguments, namespace_entry, loc);
+ MethodGroupExpr mg = ResolveOverloadExtensions (ec, ref arguments, namespace_entry, loc);
// Store resolved argument and restore original arguments
if (mg != null)
return mg;
}
- MethodGroupExpr ResolveOverloadExtensions (EmitContext ec, Arguments arguments, NamespaceEntry ns, Location loc)
+ MethodGroupExpr ResolveOverloadExtensions (EmitContext ec, ref Arguments arguments, NamespaceEntry ns, Location loc)
{
// Use normal resolve rules
MethodGroupExpr mg = base.OverloadResolve (ec, ref arguments, ns != null, loc);
e.ExtensionExpression = ExtensionExpression;
e.SetTypeArguments (type_arguments);
- return e.ResolveOverloadExtensions (ec, arguments, e.namespace_entry, loc);
+ return e.ResolveOverloadExtensions (ec, ref arguments, e.namespace_entry, loc);
}
}
{
Argument a = args [j];
+ // Provided default argument value is never better
+ if (a.IsDefaultArgument && candidate_params == best_params)
+ return false;
+
Type ct = candidate_pd.Types [c_idx];
Type bt = best_pd.Types [b_idx];
}
}
- if (arg_count + optional_count != param_count) {
+ int args_gap = 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) {
if (!pd.HasParams)
- return int.MaxValue - 10000 + Math.Abs (arg_count - param_count);
+ return int.MaxValue - 10000 + args_gap;
if (arg_count < param_count - 1)
- return int.MaxValue - 10000 + Math.Abs (arg_count - param_count);
+ 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.Value);
+
+ // 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;
- // Initialize expanded form of a method with 1 params parameter
- params_expanded_form = param_count == 1 && pd.HasParams;
+ 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;
}
#if GMCS_SOURCE
}
#endif
- if (optional_count != 0) {
- Arguments args = new Arguments (optional_count + arg_count);
- for (int i = 0; i < pd.Count; ++i) {
- if (i < arg_count) {
- args.Add (arguments[i]);
- continue;
- }
-
- Expression e = pd.FixedParameters [i].DefaultValue as Constant;
- if (e == null)
- e = new DefaultValueExpression (new TypeExpression (pd.Types [i], loc), loc).Resolve (ec);
-
- args.Add (new Argument (e, Argument.AType.Default));
- }
-
- arguments = args;
- }
-
-
//
// 2. Each argument has to be implicitly convertible to method parameter
//
Type pt = null;
for (int i = 0; i < arg_count; i++) {
Argument a = arguments [i];
- Parameter.Modifier a_mod = a.Modifier &
- ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK);
+ 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);
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 (arg_count + optional_count != param_count)
- params_expanded_form = true;
+ if (arg_count != param_count)
+ params_expanded_form = true;
return 0;
}
candidate_to_form = new PtrHashtable ();
MethodBase candidate = Methods [i];
candidate_to_form [candidate] = candidate;
- } else if (candidate_args != Arguments) {
+ }
+
+ if (candidate_args != Arguments) {
if (candidates_expanded == null)
- candidates_expanded = new Hashtable (4);
+ candidates_expanded = new Hashtable (2);
candidates_expanded.Add (Methods [i], candidate_args);
candidate_args = Arguments;
best_candidate = (MethodBase) candidates [0];
method_params = candidate_to_form != null && candidate_to_form.Contains (best_candidate);
+ //
+ // TODO: Broken inverse order of candidates logic does not work with optional
+ // parameters used for method overrides and I am not going to fix it for SRE
+ //
+ if (candidates_expanded != null && candidates_expanded.Contains (best_candidate)) {
+ candidate_args = (Arguments) candidates_expanded [best_candidate];
+ arg_count = candidate_args.Count;
+ }
+
for (int ix = 1; ix < candidate_top; ix++) {
MethodBase candidate = (MethodBase) candidates [ix];
bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate);
- if (BetterFunction (ec, Arguments, arg_count,
+ if (BetterFunction (ec, candidate_args, arg_count,
candidate, cand_params,
best_candidate, method_params)) {
best_candidate = candidate;
continue;
bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate);
- if (!BetterFunction (ec, Arguments, arg_count,
+ if (!BetterFunction (ec, candidate_args, arg_count,
best_candidate, method_params,
candidate, cand_params))
{
}
}
- //
- // TODO: Broken inverse order of candidates logic does not work with optional
- // parameters used for method overrides and I am not going to fix it for SRE
- //
- if (candidates_expanded != null && candidates_expanded.Contains (best_candidate)) {
- candidate_args = (Arguments) candidates_expanded [best_candidate];
- arg_count = candidate_args.Count;
- }
-
//
// And now check if the arguments are all
// compatible, perform conversions if
bool may_fail, Location loc)
{
AParametersCollection pd = TypeManager.GetParameterData (method);
+ int param_count = GetApplicableParametersCount (method, pd);
int errors = Report.Errors;
Parameter.Modifier p_mod = 0;
break;
continue;
+ } else {
+ NamedArgument na = a as NamedArgument;
+ if (na != null) {
+ int name_index = pd.GetParameterIndexByName (na.Name.Value);
+ if (name_index < 0 || name_index >= param_count) {
+ if (DeclaringType != null && TypeManager.IsDelegateType (DeclaringType)) {
+ Report.SymbolRelatedToPreviousError (DeclaringType);
+ Report.Error (1746, na.Name.Location,
+ "The delegate `{0}' does not contain a parameter named `{1}'",
+ TypeManager.CSharpName (DeclaringType), na.Name.Value);
+ } else {
+ Report.SymbolRelatedToPreviousError (best_candidate);
+ Report.Error (1739, na.Name.Location,
+ "The best overloaded method match for `{0}' does not contain a parameter named `{1}'",
+ TypeManager.CSharpSignature (method), na.Name.Value);
+ }
+ } else if (arguments[name_index] != a) {
+ if (DeclaringType != null && TypeManager.IsDelegateType (DeclaringType))
+ Report.SymbolRelatedToPreviousError (DeclaringType);
+ else
+ Report.SymbolRelatedToPreviousError (best_candidate);
+
+ Report.Error (1744, na.Name.Location,
+ "Named argument `{0}' cannot be used for a parameter which has positional argument specified",
+ na.Name.Value);
+ }
+ }
}
if (delegate_type != null && !Delegate.IsTypeCovariant (a.Expr, pt))
//
// Fill not provided arguments required by params modifier
//
- int param_count = GetApplicableParametersCount (method, pd);
if (params_initializers == null && pd.HasParams && arg_count + 1 == param_count) {
if (arguments == null)
arguments = new Arguments (1);