2010-04-11 Veerapuram Varadhan <vvaradhan@novell.com>
[mono.git] / mcs / mcs / method.cs
index f7f9f350790409426f50a1d506da6319445a2f62..7c7e12e10858008c4526f82f1abd9d05550b1ffe 100644 (file)
@@ -35,6 +35,7 @@ namespace Mono.CSharp {
        {
                public readonly ParametersCompiled Parameters;
                protected ToplevelBlock block;
+               protected MethodSpec spec;
 
                public MethodCore (DeclSpace parent, GenericMethod generic,
                        FullNamedExpression type, Modifiers mod, Modifiers allowed_mod,
@@ -130,6 +131,10 @@ namespace Mono.CSharp {
                        return base.EnableOverloadChecks (overload);
                }
 
+               public MethodSpec Spec {
+                       get { return spec; }
+               }
+
                protected override bool VerifyClsCompliance ()
                {
                        if (!base.VerifyClsCompliance ())
@@ -149,13 +154,88 @@ namespace Mono.CSharp {
                }
        }
 
+       interface IGenericMethodDefinition : IMemberDefinition
+       {
+               MethodInfo MakeGenericMethod (Type[] targs);
+       }
+
        public class MethodSpec : MemberSpec
        {
-               public MethodInfo MetaInfo;
+               MethodBase metaInfo;
+               readonly AParametersCollection parameters;
 
-               protected MethodSpec (IMemberDetails details, string name, Modifiers modifiers)
-                       : base (details, name, modifiers)
+               public MethodSpec (MemberKind kind, IMemberDefinition details, MethodBase info, AParametersCollection parameters, Modifiers modifiers)
+                       : base (kind, details, info.Name, modifiers)
                {
+                       this.MetaInfo = info;
+                       this.parameters = parameters;
+               }
+
+               public override Type DeclaringType {
+                       get {
+                               return MetaInfo.DeclaringType;
+                       }
+               }
+
+               public Type[] GetGenericArguments ()
+               {
+                       return MetaInfo.GetGenericArguments ();
+               }
+
+               public MethodSpec Inflate (Type[] targs)
+               {
+                       // TODO: Only create MethodSpec and inflate parameters, defer the call for later
+                       var mb = ((IGenericMethodDefinition) definition).MakeGenericMethod (targs);
+
+                       // TODO: Does not work on .NET
+                       var par = TypeManager.GetParameterData (mb);
+
+                       return new MethodSpec (Kind, definition, mb, par, Modifiers);
+               }
+
+               public bool IsAbstract {
+                       get {
+                               return (Modifiers & Modifiers.ABSTRACT) != 0;
+                       }
+               }
+
+               public bool IsConstructor {
+                       get {
+                               return MetaInfo.IsConstructor;
+                       }
+               }
+
+               public bool IsGenericMethod {
+                       get {
+                               return MetaInfo.IsGenericMethod;
+                       }
+               }
+
+               // When is virtual or abstract
+               public bool IsVirtual {
+                       get {
+                               return (Modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) != 0;
+                       }
+               }
+
+               public MethodBase MetaInfo {
+                       get {
+                               return metaInfo;
+                       }
+                       set {
+                               metaInfo = value;
+                       }
+               }
+
+               public AParametersCollection Parameters {
+                       get { return parameters; }
+               }
+
+               public Type ReturnType {
+                       get {
+                               return IsConstructor ?
+                                       TypeManager.void_type : ((MethodInfo) MetaInfo).ReturnType;
+                       }
                }
        }
 
@@ -258,6 +338,14 @@ namespace Mono.CSharp {
                                ModFlags |= Modifiers.DEBUGGER_HIDDEN;
                        }
 
+                       MemberKind kind;
+                       if (this is Operator)
+                               kind = MemberKind.Operator;
+                       else if (this is Destructor)
+                               kind = MemberKind.Destructor;
+                       else
+                               kind = MemberKind.Method;
+
                        if (IsPartialDefinition) {
                                caching_flags &= ~Flags.Excluded_Undetected;
                                caching_flags |= Flags.Excluded;
@@ -265,7 +353,9 @@ namespace Mono.CSharp {
                                // Add to member cache only when a partial method implementation has not been found yet
                                if ((caching_flags & Flags.PartialDefinitionExists) == 0) {
                                        MethodBase mb = new PartialMethodDefinitionInfo (this);
-                                       Parent.MemberCache.AddMember (mb, this);
+
+                                       spec = new MethodSpec (kind, this, mb, Parameters, ModFlags);
+                                       Parent.MemberCache.AddMember (mb, spec);
                                        TypeManager.AddMethod (mb, this);
                                }
 
@@ -280,10 +370,12 @@ namespace Mono.CSharp {
                                        
                        MethodBuilder = MethodData.MethodBuilder;
 
+                       spec = new MethodSpec (kind, this, MethodBuilder, Parameters, ModFlags);
+
                        if (TypeManager.IsGenericMethod (MethodBuilder))
                                Parent.MemberCache.AddGenericMember (MethodBuilder, this);
                        
-                       Parent.MemberCache.AddMember (MethodBuilder, this);
+                       Parent.MemberCache.AddMember (MethodBuilder, spec);
 
                        return true;
                }
@@ -515,8 +607,8 @@ namespace Mono.CSharp {
                }
        }
 
-       public class Method : MethodOrOperator {
-
+       public class Method : MethodOrOperator, IGenericMethodDefinition
+       {
                /// <summary>
                ///   Modifiers allowed in a class declaration
                /// </summary>
@@ -543,7 +635,7 @@ namespace Mono.CSharp {
                               FullNamedExpression return_type, Modifiers mod,
                               MemberName name, ParametersCompiled parameters, Attributes attrs)
                        : base (parent, generic, return_type, mod,
-                               parent.PartialContainer.Kind == Kind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
+                               parent.PartialContainer.Kind == MemberKind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
                                name, attrs, parameters)
                {
                }
@@ -756,7 +848,7 @@ namespace Mono.CSharp {
                                                        Report.Warning (402, 4, Location, "`{0}': an entry point cannot be generic or in a generic type",
                                                                GetSignatureForError ());
                                                } else {
-                                                       SetMemberIsUsed ();
+                                                       SetIsUsed ();
                                                        RootContext.EntryPoint = this;
                                                }
                                        } else {
@@ -835,6 +927,11 @@ namespace Mono.CSharp {
                        return mi;
                }
 
+               public MethodInfo MakeGenericMethod (Type[] targs)
+               {
+                       return MethodBuilder.MakeGenericMethod (targs);
+               }
+
                public void SetPartialDefinition (Method methodDefinition)
                {
                        caching_flags |= Flags.PartialDefinitionExists;
@@ -957,9 +1054,9 @@ namespace Mono.CSharp {
                        if (!ec.IsStatic)
                                base_constructor_group.InstanceExpression = ec.GetThis (loc);
                        
-                       ConstructorInfo base_ctor = (ConstructorInfo)base_constructor_group;
+                       var base_ctor = base_constructor_group.BestCandidate;
 
-                       if (base_ctor == caller_builder){
+                       if (base_ctor.MetaInfo == caller_builder){
                                ec.Report.Error (516, loc, "Constructor `{0}' cannot call itself", TypeManager.CSharpSignature (caller_builder));
                        }
                                                
@@ -1095,7 +1192,7 @@ namespace Mono.CSharp {
                                Parent.MemberCache.CheckExistingMembersOverloads (this, ConstructorInfo.ConstructorName,
                                        Parameters, Report);
 
-                       if (Parent.PartialContainer.Kind == Kind.Struct) {
+                       if (Parent.PartialContainer.Kind == MemberKind.Struct) {
                                if (Parameters.Count == 0) {
                                        Report.Error (568, Location, 
                                                "Structs cannot contain explicit parameterless constructors");
@@ -1148,6 +1245,8 @@ namespace Mono.CSharp {
                                ca, CallingConventions,
                                Parameters.GetEmitTypes ());
 
+                       spec = new MethodSpec (MemberKind.Constructor, this, ConstructorBuilder, Parameters, ModFlags);
+
                        if (Parent.PartialContainer.IsComImport) {
                                if (!IsDefault ()) {
                                        Report.Error (669, Location, "`{0}': A class with the ComImport attribute cannot have a user-defined constructor",
@@ -1156,7 +1255,7 @@ namespace Mono.CSharp {
                                ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall);
                        }
                        
-                       Parent.MemberCache.AddMember (ConstructorBuilder, this);
+                       Parent.MemberCache.AddMember (ConstructorBuilder, spec);
                        TypeManager.AddMethod (ConstructorBuilder, this);
                        
                        // It's here only to report an error
@@ -1197,12 +1296,12 @@ namespace Mono.CSharp {
                        if (block != null) {
                                // If this is a non-static `struct' constructor and doesn't have any
                                // initializer, it must initialize all of the struct's fields.
-                               if ((Parent.PartialContainer.Kind == Kind.Struct) &&
+                               if ((Parent.PartialContainer.Kind == MemberKind.Struct) &&
                                        ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
                                        block.AddThisVariable (Parent, Location);
 
                                if (block != null && (ModFlags & Modifiers.STATIC) == 0){
-                                       if (Parent.PartialContainer.Kind == Kind.Class && Initializer == null)
+                                       if (Parent.PartialContainer.Kind == MemberKind.Class && Initializer == null)
                                                Initializer = new GeneratedBaseInitializer (Location);
 
                                        if (Initializer != null) {
@@ -1337,7 +1436,7 @@ namespace Mono.CSharp {
                string GetSignatureForError ();
                bool IsExcluded ();
                bool IsClsComplianceRequired ();
-               void SetMemberIsUsed ();
+               void SetIsUsed ();
                void EmitExtraSymbolInfo (SourceMethod source);
        }
 
@@ -1643,7 +1742,7 @@ namespace Mono.CSharp {
                                new MemberName (MetadataName, l), attrs, parameters)
                {
                        ModFlags &= ~Modifiers.PRIVATE;
-                       ModFlags |= Modifiers.PROTECTED;
+                       ModFlags |= Modifiers.PROTECTED | Modifiers.OVERRIDE;
                }
 
                public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
@@ -1658,8 +1757,6 @@ namespace Mono.CSharp {
 
                protected override bool CheckBase ()
                {
-                       flags |= MethodAttributes.Virtual;
-
                        if (!base.CheckBase ())
                                return false;
 
@@ -1923,8 +2020,7 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               public override bool IsUsed
-               {
+               public override bool IsUsed {
                        get {
                                if (IsDummy)
                                        return false;
@@ -1933,6 +2029,8 @@ namespace Mono.CSharp {
                        }
                }
 
+               public MethodSpec Spec { get; protected set; }
+
                //
                //   Represents header string for documentation comment.
                //
@@ -2226,6 +2324,16 @@ namespace Mono.CSharp {
                        return null;
                }
 
+               public static OpType? GetType (string metadata_name)
+               {
+                       for (int i = 0; i < names.Length; ++i) {
+                               if (names[i][1] == metadata_name)
+                                       return (OpType) i;
+                       }
+
+                       return null;
+               }
+
                public OpType GetMatchingOperator ()
                {
                        switch (OperatorType) {