2010-01-12 Zoltan Varga <vargaz@gmail.com>
[mcs.git] / mcs / delegate.cs
blob62e5cbac290efc79bf9865b7de91b180cf1d9356
1 //
2 // delegate.cs: Delegate Handler
3 //
4 // Authors:
5 // Ravi Pratap (ravi@ximian.com)
6 // Miguel de Icaza (miguel@ximian.com)
7 // Marek Safar (marek.safar@gmail.com)
8 //
9 // Dual licensed under the terms of the MIT X11 or GNU GPL
11 // Copyright 2001 Ximian, Inc (http://www.ximian.com)
12 // Copyright 2003-2009 Novell, Inc (http://www.novell.com)
15 using System;
16 using System.Collections;
17 using System.Reflection;
18 using System.Reflection.Emit;
19 using System.Text;
21 namespace Mono.CSharp {
24 // Delegate container implementation
26 public class Delegate : TypeContainer
28 FullNamedExpression ReturnType;
29 public ParametersCompiled Parameters;
31 public ConstructorBuilder ConstructorBuilder;
32 public MethodBuilder InvokeBuilder;
33 public MethodBuilder BeginInvokeBuilder;
34 public MethodBuilder EndInvokeBuilder;
36 Type ret_type;
38 static string[] attribute_targets = new string [] { "type", "return" };
40 Expression instance_expr;
41 MethodBase delegate_method;
42 ReturnParameter return_attributes;
44 const MethodAttributes mattr = MethodAttributes.Public | MethodAttributes.HideBySig |
45 MethodAttributes.Virtual | MethodAttributes.NewSlot;
47 const int AllowedModifiers =
48 Modifiers.NEW |
49 Modifiers.PUBLIC |
50 Modifiers.PROTECTED |
51 Modifiers.INTERNAL |
52 Modifiers.UNSAFE |
53 Modifiers.PRIVATE;
55 public Delegate (NamespaceEntry ns, DeclSpace parent, FullNamedExpression type,
56 int mod_flags, MemberName name, ParametersCompiled param_list,
57 Attributes attrs)
58 : base (ns, parent, name, attrs, Kind.Delegate)
61 this.ReturnType = type;
62 ModFlags = Modifiers.Check (AllowedModifiers, mod_flags,
63 IsTopLevel ? Modifiers.INTERNAL :
64 Modifiers.PRIVATE, name.Location, Report);
65 Parameters = param_list;
68 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
70 if (a.Target == AttributeTargets.ReturnValue) {
71 if (return_attributes == null)
72 return_attributes = new ReturnParameter (InvokeBuilder, Location);
74 return_attributes.ApplyAttributeBuilder (a, cb, pa);
75 return;
78 base.ApplyAttributeBuilder (a, cb, pa);
81 public override AttributeTargets AttributeTargets {
82 get {
83 return AttributeTargets.Delegate;
87 public override bool Define ()
89 if (IsGeneric) {
90 foreach (TypeParameter type_param in TypeParameters) {
91 if (!type_param.Resolve (this))
92 return false;
95 foreach (TypeParameter type_param in TypeParameters) {
96 if (!type_param.DefineType (this))
97 return false;
101 member_cache = new MemberCache (TypeManager.multicast_delegate_type, this);
103 // FIXME: POSSIBLY make this static, as it is always constant
105 Type [] const_arg_types = new Type [2];
106 const_arg_types [0] = TypeManager.object_type;
107 const_arg_types [1] = TypeManager.intptr_type;
109 const MethodAttributes ctor_mattr = MethodAttributes.RTSpecialName | MethodAttributes.SpecialName |
110 MethodAttributes.HideBySig | MethodAttributes.Public;
112 ConstructorBuilder = TypeBuilder.DefineConstructor (ctor_mattr,
113 CallingConventions.Standard,
114 const_arg_types);
116 ConstructorBuilder.DefineParameter (1, ParameterAttributes.None, "object");
117 ConstructorBuilder.DefineParameter (2, ParameterAttributes.None, "method");
119 // HACK because System.Reflection.Emit is lame
121 IParameterData [] fixed_pars = new IParameterData [] {
122 new ParameterData ("object", Parameter.Modifier.NONE),
123 new ParameterData ("method", Parameter.Modifier.NONE)
126 AParametersCollection const_parameters = new ParametersImported (
127 fixed_pars,
128 new Type[] { TypeManager.object_type, TypeManager.intptr_type });
130 TypeManager.RegisterMethod (ConstructorBuilder, const_parameters);
131 member_cache.AddMember (ConstructorBuilder, this);
133 ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
136 // Here the various methods like Invoke, BeginInvoke etc are defined
138 // First, call the `out of band' special method for
139 // defining recursively any types we need:
141 if (!Parameters.Resolve (this))
142 return false;
145 // Invoke method
148 // Check accessibility
149 foreach (Type partype in Parameters.Types){
150 if (!IsAccessibleAs (partype)) {
151 Report.SymbolRelatedToPreviousError (partype);
152 Report.Error (59, Location,
153 "Inconsistent accessibility: parameter type `{0}' is less accessible than delegate `{1}'",
154 TypeManager.CSharpName (partype),
155 GetSignatureForError ());
156 return false;
160 ReturnType = ReturnType.ResolveAsTypeTerminal (this, false);
161 if (ReturnType == null)
162 return false;
164 ret_type = ReturnType.Type;
166 if (!IsAccessibleAs (ret_type)) {
167 Report.SymbolRelatedToPreviousError (ret_type);
168 Report.Error (58, Location,
169 "Inconsistent accessibility: return type `" +
170 TypeManager.CSharpName (ret_type) + "' is less " +
171 "accessible than delegate `" + GetSignatureForError () + "'");
172 return false;
175 CheckProtectedModifier ();
177 if (RootContext.StdLib && TypeManager.IsSpecialType (ret_type)) {
178 Method.Error1599 (Location, ret_type, Report);
179 return false;
182 TypeManager.CheckTypeVariance (ret_type, Variance.Covariant, this);
185 // We don't have to check any others because they are all
186 // guaranteed to be accessible - they are standard types.
189 CallingConventions cc = Parameters.CallingConvention;
191 InvokeBuilder = TypeBuilder.DefineMethod ("Invoke",
192 mattr,
194 ret_type,
195 Parameters.GetEmitTypes ());
197 InvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
199 TypeManager.RegisterMethod (InvokeBuilder, Parameters);
200 member_cache.AddMember (InvokeBuilder, this);
203 // Don't emit async method for compiler generated delegates (e.g. dynamic site containers)
205 if (TypeManager.iasyncresult_type != null && TypeManager.asynccallback_type != null && !IsCompilerGenerated) {
206 DefineAsyncMethods (cc);
209 return true;
212 void DefineAsyncMethods (CallingConventions cc)
215 // BeginInvoke
217 ParametersCompiled async_parameters = ParametersCompiled.MergeGenerated (Parameters, false,
218 new Parameter [] {
219 new Parameter (null, "callback", Parameter.Modifier.NONE, null, Location),
220 new Parameter (null, "object", Parameter.Modifier.NONE, null, Location)
222 new Type [] {
223 TypeManager.asynccallback_type,
224 TypeManager.object_type
228 BeginInvokeBuilder = TypeBuilder.DefineMethod ("BeginInvoke",
229 mattr, cc, TypeManager.iasyncresult_type, async_parameters.GetEmitTypes ());
231 BeginInvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
232 TypeManager.RegisterMethod (BeginInvokeBuilder, async_parameters);
233 member_cache.AddMember (BeginInvokeBuilder, this);
236 // EndInvoke is a bit more interesting, all the parameters labeled as
237 // out or ref have to be duplicated here.
241 // Define parameters, and count out/ref parameters
243 ParametersCompiled end_parameters;
244 int out_params = 0;
246 foreach (Parameter p in Parameters.FixedParameters) {
247 if ((p.ModFlags & Parameter.Modifier.ISBYREF) != 0)
248 ++out_params;
251 if (out_params > 0) {
252 Type [] end_param_types = new Type [out_params];
253 Parameter[] end_params = new Parameter [out_params];
255 int param = 0;
256 for (int i = 0; i < Parameters.FixedParameters.Length; ++i) {
257 Parameter p = Parameters [i];
258 if ((p.ModFlags & Parameter.Modifier.ISBYREF) == 0)
259 continue;
261 end_param_types [param] = Parameters.Types [i];
262 end_params [param] = p;
263 ++param;
265 end_parameters = ParametersCompiled.CreateFullyResolved (end_params, end_param_types);
266 } else {
267 end_parameters = ParametersCompiled.EmptyReadOnlyParameters;
270 end_parameters = ParametersCompiled.MergeGenerated (end_parameters, false,
271 new Parameter (null, "result", Parameter.Modifier.NONE, null, Location), TypeManager.iasyncresult_type);
274 // Create method, define parameters, register parameters with type system
276 EndInvokeBuilder = TypeBuilder.DefineMethod ("EndInvoke", mattr, cc, ret_type, end_parameters.GetEmitTypes ());
277 EndInvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
279 end_parameters.ApplyAttributes (EndInvokeBuilder);
280 TypeManager.RegisterMethod (EndInvokeBuilder, end_parameters);
281 member_cache.AddMember (EndInvokeBuilder, this);
284 public override void Emit ()
286 if (TypeManager.IsDynamicType (ret_type)) {
287 return_attributes = new ReturnParameter (InvokeBuilder, Location);
288 return_attributes.EmitPredefined (PredefinedAttributes.Get.Dynamic, Location);
291 Parameters.ApplyAttributes (InvokeBuilder);
293 if (BeginInvokeBuilder != null) {
294 ParametersCompiled p = (ParametersCompiled) TypeManager.GetParameterData (BeginInvokeBuilder);
295 p.ApplyAttributes (BeginInvokeBuilder);
298 if (OptAttributes != null) {
299 OptAttributes.Emit ();
302 base.Emit ();
305 protected override TypeAttributes TypeAttr {
306 get {
307 return Modifiers.TypeAttr (ModFlags, IsTopLevel) |
308 TypeAttributes.Class | TypeAttributes.Sealed |
309 base.TypeAttr;
313 public override string[] ValidAttributeTargets {
314 get {
315 return attribute_targets;
319 //TODO: duplicate
320 protected override bool VerifyClsCompliance ()
322 if (!base.VerifyClsCompliance ()) {
323 return false;
326 Parameters.VerifyClsCompliance ();
328 if (!AttributeTester.IsClsCompliant (ReturnType.Type)) {
329 Report.Warning (3002, 1, Location, "Return type of `{0}' is not CLS-compliant",
330 GetSignatureForError ());
332 return true;
336 public static ConstructorInfo GetConstructor (CompilerContext ctx, Type container_type, Type delegate_type)
338 Type dt = delegate_type;
339 Type[] g_args = null;
340 if (TypeManager.IsGenericType (delegate_type)) {
341 g_args = TypeManager.GetTypeArguments (delegate_type);
342 delegate_type = TypeManager.DropGenericTypeArguments (delegate_type);
345 Delegate d = TypeManager.LookupDelegate (delegate_type);
346 if (d != null) {
347 #if GMCS_SOURCE
348 if (g_args != null)
349 return TypeBuilder.GetConstructor (dt, d.ConstructorBuilder);
350 #endif
351 return d.ConstructorBuilder;
354 Expression ml = Expression.MemberLookup (ctx, container_type,
355 null, dt, ConstructorInfo.ConstructorName, MemberTypes.Constructor,
356 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly, Location.Null);
358 MethodGroupExpr mg = ml as MethodGroupExpr;
359 if (mg == null) {
360 ctx.Report.Error (-100, Location.Null, "Internal error: could not find delegate constructor!");
361 // FIXME: null will cause a crash later
362 return null;
365 return (ConstructorInfo) mg.Methods[0];
369 // Returns the MethodBase for "Invoke" from a delegate type, this is used
370 // to extract the signature of a delegate.
372 public static MethodInfo GetInvokeMethod (CompilerContext ctx, Type container_type, Type delegate_type)
374 Type dt = delegate_type;
376 Type[] g_args = null;
377 if (TypeManager.IsGenericType (delegate_type)) {
378 g_args = TypeManager.GetTypeArguments (delegate_type);
379 delegate_type = TypeManager.DropGenericTypeArguments (delegate_type);
382 Delegate d = TypeManager.LookupDelegate (delegate_type);
383 MethodInfo invoke;
384 if (d != null) {
385 #if GMCS_SOURCE
386 if (g_args != null) {
387 invoke = TypeBuilder.GetMethod (dt, d.InvokeBuilder);
388 #if MS_COMPATIBLE
389 ParametersCompiled p = (ParametersCompiled) d.Parameters.InflateTypes (g_args, g_args);
390 TypeManager.RegisterMethod (invoke, p);
391 #endif
392 return invoke;
394 #endif
395 return d.InvokeBuilder;
398 Expression ml = Expression.MemberLookup (ctx, container_type, null, dt,
399 "Invoke", Location.Null);
401 MethodGroupExpr mg = ml as MethodGroupExpr;
402 if (mg == null) {
403 ctx.Report.Error (-100, Location.Null, "Internal error: could not find Invoke method!");
404 // FIXME: null will cause a crash later
405 return null;
408 invoke = (MethodInfo) mg.Methods[0];
409 #if MS_COMPATIBLE
410 if (g_args != null) {
411 AParametersCollection p = TypeManager.GetParameterData (invoke);
412 p = p.InflateTypes (g_args, g_args);
413 TypeManager.RegisterMethod (invoke, p);
414 return invoke;
416 #endif
418 return invoke;
422 // 15.2 Delegate compatibility
424 public static bool IsTypeCovariant (Expression a, Type b)
427 // For each value parameter (a parameter with no ref or out modifier), an
428 // identity conversion or implicit reference conversion exists from the
429 // parameter type in D to the corresponding parameter type in M
431 if (a.Type == b)
432 return true;
434 if (RootContext.Version == LanguageVersion.ISO_1)
435 return false;
437 return Convert.ImplicitReferenceConversionExists (a, b);
440 // <summary>
441 // Verifies whether the invocation arguments are compatible with the
442 // delegate's target method
443 // </summary>
444 public static bool VerifyApplicability (ResolveContext ec, Type delegate_type, ref Arguments args, Location loc)
446 int arg_count;
448 if (args == null)
449 arg_count = 0;
450 else
451 arg_count = args.Count;
453 MethodBase mb = GetInvokeMethod (ec.Compiler, ec.CurrentType, delegate_type);
454 MethodGroupExpr me = new MethodGroupExpr (new MemberInfo [] { mb }, delegate_type, loc);
456 AParametersCollection pd = TypeManager.GetParameterData (mb);
458 int pd_count = pd.Count;
460 bool params_method = pd.HasParams;
461 bool is_params_applicable = false;
462 bool is_applicable = me.IsApplicable (ec, ref args, arg_count, ref mb, ref is_params_applicable) == 0;
463 if (args != null)
464 arg_count = args.Count;
466 if (!is_applicable && !params_method && arg_count != pd_count) {
467 ec.Report.Error (1593, loc, "Delegate `{0}' does not take `{1}' arguments",
468 TypeManager.CSharpName (delegate_type), arg_count.ToString ());
469 return false;
472 return me.VerifyArgumentsCompat (
473 ec, ref args, arg_count, mb,
474 is_params_applicable || (!is_applicable && params_method),
475 false, loc);
478 public static string FullDelegateDesc (MethodBase invoke_method)
480 return TypeManager.GetFullNameSignature (invoke_method).Replace (".Invoke", "");
483 public Expression InstanceExpression {
484 get {
485 return instance_expr;
487 set {
488 instance_expr = value;
492 public MethodBase TargetMethod {
493 get {
494 return delegate_method;
496 set {
497 delegate_method = value;
501 public Type TargetReturnType {
502 get {
503 return ret_type;
509 // Base class for `NewDelegate' and `ImplicitDelegateCreation'
511 public abstract class DelegateCreation : Expression, MethodGroupExpr.IErrorHandler
513 protected ConstructorInfo constructor_method;
514 protected MethodInfo delegate_method;
515 // We keep this to handle IsBase only
516 protected MethodGroupExpr method_group;
517 protected Expression delegate_instance_expression;
519 // TODO: Should either cache it or use interface to abstract it
520 public static Arguments CreateDelegateMethodArguments (AParametersCollection pd, Location loc)
522 Arguments delegate_arguments = new Arguments (pd.Count);
523 for (int i = 0; i < pd.Count; ++i) {
524 Argument.AType atype_modifier;
525 Type atype = pd.Types [i];
526 switch (pd.FixedParameters [i].ModFlags) {
527 case Parameter.Modifier.REF:
528 atype_modifier = Argument.AType.Ref;
529 //atype = atype.GetElementType ();
530 break;
531 case Parameter.Modifier.OUT:
532 atype_modifier = Argument.AType.Out;
533 //atype = atype.GetElementType ();
534 break;
535 default:
536 atype_modifier = 0;
537 break;
539 delegate_arguments.Add (new Argument (new TypeExpression (atype, loc), atype_modifier));
541 return delegate_arguments;
544 public override Expression CreateExpressionTree (ResolveContext ec)
546 MemberAccess ma = new MemberAccess (new MemberAccess (new QualifiedAliasMember ("global", "System", loc), "Delegate", loc), "CreateDelegate", loc);
548 Arguments args = new Arguments (3);
549 args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
550 args.Add (new Argument (new NullLiteral (loc)));
551 args.Add (new Argument (new TypeOfMethod (delegate_method, loc)));
552 Expression e = new Invocation (ma, args).Resolve (ec);
553 if (e == null)
554 return null;
556 e = Convert.ExplicitConversion (ec, e, type, loc);
557 if (e == null)
558 return null;
560 return e.CreateExpressionTree (ec);
563 public override Expression DoResolve (ResolveContext ec)
565 constructor_method = Delegate.GetConstructor (ec.Compiler, ec.CurrentType, type);
567 MethodInfo invoke_method = Delegate.GetInvokeMethod (ec.Compiler, ec.CurrentType, type);
568 method_group.DelegateType = type;
569 method_group.CustomErrorHandler = this;
571 Arguments arguments = CreateDelegateMethodArguments (TypeManager.GetParameterData (invoke_method), loc);
572 method_group = method_group.OverloadResolve (ec, ref arguments, false, loc);
573 if (method_group == null)
574 return null;
576 delegate_method = (MethodInfo) method_group;
578 if (TypeManager.IsNullableType (delegate_method.DeclaringType)) {
579 ec.Report.Error (1728, loc, "Cannot create delegate from method `{0}' because it is a member of System.Nullable<T> type",
580 TypeManager.GetFullNameSignature (delegate_method));
581 return null;
584 Invocation.IsSpecialMethodInvocation (ec, delegate_method, loc);
586 ExtensionMethodGroupExpr emg = method_group as ExtensionMethodGroupExpr;
587 if (emg != null) {
588 delegate_instance_expression = emg.ExtensionExpression;
589 Type e_type = delegate_instance_expression.Type;
590 if (TypeManager.IsValueType (e_type)) {
591 ec.Report.Error (1113, loc, "Extension method `{0}' of value type `{1}' cannot be used to create delegates",
592 TypeManager.CSharpSignature (delegate_method), TypeManager.CSharpName (e_type));
596 Type rt = TypeManager.TypeToCoreType (delegate_method.ReturnType);
597 Expression ret_expr = new TypeExpression (rt, loc);
598 if (!Delegate.IsTypeCovariant (ret_expr, (TypeManager.TypeToCoreType (invoke_method.ReturnType)))) {
599 Error_ConversionFailed (ec, delegate_method, ret_expr);
602 if (Invocation.IsMethodExcluded (delegate_method, loc)) {
603 ec.Report.SymbolRelatedToPreviousError (delegate_method);
604 MethodOrOperator m = TypeManager.GetMethod (delegate_method) as MethodOrOperator;
605 if (m != null && m.IsPartialDefinition) {
606 ec.Report.Error (762, loc, "Cannot create delegate from partial method declaration `{0}'",
607 TypeManager.CSharpSignature (delegate_method));
608 } else {
609 ec.Report.Error (1618, loc, "Cannot create delegate with `{0}' because it has a Conditional attribute",
610 TypeManager.CSharpSignature (delegate_method));
614 DoResolveInstanceExpression (ec);
615 eclass = ExprClass.Value;
616 return this;
619 void DoResolveInstanceExpression (ResolveContext ec)
622 // Argument is another delegate
624 if (delegate_instance_expression != null)
625 return;
627 if (method_group.IsStatic) {
628 delegate_instance_expression = null;
629 return;
632 Expression instance = method_group.InstanceExpression;
633 if (instance != null && instance != EmptyExpression.Null) {
634 delegate_instance_expression = instance;
635 Type instance_type = delegate_instance_expression.Type;
636 if (TypeManager.IsValueType (instance_type) || TypeManager.IsGenericParameter (instance_type)) {
637 delegate_instance_expression = new BoxedCast (
638 delegate_instance_expression, TypeManager.object_type);
640 } else {
641 delegate_instance_expression = ec.GetThis (loc);
645 public override void Emit (EmitContext ec)
647 if (delegate_instance_expression == null)
648 ec.ig.Emit (OpCodes.Ldnull);
649 else
650 delegate_instance_expression.Emit (ec);
652 if (!delegate_method.DeclaringType.IsSealed && delegate_method.IsVirtual && !method_group.IsBase) {
653 ec.ig.Emit (OpCodes.Dup);
654 ec.ig.Emit (OpCodes.Ldvirtftn, delegate_method);
655 } else {
656 ec.ig.Emit (OpCodes.Ldftn, delegate_method);
659 ec.ig.Emit (OpCodes.Newobj, constructor_method);
662 void Error_ConversionFailed (ResolveContext ec, MethodBase method, Expression return_type)
664 MethodInfo invoke_method = Delegate.GetInvokeMethod (ec.Compiler, ec.CurrentType, type);
665 string member_name = delegate_instance_expression != null ?
666 Delegate.FullDelegateDesc (method) :
667 TypeManager.GetFullNameSignature (method);
669 ec.Report.SymbolRelatedToPreviousError (type);
670 ec.Report.SymbolRelatedToPreviousError (method);
671 if (RootContext.Version == LanguageVersion.ISO_1) {
672 ec.Report.Error (410, loc, "A method or delegate `{0} {1}' parameters and return type must be same as delegate `{2} {3}' parameters and return type",
673 TypeManager.CSharpName (((MethodInfo) method).ReturnType), member_name,
674 TypeManager.CSharpName (invoke_method.ReturnType), Delegate.FullDelegateDesc (invoke_method));
675 return;
677 if (return_type == null) {
678 ec.Report.Error (123, loc, "A method or delegate `{0}' parameters do not match delegate `{1}' parameters",
679 member_name, Delegate.FullDelegateDesc (invoke_method));
680 return;
683 ec.Report.Error (407, loc, "A method or delegate `{0} {1}' return type does not match delegate `{2} {3}' return type",
684 return_type.GetSignatureForError (), member_name,
685 TypeManager.CSharpName (invoke_method.ReturnType), Delegate.FullDelegateDesc (invoke_method));
688 public static bool ImplicitStandardConversionExists (ResolveContext ec, MethodGroupExpr mg, Type target_type)
690 if (target_type == TypeManager.delegate_type || target_type == TypeManager.multicast_delegate_type)
691 return false;
693 mg.DelegateType = target_type;
694 MethodInfo invoke = Delegate.GetInvokeMethod (ec.Compiler, null, target_type);
696 Arguments arguments = CreateDelegateMethodArguments (TypeManager.GetParameterData (invoke), mg.Location);
697 return mg.OverloadResolve (ec, ref arguments, true, mg.Location) != null;
700 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
702 if (delegate_instance_expression != null)
703 delegate_instance_expression.MutateHoistedGenericType (storey);
705 delegate_method = storey.MutateGenericMethod (delegate_method);
706 constructor_method = storey.MutateConstructor (constructor_method);
709 #region IErrorHandler Members
711 public bool NoExactMatch (ResolveContext ec, MethodBase method)
713 if (TypeManager.IsGenericMethod (method))
714 return false;
716 Error_ConversionFailed (ec, method, null);
717 return true;
720 public bool AmbiguousCall (ResolveContext ec, MethodBase ambiguous)
722 return false;
725 #endregion
729 // Created from the conversion code
731 public class ImplicitDelegateCreation : DelegateCreation
733 ImplicitDelegateCreation (Type t, MethodGroupExpr mg, Location l)
735 type = t;
736 this.method_group = mg;
737 loc = l;
740 static public Expression Create (ResolveContext ec, MethodGroupExpr mge,
741 Type target_type, Location loc)
743 ImplicitDelegateCreation d = new ImplicitDelegateCreation (target_type, mge, loc);
744 return d.DoResolve (ec);
749 // A delegate-creation-expression, invoked from the `New' class
751 public class NewDelegate : DelegateCreation
753 public Arguments Arguments;
756 // This constructor is invoked from the `New' expression
758 public NewDelegate (Type type, Arguments Arguments, Location loc)
760 this.type = type;
761 this.Arguments = Arguments;
762 this.loc = loc;
765 public override Expression DoResolve (ResolveContext ec)
767 if (Arguments == null || Arguments.Count != 1) {
768 ec.Report.Error (149, loc, "Method name expected");
769 return null;
772 Argument a = Arguments [0];
773 if (!a.ResolveMethodGroup (ec))
774 return null;
776 Expression e = a.Expr;
778 AnonymousMethodExpression ame = e as AnonymousMethodExpression;
779 if (ame != null && RootContext.Version != LanguageVersion.ISO_1) {
780 e = ame.Compatible (ec, type);
781 if (e == null)
782 return null;
784 return e.Resolve (ec);
787 method_group = e as MethodGroupExpr;
788 if (method_group == null) {
789 if (!TypeManager.IsDelegateType (e.Type)) {
790 e.Error_UnexpectedKind (ec, ResolveFlags.MethodGroup | ResolveFlags.Type, loc);
791 return null;
795 // An argument is not a method but another delegate
797 delegate_instance_expression = e;
798 method_group = new MethodGroupExpr (new MemberInfo [] {
799 Delegate.GetInvokeMethod (ec.Compiler, ec.CurrentType, e.Type) }, e.Type, loc);
802 return base.DoResolve (ec);
806 public class DelegateInvocation : ExpressionStatement {
808 readonly Expression InstanceExpr;
809 Arguments Arguments;
810 MethodInfo method;
812 public DelegateInvocation (Expression instance_expr, Arguments args, Location loc)
814 this.InstanceExpr = instance_expr;
815 this.Arguments = args;
816 this.loc = loc;
819 public override Expression CreateExpressionTree (ResolveContext ec)
821 Arguments args = Arguments.CreateForExpressionTree (ec, Arguments,
822 InstanceExpr.CreateExpressionTree (ec));
824 return CreateExpressionFactoryCall (ec, "Invoke", args);
827 public override Expression DoResolve (ResolveContext ec)
829 if (InstanceExpr is EventExpr) {
830 ((EventExpr) InstanceExpr).Error_CannotAssign (ec);
831 return null;
834 Type del_type = InstanceExpr.Type;
835 if (del_type == null)
836 return null;
838 if (!Delegate.VerifyApplicability (ec, del_type, ref Arguments, loc))
839 return null;
841 method = Delegate.GetInvokeMethod (ec.Compiler, ec.CurrentType, del_type);
842 type = TypeManager.TypeToCoreType (method.ReturnType);
843 eclass = ExprClass.Value;
845 return this;
848 public override void Emit (EmitContext ec)
851 // Invocation on delegates call the virtual Invoke member
852 // so we are always `instance' calls
854 Invocation.EmitCall (ec, false, InstanceExpr, method, Arguments, loc);
857 public override void EmitStatement (EmitContext ec)
859 Emit (ec);
861 // Pop the return value if there is one
863 if (type != TypeManager.void_type)
864 ec.ig.Emit (OpCodes.Pop);
867 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
869 method = storey.MutateGenericMethod (method);
870 type = storey.MutateType (type);
872 if (Arguments != null)
873 Arguments.MutateHoistedGenericType (storey);
875 InstanceExpr.MutateHoistedGenericType (storey);