// // class.cs: Class and Struct handlers // // Author: Miguel de Icaza (miguel@gnu.org) // // Licensed under the terms of the GNU GPL // // (C) 2001 Ximian, Inc (http://www.ximian.com) // // using System.Collections; using System.Reflection; using System.Reflection.Emit; using System; namespace CIR { public class TypeContainer : DeclSpace { protected int mod_flags; // 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; // Maps MethodBuilders to Methods static Hashtable method_builders_to_methods; // // 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. // Namespace my_namespace; // // This one is computed after we can distinguish interfaces // from classes from the arraylist `type_bases' // string base_class_name; TypeContainer parent; ArrayList type_bases; // // 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) { string n; types = new ArrayList (); this.parent = parent; RootContext = rc; object a = rc.Report; if (parent == null) n = ""; else n = parent.Name; base_class_name = null; //Console.WriteLine ("New class " + name + " inside " + n); } public AdditionResult AddConstant (Constant constant) { AdditionResult res; string name = constant.Name; if ((res = IsValid (name)) != AdditionResult.Success) return res; if (constants == null) constants = new ArrayList (); constants.Add (constant); DefineName (name, constant); return AdditionResult.Success; } public AdditionResult AddEnum (CIR.Enum e) { AdditionResult res; string name = e.Name; if ((res = IsValid (name)) != AdditionResult.Success) return res; if (enums == null) enums = new ArrayList (); enums.Add (e); DefineName (name, e); return AdditionResult.Success; } public AdditionResult AddClass (Class c) { AdditionResult res; string name = c.Name; if ((res = IsValid (name)) != AdditionResult.Success) return res; DefineName (name, c); types.Add (c); return AdditionResult.Success; } public AdditionResult AddStruct (Struct s) { AdditionResult res; string name = s.Name; if ((res = IsValid (name)) != AdditionResult.Success) return res; DefineName (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; } public AdditionResult AddMethod (Method method) { string name = method.Name; Object value = defined_names [name]; if (value != null && (!(value is Method))) return AdditionResult.NameExists; if (methods == null) methods = new ArrayList (); methods.Add (method); if (value != null) DefineName (name, method); return AdditionResult.Success; } public AdditionResult AddConstructor (Constructor c) { if (c.Name != Basename) return AdditionResult.NotAConstructor; if (constructors == null) constructors = new ArrayList (); 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; } public AdditionResult AddInterface (Interface iface) { AdditionResult res; string name = iface.Name; if ((res = IsValid (name)) != AdditionResult.Success) return res; if (interfaces == null) interfaces = new ArrayList (); interfaces.Add (iface); DefineName (name, iface); return AdditionResult.Success; } public AdditionResult AddField (Field field) { AdditionResult res; string name = field.Name; if ((res = IsValid (name)) != AdditionResult.Success) return res; if (fields == null) 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; } public AdditionResult AddProperty (Property prop) { AdditionResult res; string name = prop.Name; if ((res = IsValid (name)) != AdditionResult.Success) return res; if (properties == null) properties = new ArrayList (); properties.Add (prop); DefineName (name, prop); return AdditionResult.Success; } 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 { get { return parent; } } public ArrayList Types { get { return types; } } public ArrayList Methods { get { return methods; } } public ArrayList Constants { get { return constants; } } public ArrayList Interfaces { get { return interfaces; } } public int ModFlags { get { return mod_flags; } } public string Base { get { return base_class_name; } } public ArrayList Bases { get { return type_bases; } set { type_bases = value; } } public ArrayList Fields { get { return fields; } } public ArrayList Constructors { get { return constructors; } } public ArrayList Properties { get { return properties; } } public ArrayList Events { get { return events; } } public ArrayList Enums { get { return enums; } } 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; } set { my_namespace = value; } } // // root_types contains all the types. All TopLevel types // hence have a parent that points to `root_types', that is // why there is a non-obvious test down here. // public bool IsTopLevel { get { if (parent != null){ if (parent.Parent == null) return true; } return false; } } public bool HaveStaticConstructor { get { return have_static_constructor; } } public virtual TypeAttributes TypeAttr { get { return Modifiers.TypeAttr (mod_flags, this); } } // // Emits the instance field initializers // public bool EmitFieldInitializers (EmitContext ec, bool is_static) { ArrayList fields; ILGenerator ig = ec.ig; if (is_static) fields = initialized_static_fields; else fields = initialized_fields; if (fields == null) return true; foreach (Field f in fields){ Object init = f.Initializer; if (init is Expression){ Expression e = (Expression) init; e = e.Resolve (this); if (e == null) return false; if (!is_static) ig.Emit (OpCodes.Ldarg_0); e.Emit (ec); if (is_static) ig.Emit (OpCodes.Stsfld, f.FieldBuilder); else ig.Emit (OpCodes.Stfld, f.FieldBuilder); } } return true; } // // Defines the default constructors // void DefineDefaultConstructor (bool is_static) { Constructor c; int mods = 0; c = new Constructor (Name, new Parameters (null, null), new ConstructorBaseInitializer (null, new Location ("", 0, 0))); AddConstructor (c); c.Block = new Block (null); if (is_static) mods = Modifiers.STATIC; c.ModFlags = mods; } // // Populates our TypeBuilder with fields and methods // public void Populate () { if (Constants != null){ foreach (Constant c in Constants) c.EmitConstant (RootContext, this); } if (Fields != null){ foreach (Field f in Fields) f.Define (this); } if (default_constructor == null) DefineDefaultConstructor (false); if (initialized_static_fields != null && default_static_constructor == null) DefineDefaultConstructor (true); if (Constructors != null){ foreach (Constructor c in Constructors){ c.Define (this); if (method_builders_to_methods == null) method_builders_to_methods = new Hashtable (); method_builders_to_methods.Add (c.ConstructorBuilder, c); } } if (Methods != null){ foreach (Method m in Methods){ m.Define (this); if (method_builders_to_methods == null) method_builders_to_methods = new Hashtable (); method_builders_to_methods.Add (m.MethodBuilder, m); } } if (Properties != null) { foreach (Property p in Properties) p.Define (this); } if (Enums != null) { foreach (Enum e in Enums) e.Define (this); } if (Events != null) { foreach (Event e in Events) e.Define (this); } if (Indexers != null) { foreach (Indexer i in Indexers) i.Define (this); } if (Operators != null) { foreach (Operator o in Operators) { o.Define (this); if (method_builders_to_methods == null) method_builders_to_methods = new Hashtable (); method_builders_to_methods.Add (o.OperatorMethodBuilder, o.OperatorMethod); } } if (Delegates != null) { foreach (Delegate d in Delegates) d.Define (this); } } // // the `mb' must be a MethodBuilder or a // ConstructorBuilder, we return the method that // defines it. // static public MethodCore LookupMethodByBuilder (MethodBase mb) { return (MethodCore) method_builders_to_methods [mb]; } // // Emits the code, this step is performed after all // the types, enumerations, constructors // public void Emit () { if (Constructors != null) foreach (Constructor c in Constructors) c.Emit (this); if (Methods != null) foreach (Method m in Methods) m.Emit (this); if (Operators != null) foreach (Operator o in Operators) o.Emit (this); } public delegate void ExamineType (TypeContainer container, object cback_data); void WalkTypesAt (TypeContainer root, ExamineType visit, object cback_data) { if (root == null) return; foreach (TypeContainer type in root.Types){ visit (type, cback_data); WalkTypesAt (type, visit, cback_data); } } public void WalkTypes (ExamineType visit, object cback) { WalkTypesAt (this, visit, cback); } public Type LookupType (string name, bool silent) { return RootContext.LookupType (this, name, silent); } bool AlwaysAccept (MemberInfo m, object filterCriteria) { return true; } // // 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' // implementation can't take care of that. // public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf, MemberFilter filter, object criteria) { ArrayList members = new ArrayList (); if (filter == null) filter = new MemberFilter (AlwaysAccept); if ((mt & MemberTypes.Field) != 0 && Fields != null) { foreach (Field f in Fields) { if (filter (f.FieldBuilder, criteria) == true) members.Add (f.FieldBuilder); } } if ((mt & MemberTypes.Method) != 0) { if (Methods != null){ foreach (Method m in Methods) { if (filter (m.MethodBuilder, criteria) == true) members.Add (m.MethodBuilder); } } if (Operators != null){ foreach (Operator o in Operators) { if (filter (o.OperatorMethodBuilder, criteria) == true) members.Add (o.OperatorMethodBuilder); } } } // FIXME : This ain't right because EventBuilder is not a // MemberInfo. What do we do ? if ((mt & MemberTypes.Event) != 0 && Events != null) { //foreach (Event e in Events) { // if (filter (e.EventBuilder, criteria) == true) // mi [i++] = e.EventBuilder; //} } if ((mt & MemberTypes.Property) != 0 && Properties != null) { foreach (Property p in Properties) { if (filter (p.PropertyBuilder, criteria) == true) members.Add (p.PropertyBuilder); } } if ((mt & MemberTypes.NestedType) != 0 && Types != null) { foreach (TypeContainer t in Types) { if (filter (t.TypeBuilder, criteria) == true) members.Add (t.TypeBuilder); } } if ((mt & MemberTypes.Constructor) != 0){ if (Constructors != null){ foreach (Constructor c in Constructors) if (filter (c.ConstructorBuilder, criteria) == true) members.Add (c.ConstructorBuilder); } } int count = members.Count; if (count > 0){ MemberInfo [] mi = new MemberInfo [count]; members.CopyTo (mi); return mi; } return null; } } public class Class : TypeContainer { // // Modifiers allowed in a class declaration // public const int AllowedModifiers = Modifiers.NEW | Modifiers.PUBLIC | Modifiers.PROTECTED | Modifiers.INTERNAL | Modifiers.PRIVATE | Modifiers.ABSTRACT | Modifiers.SEALED; public Class (RootContext rc, TypeContainer parent, string name, int mod, Attributes attrs) : base (rc, parent, name) { int accmods; if (parent.Parent == null) accmods = Modifiers.INTERNAL; else 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; } } } public class Struct : TypeContainer { // // Modifiers allowed in a struct declaration // public const int AllowedModifiers = Modifiers.NEW | Modifiers.PUBLIC | Modifiers.PROTECTED | Modifiers.INTERNAL | Modifiers.PRIVATE; public Struct (RootContext rc, TypeContainer parent, string name, int mod, Attributes attrs) : base (rc, parent, name) { int accmods; if (parent.Parent == null) accmods = Modifiers.INTERNAL; else 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 MethodCore { public readonly Parameters Parameters; public readonly string Name; public int ModFlags; Block block; // // Parameters, cached for semantic analysis. // InternalParameters parameter_info; public MethodCore (string name, Parameters parameters) { Name = name; Parameters = parameters; } // // 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 InternalParameters ParameterInfo { get { return parameter_info; } set { parameter_info = value; } } public Block Block { get { return block; } set { block = value; } } public CallingConventions GetCallingConvention (bool is_class) { CallingConventions cc = 0; cc = Parameters.GetCallingConvention (); if (is_class) if ((ModFlags & Modifiers.STATIC) == 0) cc |= CallingConventions.HasThis; // FIXME: How is `ExplicitThis' used in C#? return cc; } } public class Method : MethodCore { public readonly string ReturnType; public MethodBuilder MethodBuilder; public readonly Attributes OptAttributes; // // Modifiers allowed in a class declaration // const int AllowedModifiers = Modifiers.NEW | Modifiers.PUBLIC | Modifiers.PROTECTED | Modifiers.INTERNAL | Modifiers.PRIVATE | Modifiers.STATIC | Modifiers.VIRTUAL | Modifiers.SEALED | Modifiers.OVERRIDE | Modifiers.ABSTRACT | Modifiers.EXTERN; // return_type can be "null" for VOID values. public Method (string return_type, int mod, string name, Parameters parameters, Attributes attrs) : base (name, parameters) { ReturnType = return_type; ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE); OptAttributes = attrs; } // // 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; } // // 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); ParameterInfo = new InternalParameters (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); 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 abstract class ConstructorInitializer { ArrayList argument_list; ConstructorInfo parent_constructor; Location location; public ConstructorInitializer (ArrayList argument_list, Location location) { this.argument_list = argument_list; this.location = location; } public ArrayList Arguments { get { return argument_list; } } public bool Resolve (TypeContainer tc) { Expression parent_constructor_group; if (argument_list != null){ for (int i = argument_list.Count; i > 0; ){ --i; Argument a = (Argument) argument_list [i]; if (!a.Resolve (tc)) return false; } } parent_constructor_group = Expression.MemberLookup ( tc, tc.TypeBuilder.BaseType, ".ctor", false, MemberTypes.Constructor, BindingFlags.Public | BindingFlags.Instance); if (parent_constructor_group == null){ Console.WriteLine ("Could not find a constructor in our parent"); return false; } parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (tc, (MethodGroupExpr) parent_constructor_group, argument_list, location); if (parent_constructor == null) return false; return true; } public void Emit (EmitContext ec) { ec.ig.Emit (OpCodes.Ldarg_0); if (argument_list != null) Invocation.EmitArguments (ec, parent_constructor, argument_list); ec.ig.Emit (OpCodes.Call, parent_constructor); } } public class ConstructorBaseInitializer : ConstructorInitializer { public ConstructorBaseInitializer (ArrayList argument_list, Location l) : base (argument_list, l) { } } public class ConstructorThisInitializer : ConstructorInitializer { public ConstructorThisInitializer (ArrayList argument_list, Location l) : base (argument_list, l) { } } public class Constructor : MethodCore { public ConstructorBuilder ConstructorBuilder; public ConstructorInitializer Initializer; // // Modifiers allowed for a constructor. // const int AllowedModifiers = Modifiers.PUBLIC | Modifiers.PROTECTED | Modifiers.INTERNAL | Modifiers.STATIC | Modifiers.PRIVATE; // // The spec claims that static is not permitted, but // my very own code has static constructors. // public Constructor (string name, Parameters args, ConstructorInitializer init) : base (name, args) { Initializer = init; } // // Returns true if this is a default constructor // public bool IsDefault () { return (Parameters == null ? true : Parameters.Empty) && (Initializer is ConstructorBaseInitializer) && (Initializer.Arguments == null); } // // Creates the ConstructorBuilder // public void Define (TypeContainer parent) { MethodAttributes ca = (MethodAttributes.RTSpecialName | MethodAttributes.SpecialName); Type [] parameters = ParameterTypes (parent); if ((ModFlags & Modifiers.STATIC) != 0) ca |= MethodAttributes.Static; ConstructorBuilder = parent.TypeBuilder.DefineConstructor ( ca, GetCallingConvention (parent is Class), parameters); ParameterInfo = new InternalParameters (parameters); } // // Emits the code // public void Emit (TypeContainer parent) { if (Initializer != null) if (!Initializer.Resolve (parent)) return; ILGenerator ig = ConstructorBuilder.GetILGenerator (); EmitContext ec = new EmitContext (parent, ig); if ((ModFlags & Modifiers.STATIC) == 0) Initializer.Emit (ec); if ((ModFlags & Modifiers.STATIC) != 0) parent.EmitFieldInitializers (ec, true); else parent.EmitFieldInitializers (ec, false); ec.EmitTopBlock (Block); } } public class Field { public readonly string Type; public readonly Object Initializer; public readonly string Name; public readonly int ModFlags; public readonly Attributes OptAttributes; public FieldBuilder FieldBuilder; // // Modifiers allowed in a class declaration // const int AllowedModifiers = Modifiers.NEW | Modifiers.PUBLIC | Modifiers.PROTECTED | Modifiers.INTERNAL | Modifiers.PRIVATE | Modifiers.STATIC | Modifiers.READONLY; public Field (string type, int mod, string name, Object expr_or_array_init, Attributes attrs) { Type = type; ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE); Name = name; Initializer = expr_or_array_init; OptAttributes = attrs; } public void Define (TypeContainer parent) { Type t = parent.LookupType (Type, false); if (t == null) return; FieldBuilder = parent.TypeBuilder.DefineField ( Name, t, Modifiers.FieldAttr (ModFlags)); } } public class Property { 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 | Modifiers.PROTECTED | Modifiers.INTERNAL | Modifiers.PRIVATE | Modifiers.STATIC | Modifiers.SEALED | Modifiers.OVERRIDE | Modifiers.ABSTRACT | Modifiers.VIRTUAL; public Property (string type, string name, int mod_flags, Block get_block, Block set_block, Attributes attrs) { Type = type; Name = name; ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE); Get = get_block; Set = set_block; OptAttributes = attrs; } public void Define (TypeContainer parent) { MethodAttributes method_attr = Modifiers.MethodAttr(ModFlags); // FIXME - 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 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 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); } if (Remove != null) { mb = parent.TypeBuilder.DefineMethod ("remove_" + Name, m_attr, null, p_type); mb.DefineParameter (1, ParameterAttributes.None, "value"); EventBuilder.SetRemoveOnMethod (mb); } } } 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; const int RequiredModifiers = Modifiers.PUBLIC | Modifiers.STATIC; public enum OpType { // Unary operators Negate, BitComplement, Increment, Decrement, True, False, // Unary and Binary operators Addition, Subtraction, // Binary operators Multiply, Division, Modulus, BitwiseAnd, BitwiseOr, ExclusiveOr, LeftShift, RightShift, Equality, Inequality, GreaterThan, LessThan, GreaterThanOrEqual, LessThanOrEqual, // 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 string MethodName; public Method OperatorMethod; 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; } string Prototype (TypeContainer parent) { return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," + SecondArgType + ")"; } public void Define (TypeContainer parent) { int length = 1; MethodName = "op_" + OperatorType; if (SecondArgType != null) length = 2; Parameter [] param_list = new Parameter [length]; if ((ModFlags & RequiredModifiers) != RequiredModifiers){ parent.RootContext.Report.Error ( 558, "User defined operators `" + Prototype (parent) + "' must be declared static and public"); } param_list[0] = new Parameter (FirstArgType, FirstArgName, Parameter.Modifier.NONE, null); if (SecondArgType != null) param_list[1] = new Parameter (SecondArgType, SecondArgName, Parameter.Modifier.NONE, null); OperatorMethod = new Method (ReturnType, ModFlags, MethodName, new Parameters (param_list, null), OptAttributes); OperatorMethod.Define (parent); OperatorMethodBuilder = OperatorMethod.MethodBuilder; } public void Emit (TypeContainer parent) { OperatorMethod.Block = Block; OperatorMethod.Emit (parent); } } }