}\r
\r
//\r
- // A delegate-creation-expression\r
+ // Base class for `NewDelegate' and `ImplicitDelegateCreation'\r
//\r
- public class NewDelegate : Expression {\r
+ public abstract class DelegateCreation : Expression {\r
+ protected MethodBase constructor_method;\r
+ protected MethodBase delegate_method;\r
+ protected Expression delegate_instance_expr;\r
\r
- public ArrayList Arguments;\r
+ public DelegateCreation () {}\r
\r
- MethodBase constructor_method;\r
- MethodBase delegate_method;\r
- Expression delegate_instance_expr;\r
+ public static void Error_NoMatchingMethodForDelegate (MethodGroupExpr mg, Type t, MethodBase method, Location loc)\r
+ {\r
+ string method_desc;\r
+ \r
+ if (mg.Methods.Length > 1)\r
+ method_desc = mg.Methods [0].Name;\r
+ else\r
+ method_desc = Invocation.FullMethodDesc (mg.Methods [0]);\r
+\r
+ ParameterData param = Invocation.GetParameterData (method);\r
+ string delegate_desc = Delegate.FullDelegateDesc (t, method, param);\r
+ \r
+ Report.Error (123, loc, "Method '" + method_desc + "' does not " +\r
+ "match delegate '" + delegate_desc + "'");\r
+ }\r
+ \r
+ public override void Emit (EmitContext ec)\r
+ {\r
+ if (delegate_instance_expr == null ||\r
+ delegate_method.IsStatic)\r
+ ec.ig.Emit (OpCodes.Ldnull);\r
+ else\r
+ delegate_instance_expr.Emit (ec);\r
+ \r
+ if (delegate_method.IsVirtual) {\r
+ ec.ig.Emit (OpCodes.Dup);\r
+ ec.ig.Emit (OpCodes.Ldvirtftn, (MethodInfo) delegate_method);\r
+ } else\r
+ ec.ig.Emit (OpCodes.Ldftn, (MethodInfo) delegate_method);\r
+ ec.ig.Emit (OpCodes.Newobj, (ConstructorInfo) constructor_method);\r
+ }\r
+\r
+ protected bool ResolveConstructorMethod (EmitContext ec)\r
+ {\r
+ Expression ml = Expression.MemberLookup (\r
+ ec, type, ".ctor", loc);\r
+\r
+ if (!(ml is MethodGroupExpr)) {\r
+ Report.Error (-100, loc, "Internal error: Could not find delegate constructor!");\r
+ return false;\r
+ }\r
+\r
+ constructor_method = ((MethodGroupExpr) ml).Methods [0];\r
+ return true;\r
+ }\r
+\r
+ protected Expression ResolveMethodGroupExpr (EmitContext ec, MethodGroupExpr mg)\r
+ {\r
+ foreach (MethodInfo mi in mg.Methods){\r
+ delegate_method = Delegate.VerifyMethod (ec, type, mi, loc);\r
+ \r
+ if (delegate_method != null)\r
+ break;\r
+ }\r
+ \r
+ if (delegate_method == null) {\r
+ Error_NoMatchingMethodForDelegate (mg, type, delegate_method, loc);\r
+ return null;\r
+ }\r
+ \r
+ //\r
+ // Check safe/unsafe of the delegate\r
+ //\r
+ if (!ec.InUnsafe){\r
+ ParameterData param = Invocation.GetParameterData (delegate_method);\r
+ int count = param.Count;\r
+ \r
+ for (int i = 0; i < count; i++){\r
+ if (param.ParameterType (i).IsPointer){\r
+ Expression.UnsafeError (loc);\r
+ return null;\r
+ }\r
+ }\r
+ }\r
+ \r
+ if (mg.InstanceExpression != null)\r
+ delegate_instance_expr = mg.InstanceExpression.Resolve (ec);\r
+ else {\r
+ if (ec.IsStatic){\r
+ if (!delegate_method.IsStatic){\r
+ Report.Error (120, loc,\r
+ "An object reference is required for the non-static method " +\r
+ delegate_method.Name);\r
+ return null;\r
+ }\r
+ delegate_instance_expr = null;\r
+ } else\r
+ delegate_instance_expr = ec.GetThis (loc);\r
+ }\r
+ \r
+ if (delegate_instance_expr != null)\r
+ if (delegate_instance_expr.Type.IsValueType)\r
+ delegate_instance_expr = new BoxedCast (delegate_instance_expr);\r
+ \r
+ eclass = ExprClass.Value;\r
+ return this;\r
+ }\r
+ }\r
\r
+ //\r
+ // Created from the conversion code\r
+ //\r
+ public class ImplicitDelegateCreation : DelegateCreation {\r
+\r
+ ImplicitDelegateCreation (Type t, Location l)\r
+ {\r
+ type = t;\r
+ loc = l;\r
+ }\r
+\r
+ public override Expression DoResolve (EmitContext ec)\r
+ {\r
+ return this;\r
+ }\r
+ \r
+ static public Expression Create (EmitContext ec, MethodGroupExpr mge, Type target_type, Location loc)\r
+ {\r
+ ImplicitDelegateCreation d = new ImplicitDelegateCreation (target_type, loc);\r
+ if (d.ResolveConstructorMethod (ec))\r
+ return d.ResolveMethodGroupExpr (ec, mge);\r
+ else\r
+ return null;\r
+ }\r
+ }\r
+ \r
+ //\r
+ // A delegate-creation-expression, invoked from the `New' class \r
+ //\r
+ public class NewDelegate : DelegateCreation {\r
+ public ArrayList Arguments;\r
+\r
+ //\r
+ // This constructor is invoked from the `New' expression\r
+ //\r
public NewDelegate (Type type, ArrayList Arguments, Location loc)\r
{\r
this.type = type;\r
return null;\r
}\r
\r
- Expression ml = Expression.MemberLookup (\r
- ec, type, ".ctor", loc);\r
-\r
- if (!(ml is MethodGroupExpr)) {\r
- Report.Error (-100, loc, "Internal error: Could not find delegate constructor!");\r
+ if (!ResolveConstructorMethod (ec))\r
return null;\r
- }\r
\r
- constructor_method = ((MethodGroupExpr) ml).Methods [0];\r
Argument a = (Argument) Arguments [0];\r
\r
- if (!a.ResolveMethodGroup (ec, Location))\r
- return null;\r
- \r
- Expression e = a.Expr;\r
-\r
Expression invoke_method = Expression.MemberLookup (\r
ec, type, "Invoke", MemberTypes.Method,\r
Expression.AllBindingFlags, loc);\r
return null;\r
}\r
\r
- if (e is MethodGroupExpr) {\r
- MethodGroupExpr mg = (MethodGroupExpr) e;\r
-\r
- foreach (MethodInfo mi in mg.Methods){\r
- delegate_method = Delegate.VerifyMethod (ec, type, mi, loc);\r
-\r
- if (delegate_method != null)\r
- break;\r
- }\r
- \r
- if (delegate_method == null) {\r
- string method_desc;\r
- if (mg.Methods.Length > 1)\r
- method_desc = mg.Methods [0].Name;\r
- else\r
- method_desc = Invocation.FullMethodDesc (mg.Methods [0]);\r
-\r
- MethodBase dm = ((MethodGroupExpr) invoke_method).Methods [0];\r
- ParameterData param = Invocation.GetParameterData (dm);\r
- string delegate_desc = Delegate.FullDelegateDesc (type, dm, param);\r
-\r
- Report.Error (123, loc, "Method '" + method_desc + "' does not " +\r
- "match delegate '" + delegate_desc + "'");\r
-\r
- return null;\r
- }\r
-\r
- //\r
- // Check safe/unsafe of the delegate\r
- //\r
- if (!ec.InUnsafe){\r
- ParameterData param = Invocation.GetParameterData (delegate_method);\r
- int count = param.Count;\r
- \r
- for (int i = 0; i < count; i++){\r
- if (param.ParameterType (i).IsPointer){\r
- Expression.UnsafeError (loc);\r
- return null;\r
- }\r
- }\r
- }\r
- \r
- if (mg.InstanceExpression != null)\r
- delegate_instance_expr = mg.InstanceExpression.Resolve (ec);\r
- else {\r
- if (ec.IsStatic){\r
- if (!delegate_method.IsStatic){\r
- Report.Error (120, loc,\r
- "An object reference is required for the non-static method " +\r
- delegate_method.Name);\r
- return null;\r
- }\r
- delegate_instance_expr = null;\r
- } else\r
- delegate_instance_expr = ec.GetThis (loc);\r
- }\r
+ if (!a.ResolveMethodGroup (ec, loc))\r
+ return null;\r
+ \r
+ Expression e = a.Expr;\r
\r
- if (delegate_instance_expr != null)\r
- if (delegate_instance_expr.Type.IsValueType)\r
- delegate_instance_expr = new BoxedCast (delegate_instance_expr);\r
- \r
- eclass = ExprClass.Value;\r
- return this;\r
- }\r
+ MethodGroupExpr mg = e as MethodGroupExpr;\r
+ if (mg != null)\r
+ return ResolveMethodGroupExpr (ec, mg);\r
\r
Type e_type = e.Type;\r
\r
\r
public override void Emit (EmitContext ec)\r
{\r
- if (delegate_instance_expr == null ||\r
- delegate_method.IsStatic)\r
+ if (delegate_instance_expr == null || delegate_method.IsStatic)\r
ec.ig.Emit (OpCodes.Ldnull);\r
else\r
delegate_instance_expr.Emit (ec);\r
}
}
- //
- // Step 2: Default operations on CLI native types.
- //
-
//
// Step 0: String concatenation (because overloading will get this wrong)
//
// +, -, *, /, %, &, |, ^, ==, !=, <, >, <=, >=
//
if (oper == Operator.Addition || oper == Operator.Subtraction) {
- if (l.IsSubclassOf (TypeManager.delegate_type) &&
- r.IsSubclassOf (TypeManager.delegate_type)) {
- MethodInfo method;
- ArrayList args = new ArrayList (2);
-
- args = new ArrayList (2);
- args.Add (new Argument (left, Argument.AType.Expression));
- args.Add (new Argument (right, Argument.AType.Expression));
-
- if (oper == Operator.Addition)
- method = TypeManager.delegate_combine_delegate_delegate;
- else
- method = TypeManager.delegate_remove_delegate_delegate;
-
- if (l != r) {
- Error_OperatorCannotBeApplied ();
- return null;
+ if (l.IsSubclassOf (TypeManager.delegate_type)){
+ if (right.eclass == ExprClass.MethodGroup && RootContext.V2){
+ Expression tmp = Convert.ImplicitConversionRequired (ec, right, l, loc);
+ if (tmp == null)
+ return null;
+ right = tmp;
+ r = right.Type;
+ }
+
+ if (r.IsSubclassOf (TypeManager.delegate_type)){
+ MethodInfo method;
+ ArrayList args = new ArrayList (2);
+
+ args = new ArrayList (2);
+ args.Add (new Argument (left, Argument.AType.Expression));
+ args.Add (new Argument (right, Argument.AType.Expression));
+
+ if (oper == Operator.Addition)
+ method = TypeManager.delegate_combine_delegate_delegate;
+ else
+ method = TypeManager.delegate_remove_delegate_delegate;
+
+ if (l != r) {
+ Error_OperatorCannotBeApplied ();
+ return null;
+ }
+
+ return new BinaryDelegate (l, method, args);
}
-
- return new BinaryDelegate (l, method, args);
}
-
+
//
// Pointer arithmetic:
//