2001-09-12 Miguel de Icaza <miguel@ximian.com>
[mono.git] / mcs / mcs / class.cs
index 131f29a43b7a6dfcba100ad3c4ed41aa6804fa46..f05f3c0a3235859642fd452eaf38bc6387246957 100755 (executable)
@@ -7,30 +7,76 @@
 //
 // (C) 2001 Ximian, Inc (http://www.ximian.com)
 //
-// TODO:
-//
-//    a. Maybe keep a list of defined names in the order they
-//       appeared, so we can walk things in this way to present
-//       the users with errors in that order?
 //
 
 using System.Collections;
+using System.Reflection;
+using System.Reflection.Emit;
 using System;
 
 namespace CIR {
        
        public class TypeContainer : DeclSpace {
                protected int mod_flags;
-               Hashtable types, fields, properties;
-               Hashtable enums, constants, interfaces, method_groups;
 
-               ArrayList constructor_list;
+               // Holds a list of classes and structures
+               ArrayList types;
+
+               // Holds the list of properties
+               ArrayList properties;
+
+               // Holds the list of enumerations
+               ArrayList enums;
+
+               // Holds the list of delegates
+               ArrayList delegates;
+               
+               // Holds the list of constructors
+               ArrayList constructors;
+
+               // Holds the list of fields
+               ArrayList fields;
+
+               // Holds a list of fields that have initializers
+               ArrayList initialized_fields;
 
+               // Holds a list of static fields that have initializers
+               ArrayList initialized_static_fields;
+
+               // Holds the list of constants
+               ArrayList constants;
+
+               // Holds the list of
+               ArrayList interfaces;
+
+               // Holds the methods.
+               ArrayList methods;
+
+               // Holds the events
+               ArrayList events;
+
+               // Holds the indexers
+               ArrayList indexers;
+
+               // Holds the operators
+               ArrayList operators;
+               
+               //
+               // Pointers to the default constructor and the default static constructor
+               //
+               Constructor default_constructor;
+               Constructor default_static_constructor;
+               
+               //
+               // Whether we have seen a static constructor for this class or not
+               //
+               bool have_static_constructor = false;
+               
                //
                // This is the namespace in which this typecontainer
                // was declared.  We use this to resolve names.
                //
-               CSC.Namespace my_namespace;
+               Namespace my_namespace;
                
                //
                // This one is computed after we can distinguish interfaces
@@ -41,12 +87,23 @@ namespace CIR {
                TypeContainer parent;
                ArrayList type_bases;
 
-               public TypeContainer (TypeContainer parent, string name) : base (name)
+               //
+               // This behaves like a property ;-)
+               //
+               public readonly RootContext RootContext;
+
+               // Attributes for this type
+               protected Attributes attributes;
+
+               public TypeContainer (RootContext rc, TypeContainer parent, string name) : base (name)
                {
-                       types = new Hashtable ();
+                       string n;
+                       types = new ArrayList ();
                        this.parent = parent;
+                       RootContext = rc;
 
-                       string n;
+                       object a = rc.Report;
+                       
                        if (parent == null)
                                n = "";
                        else
@@ -66,9 +123,9 @@ namespace CIR {
                                return res;
                        
                        if (constants == null)
-                               constants = new Hashtable ();
+                               constants = new ArrayList ();
 
-                       constants.Add (name, constant);
+                       constants.Add (constant);
                        DefineName (name, constant);
 
                        return AdditionResult.Success;
@@ -83,9 +140,9 @@ namespace CIR {
                                return res;
 
                        if (enums == null)
-                               enums = new Hashtable ();
+                               enums = new ArrayList ();
 
-                       enums.Add (name, e);
+                       enums.Add (e);
                        DefineName (name, e);
 
                        return AdditionResult.Success;
@@ -101,7 +158,7 @@ namespace CIR {
                                return res;
 
                        DefineName (name, c);
-                       types.Add (name, c);
+                       types.Add (c);
 
                        return AdditionResult.Success;
                }
@@ -115,7 +172,24 @@ namespace CIR {
                                return res;
 
                        DefineName (name, s);
-                       types.Add (name, s);
+                       types.Add (s);
+
+                       return AdditionResult.Success;
+               }
+
+               public AdditionResult AddDelegate (Delegate d)
+               {
+                       AdditionResult res;
+                       string name = d.Name;
+
+                       if ((res = IsValid (name)) != AdditionResult.Success)
+                               return res;
+
+                       if (delegates == null)
+                               delegates = new ArrayList ();
+                       
+                       DefineName (name, d);
+                       delegates.Add (d);
 
                        return AdditionResult.Success;
                }
@@ -125,26 +199,15 @@ namespace CIR {
                        string name = method.Name;
                        Object value = defined_names [name];
                        
-                       if (value != null && (!(value is MethodGroup)))
+                       if (value != null && (!(value is Method)))
                                return AdditionResult.NameExists;
 
-                       if (method_groups == null)
-                               method_groups = new Hashtable ();
-
-                       MethodGroup mg = (MethodGroup) method_groups [name];
-                       if (mg == null){
-                               mg = new MethodGroup (name);
-
-                               mg.Add (method);
-                               method_groups.Add (name, mg);
+                       if (methods == null)
+                               methods = new ArrayList ();
 
-                               return AdditionResult.Success;
-                       }
-                       mg.Add (method);
+                       methods.Add (method);
+                       DefineName (name, method);
 
-                       if (value == null)
-                               DefineName (name, mg);
-                       
                        return AdditionResult.Success;
                }
 
@@ -153,10 +216,22 @@ namespace CIR {
                        if (c.Name != Basename)
                                return AdditionResult.NotAConstructor;
                        
-                       if (constructor_list == null)
-                               constructor_list = new ArrayList ();
+                       if (constructors == null)
+                               constructors = new ArrayList ();
 
-                       constructor_list.Add (c);
+                       constructors.Add (c);
+
+                       bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
+                       
+                       if (is_static)
+                               have_static_constructor = true;
+
+                       if (c.IsDefault ()){
+                               if (is_static)
+                                       default_static_constructor = c;
+                               else
+                                       default_constructor = c;
+                       }
                        
                        return AdditionResult.Success;
                }
@@ -170,8 +245,8 @@ namespace CIR {
                                return res;
                        
                        if (interfaces == null)
-                               interfaces = new Hashtable ();
-                       interfaces.Add (name, iface);
+                               interfaces = new ArrayList ();
+                       interfaces.Add (iface);
                        DefineName (name, iface);
                        
                        return AdditionResult.Success;
@@ -186,9 +261,29 @@ namespace CIR {
                                return res;
 
                        if (fields == null)
-                               fields = new Hashtable ();
-
-                       fields.Add (name, field);
+                               fields = new ArrayList ();
+
+                       fields.Add (field);
+                       if (field.Initializer != null){
+                               if ((field.ModFlags & Modifiers.STATIC) != 0){
+                                       if (initialized_static_fields == null)
+                                               initialized_static_fields = new ArrayList ();
+
+                                       initialized_static_fields.Add (field);
+
+                                       //
+                                       // We have not seen a static constructor,
+                                       // but we will provide static initialization of fields
+                                       //
+                                       have_static_constructor = true;
+                               } else {
+                                       if (initialized_fields == null)
+                                               initialized_fields = new ArrayList ();
+                               
+                                       initialized_fields.Add (field);
+                               }
+                       }
+                       
                        DefineName (name, field);
                        return AdditionResult.Success;
                }
@@ -202,16 +297,49 @@ namespace CIR {
                                return res;
 
                        if (properties == null)
-                               properties = new Hashtable ();
+                               properties = new ArrayList ();
 
-                       properties.Add (name, prop);
+                       properties.Add (prop);
                        DefineName (name, prop);
 
                        return AdditionResult.Success;
                }
-               
-               public Constant GetConstant (string name) {
-                       return (Constant) constants [name];
+
+               public AdditionResult AddEvent (Event e)
+               {
+                       AdditionResult res;
+                       string name = e.Name;
+
+                       if ((res = IsValid (name)) != AdditionResult.Success)
+                               return res;
+
+                       if (events == null)
+                               events = new ArrayList ();
+                       
+                       events.Add (e);
+                       DefineName (name, e);
+
+                       return AdditionResult.Success;
+               }
+
+               public AdditionResult AddIndexer (Indexer i)
+               {
+                       if (indexers == null)
+                               indexers = new ArrayList ();
+
+                       indexers.Add (i);
+
+                       return AdditionResult.Success;
+               }
+
+               public AdditionResult AddOperator (Operator op)
+               {
+                       if (operators == null)
+                               operators = new ArrayList ();
+
+                       operators.Add (op);
+
+                       return AdditionResult.Success;
                }
                
                public TypeContainer Parent {
@@ -220,25 +348,25 @@ namespace CIR {
                        }
                }
 
-               public Hashtable Types {
+               public ArrayList Types {
                        get {
                                return types;
                        }
                }
 
-               public Hashtable MethodGroups {
+               public ArrayList Methods {
                        get {
-                               return method_groups;
+                               return methods;
                        }
                }
 
-               public Hashtable Constants {
+               public ArrayList Constants {
                        get {
                                return constants;
                        }
                }
 
-               public Hashtable Interfaces {
+               public ArrayList Interfaces {
                        get {
                                return interfaces;
                        }
@@ -266,31 +394,61 @@ namespace CIR {
                        }
                }
 
-               public Hashtable Fields {
+               public ArrayList Fields {
                        get {
                                return fields;
                        }
                }
 
-               public Hashtable Constructors {
+               public ArrayList Constructors {
                        get {
-                               return null; // constructors;
+                               return constructors;
                        }
                }
 
-               public Hashtable Properties {
+               public ArrayList Properties {
                        get {
                                return properties;
                        }
                }
 
-               public Hashtable Enums {
+               public ArrayList Events {
+                       get {
+                               return events;
+                       }
+               }
+               
+               public ArrayList Enums {
                        get {
                                return enums;
                        }
                }
 
-               public CSC.Namespace Namespace {
+               public ArrayList Indexers {
+                       get {
+                               return indexers;
+                       }
+               }
+
+               public ArrayList Operators {
+                       get {
+                               return operators;
+                       }
+               }
+
+               public ArrayList Delegates {
+                       get {
+                               return delegates;
+                       }
+               }
+               
+               public Attributes OptAttributes {
+                       get {
+                               return attributes;
+                       }
+               }
+               
+               public Namespace Namespace {
                        get {
                                return my_namespace;
                        }
@@ -299,148 +457,297 @@ namespace CIR {
                                my_namespace = value;
                        }
                }
-               
-               public int ResolveParents (Tree root)
-               {
-                       if (Bases == null){
-                               base_class_name = "System.Object";
-                               return 0;
+
+               //
+               // The Toplevel is `root_types' which is a containerfor all
+               // types defined, hence the non-obviios parent.parent.
+               //
+               // If we were not tracking Namespaces we could remove this.
+               //
+               bool IsTopLevel {
+                       get {
+                               if (parent != null){
+                                       if (parent.parent == null)
+                                               return true;
+                               }
+
+                               return false;
                        }
-                       
-                       if (type_bases.Count == 0){
-                               base_class_name = "System.Object";
-                               return 0;
+               }
+
+               // <summary>
+               //   Returns the TypeAttributes for this TypeContainer
+               // </summary>
+               public virtual TypeAttributes TypeAttr {
+                       get {
+                               TypeAttributes x = 0;
+
+                               //
+                               // FIXME: Figure out exactly how private, public and protected
+                               // map to the TypeAttribute flags.
+                               //
+                               // FIXME: Figure out what `new' in the context of a class/struct means.
+                               //
+                               // FIXME: figure out what `internal' means in the context of class/structs
+                               //
+                               if ((mod_flags & Modifiers.PUBLIC) != 0)
+                                       x |= TypeAttributes.Public;
+
+                               if ((mod_flags & Modifiers.PRIVATE) != 0)
+                                       x |= TypeAttributes.NotPublic;
+                               
+                               if ((mod_flags & Modifiers.ABSTRACT) != 0)
+                                       x |= TypeAttributes.Abstract;
+                               
+                               if ((mod_flags & Modifiers.SEALED) != 0)
+                                       x |= TypeAttributes.Sealed;
+
+                               if (!IsTopLevel){
+                                       if ((mod_flags & Modifiers.PUBLIC) != 0)
+                                               x |= TypeAttributes.NestedPublic;
+                                       else
+                                               x |= TypeAttributes.NestedPrivate;
+                               }
+
+                               //
+                               // If we have static constructors, the runtime needs to
+                               // initialize the class, otherwise we can optimize
+                               // the case.
+                               //
+                               if (!have_static_constructor)
+                                       x |= TypeAttributes.BeforeFieldInit;
+                               return x;
                        }
+               }
+
+               void EmitField (Field f)
+               {
+                       Type t = LookupType (f.Type, false);
+
+                       if (t == null)
+                               return;
                        
-                       return 0;
+                       TypeBuilder.DefineField (f.Name, t, Modifiers.FieldAttr (f.ModFlags));
                }
 
-               override public Type Define (Tree tree)
+               //
+               // Emits the class field initializers
+               //
+               void EmitStaticFieldInitializers (ConstructorBuilder cb)
                {
-                       return null;
+                       // FIXME: Implement
                }
-               
-               public delegate void VisitContainer (TypeContainer container, object cback_data);
 
-               void VisitTypesAt (TypeContainer root, VisitContainer visit, object cback)
+               //
+               // Emits the instance field initializers
+               //
+               void EmitFieldInitializers (ConstructorBuilder cb)
                {
-                       if (root == null)
-                               return;
-                       
-                       foreach (DictionaryEntry de in root.Types){
-                               TypeContainer type = (TypeContainer) de.Value;
+                       // FIXME: Implement
+               }
 
-                               visit (type, cback);
-                               VisitTypesAt (type, visit, cback);
+               //
+               // Emits a constructor
+               //
+               void EmitConstructor (Constructor c)
+               {
+                       if ((c.ModFlags & Modifiers.STATIC) != 0){
+                               if (initialized_static_fields != null)
+                                       EmitStaticFieldInitializers (c.ConstructorBuilder);
+                       } else {
+                               if (initialized_fields != null)
+                                       EmitFieldInitializers (c.ConstructorBuilder);
                        }
+
                }
 
-               // <summary>
-               //   Use this method to visit all the types in a type container.
-               //   You can use cback to pass arbitrary data to your callback.
-               // </summary>
-               public void VisitTypes (VisitContainer visit, object cback)
+               //
+               // This function is used to emit instance and static constructors
+               // when the user did not provide one.
+               // 
+               void EmitDefaultConstructor (bool is_static)
                {
-                       foreach (DictionaryEntry de in types){
-                               TypeContainer type = (TypeContainer) de.Value;
+                       ConstructorBuilder cb;
+                       MethodAttributes ca = (MethodAttributes.RTSpecialName |
+                                              MethodAttributes.SpecialName);
 
-                               VisitTypesAt (type, visit, cback);
-                       }
+                       if (is_static)
+                               ca |= MethodAttributes.Static;
                        
-               }
+                       //
+                       // Default constructors provided by the compiler should be `protected'
+                       // if the class is abstract, otherwise it is public
+                       //
+                       if ((mod_flags & Modifiers.ABSTRACT) != 0)
+                               ca |= MethodAttributes.Family;
+                       else
+                               ca |= MethodAttributes.Public;
+                       
+                       cb = TypeBuilder.DefineDefaultConstructor (ca);
 
-               internal class VisitExpressions_Lambda {
-                       VisitExpressionRoot vb;
-                       object user_data;
+                       if (is_static)
+                               EmitStaticFieldInitializers (cb);
+                       else
+                               EmitFieldInitializers (cb);
+               }
 
-                       void walk_arguments (ArrayList args)
-                       {
-                               if (args == null)
-                                       return;
-                               
-                               int top = args.Count;
+               //
+               // Populates our TypeBuilder with fields and methods
+               //
+               public void Populate ()
+               {
+                       if (Constants != null){
+                               foreach (Constant c in Constants)
+                                       c.EmitConstant (RootContext, this);
+                       }
 
-                               for (int i = 0; i < top; i++){
-                                       Argument arg = (Argument) args [i];
+                       if (Fields != null){
+                               foreach (Field f in Fields)
+                                       EmitField (f);
+                       }
 
-                                       vb (arg.Expr, user_data);
-                               }
+                       if (Constructors != null){
+                               foreach (Constructor c in Constructors)
+                                       c.Define (this);
                        }
 
-                       void walk_block (Block b)
-                       {
+                       if (Methods != null){
+                               foreach (Method m in Methods)
+                                       m.Define (this);
                        }
-                       
-                       void walk_constructor (Constructor c)
-                       {
-                               ConstructorInitializer init = c.Initializer;
-                               
-                               if (init != null && init.Arguments != null)
-                                       walk_arguments (init.Arguments);
 
-                               walk_block (c.Block);
+                       if (Properties != null) {
+                               foreach (Property p in Properties)
+                                       p.Define (this);
                        }
 
-                       void walk_properties (Property p)
-                       {
+                       if (Enums != null) {
+                               foreach (Enum e in Enums)
+                                       e.Define (this);
                        }
 
-                       void walk_method (Method m)
-                       {
+                       if (Events != null) {
+                               foreach (Event e in Events)
+                                       e.Define (this);
                        }
-                               
-                       void type_walker_1 (TypeContainer type, object cback)
-                       {
-                               if (type.Fields != null){
-                                       foreach (DictionaryEntry de in type.Fields){
-                                               Field f = (Field) de.Value;
-                                               
-                                               if (f.Initializer != null){
-                                                       if (f.Initializer is Expression)
-                                                               vb ((Expression) f.Initializer, user_data);
-                                               }
-                                       }
-                               }
 
-                               if (type.Constructors != null){
-                                       foreach (DictionaryEntry de in type.Constructors)
-                                               walk_constructor ((Constructor) de.Value);
-                               }
+                       if (Indexers != null) {
+                               foreach (Indexer i in Indexers)
+                                       i.Define (this);
+                       }
 
-                               if (type.Properties != null){
-                                       foreach (DictionaryEntry de in type.Properties)
-                                               walk_properties ((Property) de.Value);
-                               }
+                       if (Operators != null) {
+                               foreach (Operator o in Operators)
+                                       o.Define (this);
+                       }
 
-                               if (type.MethodGroups != null){
-                                       foreach (DictionaryEntry de in type.MethodGroups){
-                                               Hashtable methods = ((MethodGroup) de.Value).Methods;
-                                               foreach (Method m in methods)
-                                                       walk_method (m);
-                                       }
-                               }
+                       if (Delegates != null) {
+                               foreach (Delegate d in Delegates)
+                                       d.Define (this);
                        }
+                       
+                       
+               }
+
+               //
+               // Emits the code, this step is performed after all
+               // the types, enumerations, constructors
+               //
+               public void Emit ()
+               {
+                       if (default_constructor == null)
+                               EmitDefaultConstructor (false);
+
+                       if (initialized_static_fields != null && default_static_constructor == null)
+                               EmitDefaultConstructor (true);
 
+                       if (Constructors != null)
+                               foreach (Constructor c in Constructors)
+                                       c.Emit ();
                        
-                       internal VisitExpressions_Lambda (TypeContainer tc,
-                                                         VisitExpressionRoot vb,
-                                                         object user_data)
-                       {
-                               this.vb = vb;
-                               this.user_data = user_data;
+                       if (Methods != null)
+                               foreach (Method m in Methods)
+                                       m.Emit (this);
+               }
+               
+               public delegate void ExamineType (TypeContainer container, object cback_data);
+
+               void WalkTypesAt (TypeContainer root, ExamineType visit, object cback_data)
+               {
+                       if (root == null)
+                               return;
 
-                               tc.VisitTypes (new VisitContainer (type_walker_1), null);
+                       foreach (TypeContainer type in root.Types){
+                               visit (type, cback_data);
+                               WalkTypesAt (type, visit, cback_data);
                        }
                }
-               
-               public delegate void VisitExpressionRoot (Expression e, object cback);
+
+               public void WalkTypes (ExamineType visit, object cback)
+               {
+                       WalkTypesAt (this, visit, cback);
+               }
+
+               public Type LookupType (string name, bool silent)
+               {
+                       return RootContext.LookupType (this, name, silent);
+               }
+
                // <summary>
-               //   Use this method to visit all the code blocks in a TypeContainer
+               // This method returns the members of this type just like Type.FindMembers would
+               // Only, we need to use this for types which are _being_ defined because MS' brain
+               // dead implementation can't take care of that ;-)
                // </summary>
-               public void VisitExpressionRoots (VisitExpressionRoot vb, object cback)
+               public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf, MemberFilter filter, object criteria)
                {
-                       VisitExpressions_Lambda l = new VisitExpressions_Lambda (this, vb, cback);
+                       // FIXME : Need to actually take care of all the various
+                       // arguments being passed in but for now, we only bother with
+                       // the MemberTypes and criteria arguments.
+
+                       switch (mt) {
+
+                       case MemberTypes.All:
+
+                               break;
+
+                       case MemberTypes.Constructor:
+
+                               break;
+                               
+                       case MemberTypes.Custom:
+
+                               break;
+
+                       case MemberTypes.Event:
+
+                               break;
+
+                       case MemberTypes.Field:
+
+                               break;
+
+                       case MemberTypes.Method:
+
+                               break;
+                               
+                       case MemberTypes.NestedType:
+
+                               break;
+                               
+                       case MemberTypes.Property:
+
+                               break;
+                               
+                       case MemberTypes.TypeInfo:
+
+                               break;
+
+                       }
+
+                       return null;
+                       
                }
+               
        }
 
        public class Class : TypeContainer {
@@ -456,8 +763,8 @@ namespace CIR {
                        Modifiers.ABSTRACT |
                        Modifiers.SEALED;
 
-               public Class (TypeContainer parent, string name, int mod)
-                       : base (parent, name)
+               public Class (RootContext rc, TypeContainer parent, string name, int mod, Attributes attrs)
+                       : base (rc, parent, name)
                {
                        int accmods;
 
@@ -467,6 +774,17 @@ namespace CIR {
                                accmods = Modifiers.PRIVATE;
                        
                        this.mod_flags = Modifiers.Check (AllowedModifiers, mod, accmods);
+                       this.attributes = attrs;
+               }
+
+               //
+               // FIXME: How do we deal with the user specifying a different
+               // layout?
+               //
+               public override TypeAttributes TypeAttr {
+                       get {
+                               return base.TypeAttr | TypeAttributes.AutoLayout;
+                       }
                }
        }
 
@@ -481,8 +799,8 @@ namespace CIR {
                        Modifiers.INTERNAL |
                        Modifiers.PRIVATE;
 
-               public Struct (TypeContainer parent, string name, int mod)
-                       : base (parent, name)
+               public Struct (RootContext rc, TypeContainer parent, string name, int mod, Attributes attrs)
+                       : base (rc, parent, name)
                {
                        int accmods;
                        
@@ -492,23 +810,45 @@ namespace CIR {
                                accmods = Modifiers.PRIVATE;
                        
                        this.mod_flags = Modifiers.Check (AllowedModifiers, mod, accmods);
+
+                       this.mod_flags |= Modifiers.SEALED;
+                       this.attributes = attrs;
+                       
+               }
+
+               //
+               // FIXME: Allow the user to specify a different set of attributes
+               // in some cases (Sealed for example is mandatory for a class,
+               // but what SequentialLayout can be changed
+               //
+               public override TypeAttributes TypeAttr {
+                       get {
+                               return base.TypeAttr |
+                                       TypeAttributes.SequentialLayout |
+                                       TypeAttributes.Sealed |
+                                       TypeAttributes.BeforeFieldInit;
+                       }
                }
        }
 
        public class Method {
-               Parameters parameters;
-               TypeRef    return_typeref;
-               string     name;
-               int        modifiers;
-               Block      block;
-
+               public readonly Parameters Parameters;
+               public readonly string     ReturnType;
+               public readonly string     Name;
+               public readonly int        ModFlags;
+               public MethodBuilder MethodBuilder;
+               public readonly Attributes OptAttributes;
+               
+               Block block;
+               
                // return_type can be "null" for VOID values.
-               public Method (TypeRef return_typeref, int mod, string name, Parameters parameters)
+               public Method (string return_type, int mod, string name, Parameters parameters, Attributes attrs)
                {
-                       this.return_typeref = return_typeref;
-                       this.name = name;
-                       this.parameters = parameters;
-                       this.modifiers = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE);
+                       Name = name;
+                       ReturnType = return_type;
+                       Parameters = parameters;
+                       ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE);
+                       OptAttributes = attrs;
                }
 
                // <summary>
@@ -537,42 +877,110 @@ namespace CIR {
                        }
                }
 
-               public string Name {
-                       get {
-                               return name;
-                       }
+               //
+               // Returns the `System.Type' for the ReturnType of this
+               // function.  Provides a nice cache.  (used between semantic analysis
+               // and actual code generation
+               //
+               Type type_return_type;
+               public Type GetReturnType (TypeContainer parent)
+               {
+                       if (type_return_type == null)
+                               type_return_type = parent.LookupType (ReturnType, false);
+                       
+                       return type_return_type;
                }
 
-               public int ModFlags {
-                       get {
-                               return modifiers;
-                       }
+               //
+               //  Returns the System.Type array for the parameters of this method
+               //
+               Type [] parameter_types;
+               public Type [] ParameterTypes (TypeContainer parent)
+               {
+                       if (Parameters == null)
+                               return null;
+                       
+                       if (parameter_types == null)
+                               parameter_types = Parameters.GetParameterInfo (parent);
+
+                       return parameter_types;
                }
 
-               public Parameters Parameters {
-                       get {
-                               return parameters;
-                       }
+               public CallingConventions GetCallingConvention (bool is_class)
+               {
+                       CallingConventions cc = 0;
+                       
+                       cc = Parameters.GetCallingConvention ();
+
+                       if (is_class)
+                               if ((ModFlags & Modifiers.STATIC) == 0)
+                                       cc |= CallingConventions.HasThis;
+
+                       return cc;
                }
 
-               public Type ReturnType {
-                       get {
-                               return return_typeref.Type;
+               //
+               // Creates the type
+               // 
+               public void Define (TypeContainer parent)
+               {
+                       Type ret_type = GetReturnType (parent);
+                       Type [] parameters = ParameterTypes (parent);
+
+                       //
+                       // Create the method
+                       //
+                       MethodBuilder = parent.TypeBuilder.DefineMethod (
+                               Name, Modifiers.MethodAttr (ModFlags),
+                               GetCallingConvention (parent is Class),
+                               ret_type, parameters);
+
+                       //
+                       // This is used to track the Entry Point,
+                       //
+                       // FIXME: Allow pluggable entry point, check arguments, etc.
+                       //
+                       if (Name == "Main"){
+                               if ((ModFlags & Modifiers.STATIC) != 0){
+                                       parent.RootContext.EntryPoint = MethodBuilder;
+                               }
                        }
-               }
+                       
+                       //
+                       // Define each type attribute (in/out/ref) and
+                       // the argument names.
+                       //
+                       Parameter [] p = Parameters.FixedParameters;
+                       if (p != null){
+                               int i;
+                               
+                               for (i = 0; i < p.Length; i++)
+                                       MethodBuilder.DefineParameter (
+                                               i + 1, p [i].Attributes, p [i].Name);
 
-               public string ArgumentSignature {
-                       get {
-                               return ""; // TYPEFIX: Type.MakeParameterSignature (name, parameters);
+                               if (i != parameters.Length)
+                                       Console.WriteLine ("Implement the type definition for params");
                        }
                }
+
+               //
+               // Emits the code
+               // 
+               public void Emit (TypeContainer parent)
+               {
+                       ILGenerator ig = MethodBuilder.GetILGenerator ();
+                       EmitContext ec = new EmitContext (parent, ig);
+                       
+                       ec.EmitTopBlock (block);
+               }
        }
 
        public class Field {
-               Type type;
-               Object expr_or_array_init;
-               string name;
-               int modifiers;
+               public readonly string Type;
+               public readonly Object Initializer;
+               public readonly string Name;
+               public readonly int    ModFlags;
+               public readonly Attributes OptAttributes;
                
                // <summary>
                //   Modifiers allowed in a class declaration
@@ -586,36 +994,13 @@ namespace CIR {
                        Modifiers.STATIC |
                        Modifiers.READONLY;
 
-               public Field (TypeRef typeref, int mod, string name, Object expr_or_array_init)
+               public Field (string type, int mod, string name, Object expr_or_array_init, Attributes attrs)
                {
-                       this.type = type;
-                       this.modifiers = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE);
-                       this.name = name;
-                       this.expr_or_array_init = expr_or_array_init;
-               }
-
-               public Type Type {
-                       get {
-                               return type;
-                       }
-               }
-
-               public object Initializer {
-                       get {
-                               return expr_or_array_init;
-                       }
-               }
-
-               public string Name {
-                       get {
-                               return name;
-                       }
-               }
-
-               public int ModFlags {
-                       get {
-                               return modifiers;
-                       }
+                       Type = type;
+                       ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE);
+                       Name = name;
+                       Initializer = expr_or_array_init;
+                       OptAttributes = attrs;
                }
        }
 
@@ -647,9 +1032,10 @@ namespace CIR {
        }
        
        public class Constructor {
-               ConstructorInitializer init;
-               string name;
-               Parameters args;
+               public ConstructorBuilder ConstructorBuilder;
+               public readonly ConstructorInitializer Initializer;
+               public readonly Parameters Parameters;
+               public readonly string Name;
                Block block;
                int mod_flags;
 
@@ -667,32 +1053,33 @@ namespace CIR {
                // The spec claims that static is not permitted, but
                // my very own code has static constructors.
                //
-               
                public Constructor (string name, Parameters args, ConstructorInitializer init)
                {
-                       this.name = name;
-                       this.args = args;
-                       this.init = init;
+                       Name = name;
+                       Parameters = args;
+                       Initializer = init;
                }
 
-               public string Name {
-                       get {
-                               return name;
-                       }
+               //
+               // Returns true if this is a default constructor
+               //
+               public bool IsDefault ()
+               {
+                       return  (Parameters == null) &&
+                               (Initializer is ConstructorBaseInitializer) &&
+                               (Initializer.Arguments == null);
                }
 
-               public ConstructorInitializer Initializer {
+               public int ModFlags {
                        get {
-                               return init;
+                               return mod_flags;
                        }
-               }
 
-               public Parameters Parameters {
-                       get {
-                               return args;
+                       set {
+                               mod_flags = value;
                        }
                }
-
+               
                public Block Block {
                        get {
                                return block;
@@ -703,23 +1090,72 @@ namespace CIR {
                        }
                }
 
-               public int ModFlags {
-                       get {
-                               return mod_flags;
-                       }
+               public CallingConventions GetCallingConvention (bool parent_is_class)
+               {
+                       CallingConventions cc = 0;
+                       
+                       if (Parameters.ArrayParameter != null)
+                               cc |= CallingConventions.VarArgs;
+                       else
+                               cc |= CallingConventions.Standard;
 
-                       set {
-                               mod_flags = Modifiers.Check (AllowedModifiers, value, 0);
-                       }
+                       if (parent_is_class)
+                               if ((ModFlags & Modifiers.STATIC) != 0)
+                                       cc |= CallingConventions.HasThis;
+
+                               // FIXME: How is `ExplicitThis' used in C#?
+                               
+                       return cc;
+               }
+
+               //
+               // Cached representation
+               ///
+               Type [] parameter_types;
+               public Type [] ParameterTypes (TypeContainer tc)
+               {
+                       if (Parameters == null)
+                               return null;
+                       
+                       if (parameter_types == null)
+                               parameter_types = Parameters.GetParameterInfo (tc);
+                       
+                       return parameter_types;
+               }
+
+               //
+               // Creates the ConstructorBuilder
+               //
+               public void Define (TypeContainer parent)
+               {
+                       MethodAttributes ca = (MethodAttributes.RTSpecialName |
+                                              MethodAttributes.SpecialName);
+                       
+                       if ((ModFlags & Modifiers.STATIC) != 0)
+                               ca |= MethodAttributes.Static;
+                       
+                       ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
+                               ca, GetCallingConvention (parent is Class),
+                               ParameterTypes (parent));
+               }
+
+               //
+               // Emits the code
+               //
+               public void Emit ()
+               {
                }
        }
 
        public class Property {
-               TypeRef typeref;
-               string name;
-               int mod_flags;
-               Block get_block, set_block;
-
+               
+               public readonly string Type;
+               public readonly string Name;
+               public readonly int    ModFlags;
+               public Block           Get, Set;
+               public PropertyBuilder PropertyBuilder;
+               public Attributes OptAttributes;
+               
                const int AllowedModifiers =
                        Modifiers.NEW |
                        Modifiers.PUBLIC |
@@ -732,44 +1168,272 @@ namespace CIR {
                        Modifiers.ABSTRACT |
                        Modifiers.VIRTUAL;
                
-               public Property (TypeRef typeref, string name, int mod_flags, Block get_block, Block set_block)
+               public Property (string type, string name, int mod_flags, Block get_block, Block set_block, Attributes attrs)
                {
-                       this.typeref = typeref;
-                       this.name = name;
-                       this.mod_flags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE);
-                       this.get_block = get_block;
-                       this.set_block = set_block;
+                       Type = type;
+                       Name = name;
+                       ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE);
+                       Get = get_block;
+                       Set = set_block;
+                       OptAttributes = attrs;
                }
 
-               public Type Type {
-                       get {
-                               return typeref.Type;
+               public void Define (TypeContainer parent)
+               {
+
+                       MethodAttributes method_attr = Modifiers.MethodAttr(ModFlags);
+                                       
+                       // FIXME - how to handle PropertyAttributes.HasDefault
+
+                       PropertyAttributes prop_attr = PropertyAttributes.RTSpecialName |
+                                                      PropertyAttributes.SpecialName;
+               
+               
+                       Type tp = parent.LookupType (Type, false);
+                       Type [] prop_type = new Type [1];
+                       prop_type [0] = tp;
+
+                       MethodBuilder mb;
+                       
+                       PropertyBuilder = parent.TypeBuilder.DefineProperty(Name, prop_attr, tp, null);
+                                       
+                       if (Get != null)
+                       {
+                               mb = parent.TypeBuilder.DefineMethod("get_" + Name, method_attr, tp, null);
+                               PropertyBuilder.SetGetMethod (mb);
                        }
+                       
+                       if (Set != null)
+                       {
+                               mb = parent.TypeBuilder.DefineMethod("set_" + Name, method_attr, null, prop_type);
+                               mb.DefineParameter(1, ParameterAttributes.None, "value"); 
+                               PropertyBuilder.SetSetMethod (mb);
+                       }
+
                }
 
-               public string Name {
-                       get {
-                               return name;
-                       }
+       }
+
+       public class Event {
+               
+               const int AllowedModifiers =
+                       Modifiers.NEW |
+                       Modifiers.PUBLIC |
+                       Modifiers.PROTECTED |
+                       Modifiers.INTERNAL |
+                       Modifiers.PRIVATE |
+                       Modifiers.STATIC |
+                       Modifiers.VIRTUAL |
+                       Modifiers.SEALED |
+                       Modifiers.OVERRIDE |
+                       Modifiers.ABSTRACT;
+
+               public readonly string    Type;
+               public readonly string    Name;
+               public readonly Object    Initializer;
+               public readonly int       ModFlags;
+               public readonly Block     Add;
+               public readonly Block     Remove;
+               public EventBuilder       EventBuilder;
+               public Attributes         OptAttributes;
+               
+               public Event (string type, string name, Object init, int flags, Block add_block, Block rem_block,
+                             Attributes attrs)
+               {
+                       Type = type;
+                       Name = name;
+                       Initializer = init;
+                       ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE);  
+                       Add = add_block;
+                       Remove = rem_block;
+                       OptAttributes = attrs;
                }
 
-               public int ModFlags {
-                       get {
-                               return mod_flags;
+               public void Define (TypeContainer parent)
+               {
+                       MethodAttributes m_attr = Modifiers.MethodAttr (ModFlags);
+
+                       EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
+                       
+                       MethodBuilder mb;
+
+                       Type t = parent.LookupType (Type, false);
+                       Type [] p_type = new Type [1];
+                       p_type [0] = t;
+                       
+                       EventBuilder = parent.TypeBuilder.DefineEvent (Name, e_attr, t);
+                       
+                       if (Add != null) {
+                               mb = parent.TypeBuilder.DefineMethod ("add_" + Name, m_attr, null, p_type);
+                               mb.DefineParameter (1, ParameterAttributes.None, "value");
+                               EventBuilder.SetAddOnMethod (mb);
                        }
-               }
 
-               public Block Get {
-                       get {
-                               return get_block;
+                       if (Remove != null) {
+                               mb = parent.TypeBuilder.DefineMethod ("remove_" + Name, m_attr, null, p_type);
+                               mb.DefineParameter (1, ParameterAttributes.None, "value");
+                               EventBuilder.SetRemoveOnMethod (mb);
                        }
                }
+               
+       }
 
-               public Block Set {
-                       get {
-                               return set_block;
+       public class Indexer {
+
+               const int AllowedModifiers =
+                       Modifiers.NEW |
+                       Modifiers.PUBLIC |
+                       Modifiers.PROTECTED |
+                       Modifiers.INTERNAL |
+                       Modifiers.PRIVATE |
+                       Modifiers.VIRTUAL |
+                       Modifiers.SEALED |
+                       Modifiers.OVERRIDE |
+                       Modifiers.ABSTRACT;
+
+               public readonly string     Type;
+               public readonly string     InterfaceType;
+               public readonly Parameters FormalParameters;
+               public readonly int        ModFlags;
+               public readonly Block      Get;
+               public readonly Block      Set;
+               public Attributes          OptAttributes;
+               public MethodBuilder GetMethodBuilder;
+               public MethodBuilder SetMethodBuilder;
+               
+
+               public Indexer (string type, string int_type, int flags, Parameters parms,
+                               Block get_block, Block set_block, Attributes attrs)
+               {
+
+                       Type = type;
+                       InterfaceType = int_type;
+                       ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE);
+                       FormalParameters = parms;
+                       Get = get_block;
+                       Set = set_block;
+                       OptAttributes = attrs;
+               }
+
+               public void Define (TypeContainer parent)
+               {
+                       MethodAttributes attr = Modifiers.MethodAttr (ModFlags);
+                       
+                       Type ret_type = parent.LookupType (Type, false);
+                       Type [] param_types = FormalParameters.GetParameterInfo (parent);
+
+                       GetMethodBuilder = parent.TypeBuilder.DefineMethod ("get_Item", attr, ret_type, param_types);
+                       SetMethodBuilder = parent.TypeBuilder.DefineMethod ("set_Item", attr, ret_type, param_types);
+                       
+                       Parameter [] p = FormalParameters.FixedParameters;
+
+                       if (p != null) {
+                               int i;
+                               
+                               for (i = 0; i < p.Length; ++i) {
+                                       GetMethodBuilder.DefineParameter (i + 1, p [i].Attributes, p [i].Name);
+                                       SetMethodBuilder.DefineParameter (i + 1, p [i].Attributes, p [i].Name);
+                               }
+                               
+                               if (i != param_types.Length)
+                                       Console.WriteLine ("Implement type definition for params");
                        }
+
                }
+               
+       }
+
+       public class Operator {
+
+               const int AllowedModifiers =
+                       Modifiers.PUBLIC |
+                       Modifiers.STATIC;
+
+               public enum OpType {
+
+                       // Unary operators
+                       Bang,
+                       Tilde,
+                       Increment,
+                       Decrement,
+                       True,
+                       False,
+
+                       // Unary and Binary operators
+                       Plus,
+                       Minus,
+                       
+                       // Binary operators
+                       Star,
+                       Div,
+                       Percent,
+                       BitAnd,
+                       BitOr,
+                       Carret,
+                       ShiftLeft,
+                       ShiftRight,
+                       Eq,
+                       NotEq,
+                       GreaterThan,
+                       LesserThan,
+                       GreaterOrEq,
+                       LesserOrEq,
+
+                       // Implicit and Explicit
+                       Implicit,
+                       Explicit
+               };
+
+               public readonly OpType OperatorType;
+               public readonly string ReturnType;
+               public readonly string FirstArgType;
+               public readonly string FirstArgName;
+               public readonly string SecondArgType;
+               public readonly string SecondArgName;
+               public readonly int    ModFlags;
+               public readonly Block  Block;
+               public Attributes      OptAttributes;
+               public MethodBuilder   OperatorMethodBuilder;
+
+               public Operator (OpType type, string ret_type, int flags, string arg1type, string arg1name,
+                                string arg2type, string arg2name, Block block, Attributes attrs)
+               {
+                       OperatorType = type;
+                       ReturnType = ret_type;
+                       ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC);
+                       FirstArgType = arg1type;
+                       FirstArgName = arg1name;
+                       SecondArgType = arg2type;
+                       SecondArgName = arg2name;
+                       Block = block;
+                       OptAttributes = attrs;
+               }
+
+               public void Define (TypeContainer parent)
+               {
+                       MethodAttributes attr = Modifiers.MethodAttr (ModFlags);
+
+                       string name = "Operator" + OperatorType;
+
+                       Type ret_type = parent.LookupType (ReturnType, false);
+
+                       Type [] param_types = new Type [2];
+
+                       param_types [0] = parent.LookupType (FirstArgType, false);
+                       if (SecondArgType != null)
+                               param_types [1] = parent.LookupType (SecondArgType, false);
+                       
+                       OperatorMethodBuilder = parent.TypeBuilder.DefineMethod (name, attr, ret_type, param_types);
+
+                       OperatorMethodBuilder.DefineParameter (1, ParameterAttributes.None, FirstArgName);
+
+                       if (SecondArgType != null)
+                               OperatorMethodBuilder.DefineParameter (2, ParameterAttributes.None, SecondArgName);
+
+               }
+               
+
        }
+
 }