//
// (C) 2001 Ximian, Inc (http://www.ximian.com)
//
-
+#define CACHE
using System.Collections;
using System;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
-namespace Mono.CSharp {
+namespace Mono.MonoBASIC {
/// <summary>
/// Interfaces
/// </summary>
- public class Interface : DeclSpace {
+ public class Interface : DeclSpace, IMemberContainer {
const MethodAttributes interface_method_attributes =
MethodAttributes.Public |
MethodAttributes.Abstract |
ArrayList method_builders;
ArrayList property_builders;
+ ArrayList event_builders;
Attributes OptAttributes;
+ public string IndexerName;
+
+ IMemberContainer parent_container;
+ MemberCache member_cache;
+
+ bool members_defined;
+
// These will happen after the semantic analysis
// Hashtable defined_indexers;
public Interface (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
: base (parent, name, l)
{
- ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE, l);
+ ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PUBLIC, l);
OptAttributes = attrs;
method_builders = new ArrayList ();
property_builders = new ArrayList ();
+ event_builders = new ArrayList ();
}
public AdditionResult AddMethod (InterfaceMethod imethod)
return true;
}
- public MethodInfo [] GetMethods ()
+ //
+ // This might trigger a definition of the methods. This happens only
+ // with Attributes, as Attribute classes are processed before interfaces.
+ // Ideally, we should make everything just define recursively in terms
+ // of its dependencies.
+ //
+ public MethodInfo [] GetMethods (TypeContainer container)
{
- int n = method_builders.Count;
+ int n = 0;
+
+ if (!members_defined){
+ if (DefineMembers (container))
+ n = method_builders.Count;
+ } else
+ n = method_builders.Count;
+
MethodInfo [] mi = new MethodInfo [n];
method_builders.CopyTo (mi, 0);
}
// Hack around System.Reflection as found everywhere else
- public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf, MemberFilter filter, object criteria)
+ public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
+ MemberFilter filter, object criteria)
{
ArrayList members = new ArrayList ();
members.Add (pb);
}
- if ((bf & BindingFlags.DeclaredOnly) == 0){
- MemberInfo [] parent_mi;
+ if ((mt & MemberTypes.Event) != 0) {
+ foreach (MyEventBuilder eb in event_builders)
+ if (filter (eb, criteria))
+ members.Add (eb);
+ }
+
+ if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
+ MemberList parent_mi;
parent_mi = TypeContainer.FindMembers (
TypeBuilder.BaseType, mt, bf, filter, criteria);
- if (parent_mi != null)
- members.AddRange (parent_mi);
+ members.AddRange (parent_mi);
}
-
- // The rest of the cases, if any, are unhandled at present.
- int count = members.Count;
+ return new MemberList (members);
+ }
- if (count > 0) {
- MemberInfo [] mi = new MemberInfo [count];
- members.CopyTo (mi, 0);
- return mi;
+ public override MemberCache MemberCache {
+ get {
+ return member_cache;
}
-
- return null;
}
//
//
void PopulateMethod (TypeContainer parent, DeclSpace decl_space, InterfaceMethod im)
{
- Type return_type = RootContext.LookupType (this, im.ReturnType, false, im.Location);
+ Type return_type = this.ResolveType (im.ReturnType, false, im.Location);
Type [] arg_types = im.ParameterTypes (this);
MethodBuilder mb;
Parameter [] p;
if (return_type.IsPointer && !UnsafeOK (this))
return;
+ if (arg_types == null)
+ return;
+
foreach (Type t in arg_types){
if (t == null)
{
PropertyBuilder pb;
MethodBuilder get = null, set = null;
- Type prop_type = RootContext.LookupType (this, ip.Type, false, ip.Location);
+ ip.Type = this.ResolveTypeExpr (ip.Type, false, ip.Location);
+ Type prop_type = ip.Type.Type;
Type [] setter_args = new Type [1];
if (prop_type == null)
//
Type [] null_types = null;
InternalParameters inp = new InternalParameters
- (null_types, Parameters.GetEmptyReadOnlyParameters ());
+ (null_types, Parameters.EmptyReadOnlyParameters);
if (!RegisterMethod (get, inp, null)) {
Error111 (ip);
// FIXME: We need to do this after delegates have been
// declared or we declare them recursively.
//
+ MyEventBuilder eb;
+ MethodBuilder add = null, remove = null;
+ ie.Type = this.ResolveTypeExpr (ie.Type, false, ie.Location);
+ Type event_type = ie.Type.Type;
+
+ if (event_type == null)
+ return;
+
+ if (event_type.IsPointer && !UnsafeOK (this))
+ return;
+
+ Type [] parameters = new Type [1];
+ parameters [0] = event_type;
+
+ eb = new MyEventBuilder (TypeBuilder, ie.Name,
+ EventAttributes.None, event_type);
+
+ //
+ // Now define the accessors
+ //
+ string add_name = "add_" + ie.Name;
+
+ add = TypeBuilder.DefineMethod (
+ add_name, property_attributes, null, parameters);
+ add.DefineParameter (1, ParameterAttributes.None, "value");
+ eb.SetAddOnMethod (add);
+
+ string remove_name = "remove_" + ie.Name;
+ remove = TypeBuilder.DefineMethod (
+ remove_name, property_attributes, null, parameters);
+ remove.DefineParameter (1, ParameterAttributes.None, "value");
+ eb.SetRemoveOnMethod (remove);
+
+ Parameter [] parms = new Parameter [1];
+ parms [0] = new Parameter (ie.Type, "value", Parameter.Modifier.NONE, null);
+ InternalParameters ip = new InternalParameters (
+ this, new Parameters (parms, null, Location.Null));
+
+ if (!RegisterMethod (add, ip, parameters)) {
+ Error111 (ie);
+ return;
+ }
+
+ if (!RegisterMethod (remove, ip, parameters)) {
+ Error111 (ie);
+ return;
+ }
+
+ EmitContext ec = new EmitContext (parent, decl_space, Location, null,
+ null, ModFlags, false);
+
+
+ if (ie.OptAttributes != null)
+ Attribute.ApplyAttributes (ec, eb, ie, ie.OptAttributes, Location);
+
+ TypeManager.RegisterEvent (eb, add, remove);
+ event_builders.Add (eb);
}
//
void PopulateIndexer (TypeContainer parent, DeclSpace decl_space, InterfaceIndexer ii)
{
PropertyBuilder pb;
- Type prop_type = RootContext.LookupType (this, ii.Type, false, ii.Location);
+ ii.Type = this.ResolveTypeExpr (ii.Type, false, ii.Location);
+ Type prop_type = ii.Type.Type;
Type [] arg_types = ii.ParameterTypes (this);
Type [] value_arg_types;
value_arg_types [1] = prop_type;
}
+ EmitContext ec = new EmitContext (parent, decl_space, Location, null,
+ null, ModFlags, false);
+
+ IndexerName = Attribute.ScanForIndexerName (ec, ii.OptAttributes);
+ if (IndexerName == null)
+ IndexerName = "Item";
+
pb = TypeBuilder.DefineProperty (
- "Item", PropertyAttributes.None,
+ IndexerName, PropertyAttributes.None,
prop_type, arg_types);
MethodBuilder set_item = null, get_item = null;
Parameter [] p = ii.Parameters.FixedParameters;
get_item = TypeBuilder.DefineMethod (
- "get_Item", property_attributes, prop_type, arg_types);
+ "get_" + IndexerName, property_attributes,
+ prop_type, arg_types);
pb.SetGetMethod (get_item);
//
// HACK because System.Reflection.Emit is lame
if (ii.HasSet){
Parameter [] p = ii.Parameters.FixedParameters;
+ Parameter [] pv;
int i = 0;
+ pv = new Parameter [p.Length + 1];
+ p.CopyTo (pv, 0);
+ pv [p.Length] = new Parameter (ii.Type, "value", Parameter.Modifier.NONE, null);
+ Parameters value_params = new Parameters (pv, null, Location.Null);
+ value_params.GetParameterInfo (decl_space);
+
set_item = TypeBuilder.DefineMethod (
- "set_Item", property_attributes,
+ "set_" + IndexerName, property_attributes,
TypeManager.void_type, value_arg_types);
pb.SetSetMethod (set_item);
//
// HACK because System.Reflection.Emit is lame
//
InternalParameters ip = new InternalParameters (
- value_arg_types, ii.Parameters);
+ value_arg_types, value_params);
if (!RegisterMethod (set_item, ip, value_arg_types)) {
Error111 (ii);
return;
set_item.DefineParameter (i + 1, ParameterAttributes.None, "value");
}
- EmitContext ec = new EmitContext (parent, decl_space, Location, null,
- null, ModFlags, false);
-
if (ii.OptAttributes != null)
Attribute.ApplyAttributes (ec, pb, ii, ii.OptAttributes, Location);
+
+ property_builders.Add (pb);
}
/// <summary>
Type GetInterfaceTypeByName (string name)
{
- Type t = FindType (name);
+ Type t = FindType (Location, name);
- if (t == null)
+ if (t == null) {
+ Report.Error (246, Location, "The type or namespace `" + name +
+ "' could not be found");
return null;
+ }
if (t.IsInterface)
return t;
error = true;
return null;
}
-
+
+ if (!Parent.AsAccessible (t, ModFlags))
+ Report.Error (61, Location,
+ "Inconsistent accessibility: base interface `" +
+ TypeManager.MonoBASIC_Name (t) + "' is less " +
+ "accessible than interface `" +
+ Name + "'");
+
tbases [i++] = t;
}
- return tbases;
+ return TypeManager.ExpandInterfaces (tbases);
}
//
TypeManager.AddUserInterface (Name, TypeBuilder, this, ifaces);
InTransit = false;
-
+
return TypeBuilder;
}
+
+ //
+ // Defines the indexers, and also verifies that the IndexerNameAttribute in the
+ // interface is consistent. Either it is `Item' or it is the name defined by all the
+ // indexers with the `IndexerName' attribute.
+ //
+ // Turns out that the IndexerNameAttribute is applied to each indexer,
+ // but it is never emitted, instead a DefaultName attribute is attached
+ // to the interface
+ //
+ void DefineIndexers (TypeContainer parent)
+ {
+ string interface_indexer_name = null;
+
+ foreach (InterfaceIndexer ii in defined_indexer){
+
+ PopulateIndexer (parent, this, ii);
+
+ if (interface_indexer_name == null){
+ interface_indexer_name = IndexerName;
+ continue;
+ }
+
+ if (IndexerName == interface_indexer_name)
+ continue;
+
+ Report.Error (
+ 668, "Two indexers have different names, " +
+ " you should use the same name for all your indexers");
+ }
+ if (interface_indexer_name == null)
+ interface_indexer_name = "Item";
+ IndexerName = interface_indexer_name;
+ }
/// <summary>
/// Performs semantic analysis, and then generates the IL interfaces
/// </summary>
- public override bool Define (TypeContainer parent)
+ public override bool DefineMembers (TypeContainer parent)
{
if (!SemanticAnalysis ())
return false;
foreach (InterfaceEvent ie in defined_events)
PopulateEvent (parent, this, ie);
- //
- // FIXME: Pull the right indexer name out of the `IndexerName' attribute
- //
if (defined_indexer != null) {
- foreach (InterfaceIndexer ii in defined_indexer)
- PopulateIndexer (parent, this, ii);
+ DefineIndexers (parent);
CustomAttributeBuilder cb = EmitDefaultMemberAttr (
- parent, "Item", ModFlags, Location);
+ parent, IndexerName, ModFlags, Location);
if (cb != null)
TypeBuilder.SetCustomAttribute (cb);
}
-
+
+#if CACHE
+ if (TypeBuilder.BaseType != null)
+ parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
+
+ member_cache = new MemberCache (this);
+#endif
+ members_defined = true;
+ return true;
+ }
+
+ /// <summary>
+ /// Applies all the attributes.
+ /// </summary>
+ public override bool Define (TypeContainer parent)
+ {
+ if (OptAttributes != null) {
+ EmitContext ec = new EmitContext (parent, this, Location, null, null,
+ ModFlags, false);
+ Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes, Location);
+ }
+
return true;
}
return cb;
}
+ //
+ // IMemberContainer
+ //
+
+ string IMemberContainer.Name {
+ get {
+ return Name;
+ }
+ }
+
+ Type IMemberContainer.Type {
+ get {
+ return TypeBuilder;
+ }
+ }
+
+ IMemberContainer IMemberContainer.Parent {
+ get {
+ return parent_container;
+ }
+ }
+
+ MemberCache IMemberContainer.MemberCache {
+ get {
+ return member_cache;
+ }
+ }
+
+ bool IMemberContainer.IsInterface {
+ get {
+ return true;
+ }
+ }
+
+ MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
+ {
+ // Interfaces only contain instance members.
+ if ((bf & BindingFlags.Instance) == 0)
+ return MemberList.Empty;
+ if ((bf & BindingFlags.Public) == 0)
+ return MemberList.Empty;
+
+ ArrayList members = new ArrayList ();
+
+ if ((mt & MemberTypes.Method) != 0)
+ members.AddRange (method_builders);
+
+ if ((mt & MemberTypes.Property) != 0)
+ members.AddRange (property_builders);
+
+ if ((mt & MemberTypes.Event) != 0)
+ members.AddRange (event_builders);
+
+ return new MemberList (members);
+ }
}
public class InterfaceMemberBase {
public class InterfaceProperty : InterfaceMemberBase {
public readonly bool HasSet;
public readonly bool HasGet;
- public readonly string Type;
- public readonly string type;
public readonly Location Location;
+ public Expression Type;
- public InterfaceProperty (string type, string name,
+ public InterfaceProperty (Expression type, string name,
bool is_new, bool has_get, bool has_set,
Attributes attrs, Location loc)
: base (name, is_new, attrs)
}
public class InterfaceEvent : InterfaceMemberBase {
- public readonly string Type;
+ public readonly Location Location;
+ public Expression Type;
- public InterfaceEvent (string type, string name, bool is_new, Attributes attrs)
+ public InterfaceEvent (Expression type, string name, bool is_new, Attributes attrs,
+ Location loc)
: base (name, is_new, attrs)
{
Type = type;
+ Location = loc;
}
}
public class InterfaceMethod : InterfaceMemberBase {
- public readonly string ReturnType;
+ public readonly Expression ReturnType;
public readonly Parameters Parameters;
public readonly Location Location;
- public InterfaceMethod (string return_type, string name, bool is_new, Parameters args,
+ public InterfaceMethod (Expression return_type, string name, bool is_new, Parameters args,
Attributes attrs, Location l)
: base (name, is_new, attrs)
{
/// </summary>
public string GetSignature (DeclSpace ds)
{
- Type ret = RootContext.LookupType (ds, ReturnType, false, Location);
+ Type ret = ds.ResolveType (ReturnType, false, Location);
string args = Parameters.GetSignature (ds);
if ((ret == null) || (args == null))
public class InterfaceIndexer : InterfaceMemberBase {
public readonly bool HasGet, HasSet;
public readonly Parameters Parameters;
- public readonly string Type;
public readonly Location Location;
+ public Expression Type;
- public InterfaceIndexer (string type, Parameters args, bool do_get, bool do_set,
+ public InterfaceIndexer (Expression type, Parameters args, bool do_get, bool do_set,
bool is_new, Attributes attrs, Location loc)
: base ("", is_new, attrs)
{