2 // delegate.cs: Delegate Handler
5 // Ravi Pratap (ravi@ximian.com)
6 // Miguel de Icaza (miguel@ximian.com)
8 // Licensed under the terms of the GNU GPL
10 // (C) 2001 Ximian, Inc (http://www.ximian.com)
15 using System
.Collections
;
16 using System
.Reflection
;
17 using System
.Reflection
.Emit
;
20 namespace Mono
.CSharp
{
25 public class Delegate
: DeclSpace
{
26 public Expression ReturnType
;
27 public Parameters Parameters
;
29 public ConstructorBuilder ConstructorBuilder
;
30 public MethodBuilder InvokeBuilder
;
31 public MethodBuilder BeginInvokeBuilder
;
32 public MethodBuilder EndInvokeBuilder
;
36 static string[] attribute_targets
= new string [] { "type", "return" }
;
38 Expression instance_expr
;
39 MethodBase delegate_method
;
40 ReturnParameter return_attributes
;
42 const int AllowedModifiers
=
50 public Delegate (NamespaceEntry ns
, DeclSpace parent
, Expression type
,
51 int mod_flags
, MemberName name
, Parameters param_list
,
53 : base (ns
, parent
, name
, attrs
)
56 this.ReturnType
= type
;
57 ModFlags
= Modifiers
.Check (AllowedModifiers
, mod_flags
,
58 IsTopLevel
? Modifiers
.INTERNAL
:
59 Modifiers
.PRIVATE
, name
.Location
);
60 Parameters
= param_list
;
63 public override void ApplyAttributeBuilder(Attribute a
, CustomAttributeBuilder cb
)
65 if (a
.Target
== AttributeTargets
.ReturnValue
) {
66 if (return_attributes
== null)
67 return_attributes
= new ReturnParameter (InvokeBuilder
, Location
);
69 return_attributes
.ApplyAttributeBuilder (a
, cb
);
73 base.ApplyAttributeBuilder (a
, cb
);
76 public override TypeBuilder
DefineType ()
78 if (TypeBuilder
!= null)
82 foreach (TypeParameter type_param
in TypeParameters
)
83 if (!type_param
.Resolve (this))
87 if (TypeManager
.multicast_delegate_type
== null && !RootContext
.StdLib
) {
88 Namespace system
= RootNamespace
.Global
.GetNamespace ("System", true);
89 TypeExpr expr
= system
.Lookup (this, "MulticastDelegate", Location
) as TypeExpr
;
90 TypeManager
.multicast_delegate_type
= expr
.Type
;
93 if (TypeManager
.multicast_delegate_type
== null)
94 Report
.Error (-100, Location
, "Internal error: delegate used before " +
95 "System.MulticastDelegate is resolved. This can only " +
96 "happen during corlib compilation, when using a delegate " +
97 "in any of the `core' classes. See bug #72015 for details.");
100 if (TypeManager
.NamespaceClash (Name
, Location
))
103 ModuleBuilder builder
= CodeGen
.Module
.Builder
;
105 TypeBuilder
= builder
.DefineType (
106 Name
, TypeAttr
, TypeManager
.multicast_delegate_type
);
108 TypeBuilder builder
= Parent
.TypeBuilder
;
110 string name
= Name
.Substring (1 + Name
.LastIndexOf ('.'));
111 TypeBuilder
= builder
.DefineNestedType (
112 name
, TypeAttr
, TypeManager
.multicast_delegate_type
);
115 TypeManager
.AddUserType (this);
118 string[] param_names
= new string [TypeParameters
.Length
];
119 for (int i
= 0; i
< TypeParameters
.Length
; i
++)
120 param_names
[i
] = TypeParameters
[i
].Name
;
122 GenericTypeParameterBuilder
[] gen_params
;
123 gen_params
= TypeBuilder
.DefineGenericParameters (param_names
);
125 int offset
= CountTypeParameters
- CurrentTypeParameters
.Length
;
126 for (int i
= offset
; i
< gen_params
.Length
; i
++)
127 CurrentTypeParameters
[i
- offset
].Define (gen_params
[i
]);
129 foreach (TypeParameter type_param
in CurrentTypeParameters
) {
130 if (!type_param
.Resolve (this))
134 Expression current
= new SimpleName (
135 MemberName
.Basename
, TypeParameters
, Location
);
136 current
= current
.ResolveAsTypeTerminal (this, false);
140 CurrentType
= current
.Type
;
146 public override bool Define ()
149 foreach (TypeParameter type_param
in TypeParameters
)
150 type_param
.DefineType (this);
153 // FIXME: POSSIBLY make this static, as it is always constant
155 Type
[] const_arg_types
= new Type
[2];
156 const_arg_types
[0] = TypeManager
.object_type
;
157 const_arg_types
[1] = TypeManager
.intptr_type
;
159 const MethodAttributes ctor_mattr
= MethodAttributes
.RTSpecialName
| MethodAttributes
.SpecialName
|
160 MethodAttributes
.HideBySig
| MethodAttributes
.Public
;
162 ConstructorBuilder
= TypeBuilder
.DefineConstructor (ctor_mattr
,
163 CallingConventions
.Standard
,
166 ConstructorBuilder
.DefineParameter (1, ParameterAttributes
.None
, "object");
167 ConstructorBuilder
.DefineParameter (2, ParameterAttributes
.None
, "method");
169 // HACK because System.Reflection.Emit is lame
171 Parameter
[] fixed_pars
= new Parameter
[2];
172 fixed_pars
[0] = new Parameter (TypeManager
.object_type
, "object",
173 Parameter
.Modifier
.NONE
, null, Location
);
174 fixed_pars
[1] = new Parameter (TypeManager
.intptr_type
, "method",
175 Parameter
.Modifier
.NONE
, null, Location
);
176 Parameters const_parameters
= new Parameters (fixed_pars
);
177 const_parameters
.Resolve (null);
179 TypeManager
.RegisterMethod (ConstructorBuilder
, const_parameters
);
182 ConstructorBuilder
.SetImplementationFlags (MethodImplAttributes
.Runtime
);
185 // Here the various methods like Invoke, BeginInvoke etc are defined
187 // First, call the `out of band' special method for
188 // defining recursively any types we need:
190 if (!Parameters
.Resolve (this))
197 // Check accessibility
198 foreach (Type partype
in Parameters
.Types
){
199 if (!Parent
.AsAccessible (partype
, ModFlags
)) {
200 Report
.Error (59, Location
,
201 "Inconsistent accessibility: parameter type `" +
202 TypeManager
.CSharpName (partype
) + "' is less " +
203 "accessible than delegate `" + Name
+ "'");
208 ReturnType
= ReturnType
.ResolveAsTypeTerminal (this, false);
209 if (ReturnType
== null)
212 ret_type
= ReturnType
.Type
;
214 if (!Parent
.AsAccessible (ret_type
, ModFlags
)) {
215 Report
.Error (58, Location
,
216 "Inconsistent accessibility: return type `" +
217 TypeManager
.CSharpName (ret_type
) + "' is less " +
218 "accessible than delegate `" + Name
+ "'");
222 if (RootContext
.StdLib
&& (ret_type
== TypeManager
.arg_iterator_type
|| ret_type
== TypeManager
.typed_reference_type
)) {
223 Method
.Error1599 (Location
, ret_type
);
228 // We don't have to check any others because they are all
229 // guaranteed to be accessible - they are standard types.
232 CallingConventions cc
= Parameters
.CallingConvention
;
234 const MethodAttributes mattr
= MethodAttributes
.Public
| MethodAttributes
.HideBySig
| MethodAttributes
.Virtual
| MethodAttributes
.NewSlot
;
236 InvokeBuilder
= TypeBuilder
.DefineMethod ("Invoke",
242 InvokeBuilder
.SetImplementationFlags (MethodImplAttributes
.Runtime
);
244 TypeManager
.RegisterMethod (InvokeBuilder
, Parameters
);
250 Parameters async_parameters
= Parameters
.MergeGenerated (Parameters
,
251 new Parameter (TypeManager
.asynccallback_type
, "callback", Parameter
.Modifier
.NONE
, null, Location
),
252 new Parameter (TypeManager
.object_type
, "object", Parameter
.Modifier
.NONE
, null, Location
));
254 BeginInvokeBuilder
= TypeBuilder
.DefineMethod ("BeginInvoke",
255 mattr
, cc
, TypeManager
.iasyncresult_type
, async_parameters
.Types
);
257 BeginInvokeBuilder
.SetImplementationFlags (MethodImplAttributes
.Runtime
);
258 async_parameters
.ApplyAttributes (BeginInvokeBuilder
);
259 TypeManager
.RegisterMethod (BeginInvokeBuilder
, async_parameters
);
262 // EndInvoke is a bit more interesting, all the parameters labeled as
263 // out or ref have to be duplicated here.
267 // Define parameters, and count out/ref parameters
269 Parameters end_parameters
;
272 foreach (Parameter p
in Parameters
.FixedParameters
) {
273 if ((p
.ModFlags
& Parameter
.Modifier
.ISBYREF
) != 0)
277 if (out_params
> 0) {
278 Type
[] end_param_types
= new Type
[out_params
];
279 Parameter
[] end_params
= new Parameter
[out_params
];
282 for (int i
= 0; i
< Parameters
.FixedParameters
.Length
; ++i
) {
283 Parameter p
= Parameters
.FixedParameters
[i
];
284 if ((p
.ModFlags
& Parameter
.Modifier
.ISBYREF
) == 0)
287 end_param_types
[param
] = p
.ExternalType();
288 end_params
[param
] = p
;
291 end_parameters
= new Parameters (end_params
, end_param_types
);
294 end_parameters
= Parameters
.EmptyReadOnlyParameters
;
297 end_parameters
= Parameters
.MergeGenerated (end_parameters
,
298 new Parameter (TypeManager
.iasyncresult_type
, "result", Parameter
.Modifier
.NONE
, null, Location
));
301 // Create method, define parameters, register parameters with type system
303 EndInvokeBuilder
= TypeBuilder
.DefineMethod ("EndInvoke", mattr
, cc
, ret_type
, end_parameters
.Types
);
304 EndInvokeBuilder
.SetImplementationFlags (MethodImplAttributes
.Runtime
);
306 end_parameters
.ApplyAttributes (EndInvokeBuilder
);
307 TypeManager
.RegisterMethod (EndInvokeBuilder
, end_parameters
);
312 public override void Emit ()
314 Parameters
.ApplyAttributes (InvokeBuilder
);
316 if (OptAttributes
!= null) {
317 OptAttributes
.Emit ();
323 protected override TypeAttributes TypeAttr
{
325 return Modifiers
.TypeAttr (ModFlags
, IsTopLevel
) |
326 TypeAttributes
.Class
| TypeAttributes
.Sealed
|
331 public override string[] ValidAttributeTargets
{
333 return attribute_targets
;
338 protected override bool VerifyClsCompliance ()
340 if (!base.VerifyClsCompliance ()) {
344 Parameters
.VerifyClsCompliance ();
346 if (!AttributeTester
.IsClsCompliant (ReturnType
.Type
)) {
347 Report
.Error (3002, Location
, "Return type of `{0}' is not CLS-compliant", GetSignatureForError ());
353 // Returns the MethodBase for "Invoke" from a delegate type, this is used
354 // to extract the signature of a delegate.
356 public static MethodGroupExpr
GetInvokeMethod (Type container_type
, Type delegate_type
, Location loc
)
358 Expression ml
= Expression
.MemberLookup (container_type
, null, delegate_type
,
361 MethodGroupExpr mg
= ml
as MethodGroupExpr
;
363 Report
.Error (-100, loc
, "Internal error: could not find Invoke method!");
371 /// Verifies whether the method in question is compatible with the delegate
372 /// Returns the method itself if okay and null if not.
374 public static MethodBase
VerifyMethod (Type container_type
, Type delegate_type
,
375 MethodGroupExpr old_mg
, MethodBase mb
,
378 MethodGroupExpr mg
= GetInvokeMethod (container_type
, delegate_type
, loc
);
382 if (old_mg
.HasTypeArguments
)
383 mg
.HasTypeArguments
= true;
385 MethodBase invoke_mb
= mg
.Methods
[0];
386 ParameterData invoke_pd
= TypeManager
.GetParameterData (invoke_mb
);
388 if (!mg
.HasTypeArguments
&&
389 !TypeManager
.InferTypeArguments (invoke_pd
, ref mb
))
392 ParameterData pd
= TypeManager
.GetParameterData (mb
);
394 if (invoke_pd
.Count
!= pd
.Count
)
397 for (int i
= pd
.Count
; i
> 0; ) {
400 Type invoke_pd_type
= invoke_pd
.ParameterType (i
);
401 Type pd_type
= pd
.ParameterType (i
);
402 Parameter
.Modifier invoke_pd_type_mod
= invoke_pd
.ParameterModifier (i
);
403 Parameter
.Modifier pd_type_mod
= pd
.ParameterModifier (i
);
405 if (invoke_pd_type
== pd_type
&&
406 invoke_pd_type_mod
== pd_type_mod
)
409 if (invoke_pd_type
.IsSubclassOf (pd_type
) &&
410 invoke_pd_type_mod
== pd_type_mod
)
411 if (RootContext
.Version
== LanguageVersion
.ISO_1
) {
412 Report
.FeatureIsNotStandardized (loc
, "contravariance");
420 Type invoke_mb_retval
= ((MethodInfo
) invoke_mb
).ReturnType
;
421 Type mb_retval
= ((MethodInfo
) mb
).ReturnType
;
422 if (invoke_mb_retval
== mb_retval
)
425 if (mb_retval
.IsSubclassOf (invoke_mb_retval
))
426 if (RootContext
.Version
== LanguageVersion
.ISO_1
) {
427 Report
.FeatureIsNotStandardized (loc
, "covariance");
437 // Verifies whether the invocation arguments are compatible with the
438 // delegate's target method
440 public static bool VerifyApplicability (EmitContext ec
, Type delegate_type
,
441 ArrayList args
, Location loc
)
448 arg_count
= args
.Count
;
450 Expression ml
= Expression
.MemberLookup (
451 ec
.ContainerType
, delegate_type
, "Invoke", loc
);
453 MethodGroupExpr me
= ml
as MethodGroupExpr
;
455 Report
.Error (-100, loc
, "Internal error: could not find Invoke method!" + delegate_type
);
459 MethodBase mb
= me
.Methods
[0];
460 ParameterData pd
= TypeManager
.GetParameterData (mb
);
462 int pd_count
= pd
.Count
;
464 bool params_method
= pd
.HasParams
;
465 bool is_params_applicable
= false;
466 bool is_applicable
= Invocation
.IsApplicable (ec
, me
, args
, arg_count
, ref mb
);
468 if (!is_applicable
&& params_method
&&
469 Invocation
.IsParamsMethodApplicable (ec
, me
, args
, arg_count
, ref mb
))
470 is_applicable
= is_params_applicable
= true;
472 if (!is_applicable
&& !params_method
&& arg_count
!= pd_count
) {
473 Report
.Error (1593, loc
, "Delegate `{0}' does not take `{1}' arguments",
474 TypeManager
.CSharpName (delegate_type
), arg_count
.ToString ());
478 return Invocation
.VerifyArgumentsCompat (
479 ec
, args
, arg_count
, mb
,
480 is_params_applicable
|| (!is_applicable
&& params_method
),
481 delegate_type
, false, loc
);
485 /// Verifies whether the delegate in question is compatible with this one in
486 /// order to determine if instantiation from the same is possible.
488 public static bool VerifyDelegate (EmitContext ec
, Type delegate_type
, Location loc
)
490 Expression ml
= Expression
.MemberLookup (
491 ec
.ContainerType
, delegate_type
, "Invoke", loc
);
493 if (!(ml
is MethodGroupExpr
)) {
494 Report
.Error (-100, loc
, "Internal error: could not find Invoke method!");
498 MethodBase mb
= ((MethodGroupExpr
) ml
).Methods
[0];
499 ParameterData pd
= TypeManager
.GetParameterData (mb
);
501 Expression probe_ml
= Expression
.MemberLookup (
502 ec
.ContainerType
, delegate_type
, "Invoke", loc
);
504 if (!(probe_ml
is MethodGroupExpr
)) {
505 Report
.Error (-100, loc
, "Internal error: could not find Invoke method!");
509 MethodBase probe_mb
= ((MethodGroupExpr
) probe_ml
).Methods
[0];
510 ParameterData probe_pd
= TypeManager
.GetParameterData (probe_mb
);
512 if (((MethodInfo
) mb
).ReturnType
!= ((MethodInfo
) probe_mb
).ReturnType
)
515 if (pd
.Count
!= probe_pd
.Count
)
518 for (int i
= pd
.Count
; i
> 0; ) {
521 if (pd
.ParameterType (i
) != probe_pd
.ParameterType (i
) ||
522 pd
.ParameterModifier (i
) != probe_pd
.ParameterModifier (i
))
529 public static string FullDelegateDesc (Type del_type
, MethodBase mb
, ParameterData pd
)
531 StringBuilder sb
= new StringBuilder ();
532 sb
.Append (TypeManager
.CSharpName (((MethodInfo
) mb
).ReturnType
));
534 sb
.Append (TypeManager
.CSharpName (del_type
));
535 sb
.Append (pd
.GetSignatureForError ());
536 return sb
.ToString ();
539 // Hack around System.Reflection as found everywhere else
540 public override MemberList
FindMembers (MemberTypes mt
, BindingFlags bf
,
541 MemberFilter filter
, object criteria
)
543 ArrayList members
= new ArrayList ();
545 if ((mt
& MemberTypes
.Method
) != 0) {
546 if (ConstructorBuilder
!= null)
547 if (filter (ConstructorBuilder
, criteria
))
548 members
.Add (ConstructorBuilder
);
550 if (InvokeBuilder
!= null)
551 if (filter (InvokeBuilder
, criteria
))
552 members
.Add (InvokeBuilder
);
554 if (BeginInvokeBuilder
!= null)
555 if (filter (BeginInvokeBuilder
, criteria
))
556 members
.Add (BeginInvokeBuilder
);
558 if (EndInvokeBuilder
!= null)
559 if (filter (EndInvokeBuilder
, criteria
))
560 members
.Add (EndInvokeBuilder
);
563 return new MemberList (members
);
566 public override MemberCache MemberCache
{
572 public Expression InstanceExpression
{
574 return instance_expr
;
577 instance_expr
= value;
581 public MethodBase TargetMethod
{
583 return delegate_method
;
586 delegate_method
= value;
590 public Type TargetReturnType
{
596 public override AttributeTargets AttributeTargets
{
598 return AttributeTargets
.Delegate
;
603 // Represents header string for documentation comment.
605 public override string DocCommentHeader
{
612 // Base class for `NewDelegate' and `ImplicitDelegateCreation'
614 public abstract class DelegateCreation
: Expression
{
615 protected MethodBase constructor_method
;
616 protected MethodBase delegate_method
;
617 protected MethodGroupExpr method_group
;
618 protected Expression delegate_instance_expression
;
620 protected DelegateCreation () {}
622 public static void Error_NoMatchingMethodForDelegate (EmitContext ec
, MethodGroupExpr mg
, Type type
, Location loc
)
625 MethodBase found_method
= mg
.Methods
[0];
627 if (mg
.Methods
.Length
> 1)
628 method_desc
= found_method
.Name
;
630 method_desc
= Invocation
.FullMethodDesc (found_method
);
632 Expression invoke_method
= Expression
.MemberLookup (
633 ec
.ContainerType
, type
, "Invoke", MemberTypes
.Method
,
634 Expression
.AllBindingFlags
, loc
);
635 MethodInfo method
= ((MethodGroupExpr
) invoke_method
).Methods
[0] as MethodInfo
;
637 ParameterData param
= TypeManager
.GetParameterData (method
);
638 string delegate_desc
= Delegate
.FullDelegateDesc (type
, method
, param
);
640 if (!mg
.HasTypeArguments
&&
641 !TypeManager
.InferTypeArguments (param
, ref found_method
))
642 Report
.Error (411, loc
, "The type arguments for " +
643 "method `{0}' cannot be infered from " +
644 "the usage. Try specifying the type " +
645 "arguments explicitly.", method_desc
);
646 else if (method
.ReturnType
!= ((MethodInfo
) found_method
).ReturnType
) {
647 Report
.Error (407, loc
, "`{0}' has the wrong return type to match the delegate `{1}'", method_desc
, delegate_desc
);
649 Report
.Error (123, loc
, "Method `{0}' does not match delegate `{1}'", method_desc
, delegate_desc
);
653 public override void Emit (EmitContext ec
)
655 if (delegate_instance_expression
== null || delegate_method
.IsStatic
)
656 ec
.ig
.Emit (OpCodes
.Ldnull
);
658 delegate_instance_expression
.Emit (ec
);
660 if (delegate_method
.IsVirtual
&& !method_group
.IsBase
) {
661 ec
.ig
.Emit (OpCodes
.Dup
);
662 ec
.ig
.Emit (OpCodes
.Ldvirtftn
, (MethodInfo
) delegate_method
);
664 ec
.ig
.Emit (OpCodes
.Ldftn
, (MethodInfo
) delegate_method
);
665 ec
.ig
.Emit (OpCodes
.Newobj
, (ConstructorInfo
) constructor_method
);
668 protected bool ResolveConstructorMethod (EmitContext ec
)
670 Expression ml
= Expression
.MemberLookup (
671 ec
.ContainerType
, type
, ".ctor", loc
);
673 if (!(ml
is MethodGroupExpr
)) {
674 Report
.Error (-100, loc
, "Internal error: Could not find delegate constructor!");
678 constructor_method
= ((MethodGroupExpr
) ml
).Methods
[0];
682 public static MethodBase
ImplicitStandardConversionExists (MethodGroupExpr mg
, Type targetType
)
684 foreach (MethodInfo mi
in mg
.Methods
){
685 MethodBase mb
= Delegate
.VerifyMethod (mg
.DeclaringType
, targetType
, mg
, mi
, Location
.Null
);
692 protected Expression
ResolveMethodGroupExpr (EmitContext ec
, MethodGroupExpr mg
)
694 delegate_method
= ImplicitStandardConversionExists (mg
, type
);
696 if (delegate_method
== null) {
697 Error_NoMatchingMethodForDelegate (ec
, mg
, type
, loc
);
702 // Check safe/unsafe of the delegate
705 ParameterData param
= TypeManager
.GetParameterData (delegate_method
);
706 int count
= param
.Count
;
708 for (int i
= 0; i
< count
; i
++){
709 if (param
.ParameterType (i
).IsPointer
){
710 Expression
.UnsafeError (loc
);
716 //TODO: implement caching when performance will be low
717 IMethodData md
= TypeManager
.GetMethod (delegate_method
);
719 if (System
.Attribute
.GetCustomAttribute (delegate_method
, TypeManager
.conditional_attribute_type
) != null) {
720 Report
.SymbolRelatedToPreviousError (delegate_method
);
721 Report
.Error (1618, loc
, "Cannot create delegate with `{0}' because it has a Conditional attribute", TypeManager
.CSharpSignature (delegate_method
));
725 md
.SetMemberIsUsed ();
726 if (md
.OptAttributes
!= null && md
.OptAttributes
.Search (TypeManager
.conditional_attribute_type
) != null) {
727 Report
.SymbolRelatedToPreviousError (delegate_method
);
728 Report
.Error (1618, loc
, "Cannot create delegate with `{0}' because it has a Conditional attribute", TypeManager
.CSharpSignature (delegate_method
));
733 if (mg
.InstanceExpression
!= null)
734 delegate_instance_expression
= mg
.InstanceExpression
.Resolve (ec
);
735 else if (ec
.IsStatic
) {
736 if (!delegate_method
.IsStatic
) {
737 Report
.Error (120, loc
, "`{0}': An object reference is required for the nonstatic field, method or property",
738 TypeManager
.CSharpSignature (delegate_method
));
741 delegate_instance_expression
= null;
743 delegate_instance_expression
= ec
.GetThis (loc
);
745 if (delegate_instance_expression
!= null && delegate_instance_expression
.Type
.IsValueType
)
746 delegate_instance_expression
= new BoxedCast (
747 delegate_instance_expression
, TypeManager
.object_type
);
750 eclass
= ExprClass
.Value
;
756 // Created from the conversion code
758 public class ImplicitDelegateCreation
: DelegateCreation
{
760 ImplicitDelegateCreation (Type t
, Location l
)
766 public override Expression
DoResolve (EmitContext ec
)
771 static public Expression
Create (EmitContext ec
, MethodGroupExpr mge
,
772 Type target_type
, Location loc
)
774 ImplicitDelegateCreation d
= new ImplicitDelegateCreation (target_type
, loc
);
775 if (!d
.ResolveConstructorMethod (ec
))
778 return d
.ResolveMethodGroupExpr (ec
, mge
);
783 // A delegate-creation-expression, invoked from the `New' class
785 public class NewDelegate
: DelegateCreation
{
786 public ArrayList Arguments
;
789 // This constructor is invoked from the `New' expression
791 public NewDelegate (Type type
, ArrayList Arguments
, Location loc
)
794 this.Arguments
= Arguments
;
798 public override Expression
DoResolve (EmitContext ec
)
800 if (Arguments
== null || Arguments
.Count
!= 1) {
801 Report
.Error (149, loc
,
802 "Method name expected");
806 if (!ResolveConstructorMethod (ec
))
809 Argument a
= (Argument
) Arguments
[0];
811 if (!a
.ResolveMethodGroup (ec
))
814 Expression e
= a
.Expr
;
816 if (e
is AnonymousMethod
&& RootContext
.Version
!= LanguageVersion
.ISO_1
)
817 return ((AnonymousMethod
) e
).Compatible (ec
, type
);
819 MethodGroupExpr mg
= e
as MethodGroupExpr
;
821 return ResolveMethodGroupExpr (ec
, mg
);
823 if (!TypeManager
.IsDelegateType (e
.Type
)) {
824 Report
.Error (149, loc
, "Method name expected");
828 method_group
= Expression
.MemberLookup (
829 ec
.ContainerType
, type
, "Invoke", MemberTypes
.Method
,
830 Expression
.AllBindingFlags
, loc
) as MethodGroupExpr
;
832 if (method_group
== null) {
833 Report
.Error (-200, loc
, "Internal error ! Could not find Invoke method!");
837 // This is what MS' compiler reports. We could always choose
838 // to be more verbose and actually give delegate-level specifics
839 if (!Delegate
.VerifyDelegate (ec
, type
, loc
)) {
840 Report
.Error (29, loc
, "Cannot implicitly convert type '" + e
.Type
+ "' " +
841 "to type '" + type
+ "'");
845 delegate_instance_expression
= e
;
846 delegate_method
= method_group
.Methods
[0];
848 eclass
= ExprClass
.Value
;
853 public class DelegateInvocation
: ExpressionStatement
{
855 public Expression InstanceExpr
;
856 public ArrayList Arguments
;
860 public DelegateInvocation (Expression instance_expr
, ArrayList args
, Location loc
)
862 this.InstanceExpr
= instance_expr
;
863 this.Arguments
= args
;
867 public override Expression
DoResolve (EmitContext ec
)
869 if (InstanceExpr
is EventExpr
) {
871 EventInfo ei
= ((EventExpr
) InstanceExpr
).EventInfo
;
873 Expression ml
= MemberLookup (
874 ec
.ContainerType
, ec
.ContainerType
, ei
.Name
,
875 MemberTypes
.Event
, AllBindingFlags
| BindingFlags
.DeclaredOnly
, loc
);
879 // If this is the case, then the Event does not belong
880 // to this Type and so, according to the spec
881 // cannot be accessed directly
883 // Note that target will not appear as an EventExpr
884 // in the case it is being referenced within the same type container;
885 // it will appear as a FieldExpr in that case.
888 Assign
.error70 (ei
, loc
);
894 Type del_type
= InstanceExpr
.Type
;
895 if (del_type
== null)
898 if (Arguments
!= null){
899 foreach (Argument a
in Arguments
){
900 if (!a
.Resolve (ec
, loc
))
905 if (!Delegate
.VerifyApplicability (ec
, del_type
, Arguments
, loc
))
908 Expression lookup
= Expression
.MemberLookup (ec
.ContainerType
, del_type
, "Invoke", loc
);
909 if (!(lookup
is MethodGroupExpr
)) {
910 Report
.Error (-100, loc
, "Internal error: could not find Invoke method!");
914 method
= ((MethodGroupExpr
) lookup
).Methods
[0];
915 type
= ((MethodInfo
) method
).ReturnType
;
916 eclass
= ExprClass
.Value
;
921 public override void Emit (EmitContext ec
)
924 // Invocation on delegates call the virtual Invoke member
925 // so we are always `instance' calls
927 Invocation
.EmitCall (ec
, false, false, InstanceExpr
, method
, Arguments
, loc
);
930 public override void EmitStatement (EmitContext ec
)
934 // Pop the return value if there is one
936 if (method
is MethodInfo
){
937 Type ret
= ((MethodInfo
)method
).ReturnType
;
938 if (TypeManager
.TypeToCoreType (ret
) != TypeManager
.void_type
)
939 ec
.ig
.Emit (OpCodes
.Pop
);