2003-05-19 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mcs / class / corlib / System.Reflection.Emit / TypeBuilder.cs
index e242c48609cde8c6e9174dc6b7820213cfd3bbe8..724b1d83216b7f526eb55a90702d090c2bed26b3 100644 (file)
@@ -61,12 +61,13 @@ namespace System.Reflection.Emit {
                        setup_internal_class (this);
                }
 
-               internal TypeBuilder (ModuleBuilder mb, string name, TypeAttributes attr, Type parent, Type[] interfaces, PackingSize packing_size, int type_size) {
+               internal TypeBuilder (ModuleBuilder mb, string name, TypeAttributes attr, Type parent, Type[] interfaces, PackingSize packing_size, int type_size, Type nesting_type) {
                        int sep_index;
                        this.parent = parent;
                        this.attrs = attr;
                        this.class_size = type_size;
                        this.packing_size = packing_size;
+                       this.nesting_type = nesting_type;
                        sep_index = name.LastIndexOf('.');
                        if (sep_index != -1) {
                                this.tname = name.Substring (sep_index + 1);
@@ -89,6 +90,7 @@ namespace System.Reflection.Emit {
                public override Assembly Assembly {
                        get {return pmodule.Assembly;}
                }
+
                public override string AssemblyQualifiedName {
                        get {
                                return fullname + ", " + Assembly.GetName().FullName;
@@ -184,17 +186,58 @@ namespace System.Reflection.Emit {
                }
 
                [MonoTODO]
-               protected override ConstructorInfo GetConstructorImpl (BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) {
-                       throw new NotImplementedException ();
+               protected override ConstructorInfo GetConstructorImpl (BindingFlags bindingAttr, Binder binder,
+                                                                      CallingConventions callConvention, Type[] types,
+                                                                      ParameterModifier[] modifiers)
+               {
+                       if (ctors == null)
+                               return null;
+
+                       ConstructorBuilder found = null;
+                       int count = 0;
+                       
+                       foreach (ConstructorBuilder cb in ctors){
+                               if (callConvention != CallingConventions.Any && cb.CallingConvention != callConvention)
+                                       continue;
+                               found = cb;
+                               count++;
+                       }
+
+                       if (count == 0)
+                               return null;
+                       if (types == null){
+                               if (count > 1)
+                                       throw new AmbiguousMatchException ();
+                               return found;
+                       }
+                       MethodBase[] match = new MethodBase [count];
+                       if (count == 1)
+                               match [0] = found;
+                       else {
+                               count = 0;
+                               foreach (ConstructorInfo m in ctors) {
+                                       if (callConvention != CallingConventions.Any && m.CallingConvention != callConvention)
+                                               continue;
+                                       match [count++] = m;
+                               }
+                       }
+                       if (binder == null)
+                               binder = Binder.DefaultBinder;
+                       return (ConstructorInfo)binder.SelectMethod (bindingAttr, match, types, modifiers);
                }
 
-               public override bool IsDefined( Type attributeType, bool inherit) {
+               public override bool IsDefined( Type attributeType, bool inherit)
+               {
                        throw not_supported ();
                }
-               public override object[] GetCustomAttributes(bool inherit) {
+               
+               public override object[] GetCustomAttributes(bool inherit)
+               {
                        throw not_supported ();
                }
-               public override object[] GetCustomAttributes(Type attributeType, bool inherit) {
+               
+               public override object[] GetCustomAttributes(Type attributeType, bool inherit)
+               {
                        throw not_supported ();
                }
 
@@ -210,7 +253,9 @@ namespace System.Reflection.Emit {
                        return DefineNestedType (name, attr, parent, null);
                }
 
-               private TypeBuilder DefineNestedType (string name, TypeAttributes attr, Type parent, Type[] interfaces, PackingSize packsize, int typesize) {
+               private TypeBuilder DefineNestedType (string name, TypeAttributes attr, Type parent, Type[] interfaces,
+                                                     PackingSize packsize, int typesize)
+               {
                        check_name ("name", name);
                        // Visibility must be NestedXXX
                        /* This breaks mcs
@@ -223,8 +268,7 @@ namespace System.Reflection.Emit {
                                        if (iface == null)
                                                throw new ArgumentNullException ("interfaces");
 
-                       TypeBuilder res = new TypeBuilder (pmodule, name, attr, parent, interfaces, packsize, typesize);
-                       res.nesting_type = this;
+                       TypeBuilder res = new TypeBuilder (pmodule, name, attr, parent, interfaces, packsize, typesize, this);
                        res.fullname = res.GetFullName ();
                        pmodule.RegisterTypeName (res, res.fullname);
                        if (subtypes != null) {
@@ -251,7 +295,8 @@ namespace System.Reflection.Emit {
                        return DefineNestedType (name, attr, parent, null, packsize, UnspecifiedTypeSize);
                }
 
-               public ConstructorBuilder DefineConstructor( MethodAttributes attributes, CallingConventions callingConvention, Type[] parameterTypes) {
+               public ConstructorBuilder DefineConstructor (MethodAttributes attributes, CallingConventions callingConvention, Type[] parameterTypes)
+               {
                        if (is_created)
                                throw not_after_created ();
                        ConstructorBuilder cb = new ConstructorBuilder (this, attributes, callingConvention, parameterTypes);
@@ -267,8 +312,21 @@ namespace System.Reflection.Emit {
                        return cb;
                }
 
-               public ConstructorBuilder DefineDefaultConstructor( MethodAttributes attributes) {
-                       return DefineConstructor (attributes, CallingConventions.Standard, null);
+               public ConstructorBuilder DefineDefaultConstructor (MethodAttributes attributes)
+               {
+                       ConstructorBuilder cb = DefineConstructor (attributes, CallingConventions.Standard, null);
+
+                       ConstructorInfo parent_constructor = parent.GetConstructor (
+                               BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
+                               null, Type.EmptyTypes, null);
+
+                       ILGenerator ig = cb.GetILGenerator ();
+                       if (parent_constructor != null){
+                               ig.Emit (OpCodes.Ldarg_0);
+                               ig.Emit (OpCodes.Call, parent_constructor);
+                       }
+                       ig.Emit (OpCodes.Ret);
+                       return cb;
                }
 
                public MethodBuilder DefineMethod( string name, MethodAttributes attributes, Type returnType, Type[] parameterTypes) {
@@ -296,6 +354,8 @@ namespace System.Reflection.Emit {
                                !((attributes & MethodAttributes.Virtual) != 0)))
                                throw new ArgumentException ("attributes", "Interface method must be abstract and virtual.");
 
+                       if (returnType == null)
+                               returnType = pmodule.assemblyb.corlib_void_type;
                        MethodBuilder res = new MethodBuilder (this, name, attributes, callingConvention, returnType, parameterTypes);
                        append_method (res);
                        return res;
@@ -401,18 +461,26 @@ namespace System.Reflection.Emit {
                                        method.fixup ();
                                }
                        }
-                       if (ctors != null) {
-                               foreach (ConstructorBuilder ctor in ctors) {
+
+                       //
+                       // On classes, define a default constructor if not provided
+                       //
+                       if (!(IsInterface || IsValueType) && (ctors == null) && (tname != "<Module>"))
+                               DefineDefaultConstructor (MethodAttributes.Public);
+
+                       if (ctors != null){
+                               foreach (ConstructorBuilder ctor in ctors) 
                                        ctor.fixup ();
-                               }
                        }
+                       
                        created = create_runtime_class (this);
                        if (created != null)
                                return created;
                        return this;
                }
 
-               public override ConstructorInfo[] GetConstructors (BindingFlags bindingAttr) {
+               public override ConstructorInfo[] GetConstructors (BindingFlags bindingAttr)
+               {
                        if (ctors == null)
                                return new ConstructorInfo [0];
                        ArrayList l = new ArrayList ();
@@ -816,8 +884,6 @@ namespace System.Reflection.Emit {
                        TypeBuilder datablobtype = DefineNestedType ("$ArrayType$"+InitializedDataCount.ToString(),
                                TypeAttributes.NestedPrivate|TypeAttributes.ExplicitLayout|TypeAttributes.Sealed,
                                pmodule.assemblyb.corlib_value_type, null, PackingSize.Size1, data.Length);
-                       datablobtype.packing_size = PackingSize.Size1;
-                       datablobtype.class_size = data.Length;
                        datablobtype.CreateType ();
                        FieldBuilder res = DefineField (name, datablobtype, attributes|FieldAttributes.Assembly|FieldAttributes.Static|FieldAttributes.HasFieldRVA);
                        res.SetRVAData (data);
@@ -867,15 +933,18 @@ namespace System.Reflection.Emit {
                        }
                }
 
-               private Exception not_supported () {
+               private Exception not_supported ()
+               {
                        return new NotSupportedException ("The invoked member is not supported in a dynamic module.");
                }
 
-               private Exception not_after_created () {
+               private Exception not_after_created ()
+               {
                        return new InvalidOperationException ("Unable to change after type has been created.");
                }
 
-               private void check_name (string argName, string name) {
+               private void check_name (string argName, string name)
+               {
                        if (name == null)
                                throw new ArgumentNullException (argName);
                        if (name == "")