//
// Author: Miguel de Icaza (miguel@gnu.org)
// Ravi Pratap (ravi@ximian.com)
+// Anirban Bhattacharjee (banirban@novell.com)
+// Jambunathan K (kjambunathan@novell.com)
//
// Licensed under the terms of the GNU GPL
//
using System.Reflection;
using System.Reflection.Emit;
-namespace Mono.CSharp {
+namespace Mono.MonoBASIC {
+
+ public class EnumMember : MemberCore
+ {
+ Enum parent_enum;
+ Expression expr;
+ int index;
+
+ FieldBuilder builder;
+ object enum_value;
+
+ bool in_transit = false;
+ FieldAttributes field_attrs = FieldAttributes.Public | FieldAttributes.Static
+ | FieldAttributes.Literal;
+
+ public EnumMember (Enum parent_enum, Expression expr, string name,
+ Location loc, Attributes attrs, int index):
+ base (name, attrs, loc)
+ {
+ this.parent_enum = parent_enum;
+ this.expr = expr;
+ this.index = index;
+ }
+
+ public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
+ {
+ builder.SetCustomAttribute (cb);
+ }
+
+ public override AttributeTargets AttributeTargets {
+ get {
+ return AttributeTargets.Field;
+ }
+ }
+
+ public override bool Define (TypeContainer tc)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public object GetValue ()
+ {
+ if (builder == null)
+ DefineMember ();
+
+ return enum_value;
+ }
+
+ public FieldBuilder DefineMember ()
+ {
+ if (builder != null)
+ return builder;
+
+ DoDefineMember ();
+
+ if (builder == null)
+ parent_enum.RemoveEnumMember (this.Name);
+
+ return builder;
+ }
+
+ public FieldBuilder DoDefineMember ()
+ {
+ object default_value = null;
+ Constant c = null;
+ Type UnderlyingType = parent_enum.UnderlyingType;
+ EmitContext ec = parent_enum.EmitContext;
+
+ default_value = enum_value;
+
+ if (in_transit) {
+ Report.Error (30500, Location, "The evaluation of the constant value for `" +
+ parent_enum.Name + "." + Name + "' involves a circular definition.");
+ return null;
+ }
+
+ //
+ // So if the above doesn't happen, we have a member that is undefined
+ // We now proceed to define it
+ //
+ Expression val = expr;
+ int idx = index;
+
+ if (val == null) {
+ if (idx == 0)
+ default_value = 0;
+ else {
+ int i = idx - 1;
+ EnumMember em = parent_enum [i];
+
+ in_transit = true;
+ default_value = em.GetValue ();
+ in_transit = false;
+
+ if (default_value == null)
+ return null;
+
+ default_value = Enum.GetNextDefaultValue (default_value, UnderlyingType);
+ }
+
+ } else {
+ bool old = ec.InEnumContext;
+ ec.InEnumContext = true;
+ in_transit = true;
+ val = val.Resolve (ec);
+ in_transit = false;
+ ec.InEnumContext = old;
+
+ if (val == null)
+ return null;
+
+ if (! Enum.IsValidEnumConstant (val)) {
+ Report.Error (
+ 30650, Location,
+ "Type byte, sbyte, short, ushort, int, uint, long, or " +
+ "ulong expected (have: " + val + ")");
+ return null;
+ }
+
+ c = (Constant) val;
+
+ default_value = c.GetValue ();
+
+ if (default_value == null) {
+ Enum.Error_ConstantValueCannotBeConverted (c, Location, UnderlyingType);
+ return null;
+ }
+ }
+
+ builder = parent_enum.TypeBuilder.DefineField (Name, parent_enum.TypeBuilder, field_attrs);
+
+ try {
+ //FXME: ChangeType is not the right thing to do.
+ default_value = TypeManager.ChangeType (default_value, UnderlyingType);
+ } catch {
+ Enum.Error_ConstantValueCannotBeConverted (c, Location, UnderlyingType);
+ return null;
+ }
+
+ enum_value = default_value;
+
+ builder.SetConstant (enum_value);
+
+ if (!TypeManager.RegisterFieldValue (builder, enum_value))
+ return null;
+
+ if (OptAttributes != null)
+ OptAttributes.Emit (ec, this);
+
+ return builder;
+ }
+
+ }
+
/// <summary>
/// Enumeration container
/// </summary>
public class Enum : DeclSpace {
-
ArrayList ordered_enums;
- public readonly string BaseType;
- public Attributes OptAttributes;
-
+ public Expression BaseType;
public Type UnderlyingType;
-
- Hashtable member_to_location;
-
- //
- // This is for members that have been defined
- //
- Hashtable member_to_value;
-
ArrayList field_builders;
public const int AllowedModifiers =
Modifiers.INTERNAL |
Modifiers.PRIVATE;
- public Enum (TypeContainer parent, string type, int mod_flags, string name, Attributes attrs, Location l)
- : base (parent, name, l)
+ EmitContext emit_context;
+
+ public Enum (TypeContainer parent, Expression type, int mod_flags, string name, Attributes attrs, Location l)
+ : base (parent, name, attrs, l)
{
this.BaseType = type;
- ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PUBLIC, l);
- OptAttributes = attrs;
+ ModFlags = Modifiers.Check (AllowedModifiers, mod_flags,
+ IsTopLevel ? Modifiers.INTERNAL : Modifiers.PUBLIC, l);
ordered_enums = new ArrayList ();
- member_to_location = new Hashtable ();
- member_to_value = new Hashtable ();
field_builders = new ArrayList ();
}
+ public override AttributeTargets AttributeTargets {
+ get {
+ return AttributeTargets.Enum;
+ }
+ }
+
/// <summary>
/// Adds @name to the enumeration space, with @expr
/// being its definition.
/// </summary>
- public AdditionResult AddEnumMember (string name, Expression expr, Location loc)
+ public AdditionResult AddEnumMember (string name, Expression expr, Location loc,
+ Attributes opt_attrs)
{
+ int index;
+ EnumMember em;
+
if (defined_names.Contains (name))
return AdditionResult.NameExists;
- DefineName (name, expr);
+ index = ordered_enums.Add (name);
+ em = new EnumMember (this, expr, name, loc, opt_attrs, index);
+ DefineName (name, em);
- ordered_enums.Add (name);
- member_to_location.Add (name, loc);
-
return AdditionResult.Success;
}
- //
- // This is used by corlib compilation: we map from our
- // type to a type that is consumable by the DefineField
- //
- Type MapToInternalType (Type t)
+ public void RemoveEnumMember (string name)
{
- if (t == TypeManager.int32_type)
- return typeof (int);
- if (t == TypeManager.int64_type)
- return typeof (long);
- if (t == TypeManager.uint32_type)
- return typeof (uint);
- if (t == TypeManager.uint64_type)
- return typeof (ulong);
- if (t == TypeManager.float_type)
- return typeof (float);
- if (t == TypeManager.double_type)
- return typeof (double);
- if (t == TypeManager.byte_type)
- return typeof (byte);
- if (t == TypeManager.sbyte_type)
- return typeof (sbyte);
- if (t == TypeManager.char_type)
- return typeof (char);
- if (t == TypeManager.short_type)
- return typeof (short);
- if (t == TypeManager.ushort_type)
- return typeof (ushort);
-
- throw new Exception ();
+ defined_names.Remove (name);
}
-
+
public override TypeBuilder DefineType ()
{
if (TypeBuilder != null)
return TypeBuilder;
-
- TypeAttributes attr = TypeAttributes.Class | TypeAttributes.Sealed;
- UnderlyingType = TypeManager.LookupType (BaseType);
-
+ emit_context = new EmitContext (Parent, this, Location, null,
+ UnderlyingType, ModFlags, false);
+
+ TypeAttributes attr = Modifiers.TypeAttr (ModFlags, IsTopLevel);
+
+ attr |= TypeAttributes.Class | TypeAttributes.Sealed;
+
+ UnderlyingType = ResolveType (BaseType, false, Location);
+
if (UnderlyingType != TypeManager.int32_type &&
UnderlyingType != TypeManager.uint32_type &&
UnderlyingType != TypeManager.int64_type &&
UnderlyingType != TypeManager.ushort_type &&
UnderlyingType != TypeManager.byte_type &&
UnderlyingType != TypeManager.sbyte_type) {
- Report.Error (1008, Location,
+ Report.Error (30650, Location,
"Type byte, sbyte, short, ushort, int, uint, " +
"long, or ulong expected (got: " +
- TypeManager.CSharpName (UnderlyingType) + ")");
+ TypeManager.MonoBASIC_Name (UnderlyingType) + ")");
return null;
}
if (IsTopLevel) {
ModuleBuilder builder = CodeGen.ModuleBuilder;
- if ((ModFlags & Modifiers.PUBLIC) != 0)
- attr |= TypeAttributes.Public;
- else
- attr |= TypeAttributes.NotPublic;
-
TypeBuilder = builder.DefineType (Name, attr, TypeManager.enum_type);
} else {
TypeBuilder builder = Parent.TypeBuilder;
- if ((ModFlags & Modifiers.PUBLIC) != 0)
- attr |= TypeAttributes.NestedPublic;
- else
- attr |= TypeAttributes.NestedPrivate;
-
-
TypeBuilder = builder.DefineNestedType (
Basename, attr, TypeManager.enum_type);
}
- //
- // Call MapToInternalType for corlib
- //
TypeBuilder.DefineField ("value__", UnderlyingType,
FieldAttributes.Public | FieldAttributes.SpecialName
| FieldAttributes.RTSpecialName);
return TypeBuilder;
}
- bool IsValidEnumConstant (Expression e)
+ public static bool IsValidEnumConstant (Expression e)
{
if (!(e is Constant))
return false;
return false;
}
- object GetNextDefaultValue (object default_value)
+ static public object GetNextDefaultValue (object default_value, Type UnderlyingType)
{
if (UnderlyingType == TypeManager.int32_type) {
int i = (int) default_value;
return null;
}
- void Error_ConstantValueCannotBeConverted (object val, Location loc)
+ public static void Error_ConstantValueCannotBeConverted (object val, Location loc, Type UnderlyingType)
{
if (val is Constant)
- Report.Error (31, loc, "Constant value '" + ((Constant) val).AsString () +
+ Report.Error (30439, loc, "Constant value '" + ((Constant) val).AsString () +
"' cannot be converted" +
- " to a " + TypeManager.CSharpName (UnderlyingType));
+ " to a " + TypeManager.MonoBASIC_Name (UnderlyingType));
else
- Report.Error (31, loc, "Constant value '" + val +
+ Report.Error (30439, loc, "Constant value '" + val +
"' cannot be converted" +
- " to a " + TypeManager.CSharpName (UnderlyingType));
+ " to a " + TypeManager.MonoBASIC_Name (UnderlyingType));
return;
}
/// This is used to lookup the value of an enum member. If the member is undefined,
/// it attempts to define it and return its value
/// </summary>
- public object LookupEnumValue (EmitContext ec, string name, Location loc)
+ public object LookupEnumValue (string name)
{
- object default_value = null;
- Constant c = null;
+ EnumMember em;
- default_value = member_to_value [name];
+ // first check whether the requested name is there
+ // in the member list of enum
- if (default_value != null)
- return default_value;
+ em = this [name];
- if (!defined_names.Contains (name)) {
- Report.Error (117, loc, "'"+ Name + "' does not contain a definition for '"
- + name + "'");
+ if (em == null)
return null;
- }
-
- //
- // So if the above doesn't happen, we have a member that is undefined
- // We now proceed to define it
- //
- Expression val = this [name];
-
- if (val == null) {
-
- int idx = ordered_enums.IndexOf (name);
-
- if (idx == 0)
- default_value = 0;
- else {
- for (int i = 0; i < idx; ++i) {
- string n = (string) ordered_enums [i];
- Location m_loc = (Mono.CSharp.Location)
- member_to_location [n];
- default_value = LookupEnumValue (ec, n, m_loc);
- }
-
- default_value = GetNextDefaultValue (default_value);
- }
-
- } else {
- bool old = ec.InEnumContext;
- ec.InEnumContext = true;
- val = val.Resolve (ec);
- ec.InEnumContext = old;
-
- if (val == null) {
- Report.Error (-12, loc, "Definition is circular.");
- return null;
- }
-
- if (IsValidEnumConstant (val)) {
- c = (Constant) val;
- default_value = c.GetValue ();
-
- if (default_value == null) {
- Error_ConstantValueCannotBeConverted (c, loc);
- return null;
- }
-
- } else {
- Report.Error (
- 1008, loc,
- "Type byte, sbyte, short, ushort, int, uint, long, or " +
- "ulong expected (have: " + val + ")");
- return null;
- }
- }
-
- FieldAttributes attr = FieldAttributes.Public | FieldAttributes.Static
- | FieldAttributes.Literal;
- FieldBuilder fb = TypeBuilder.DefineField (name, UnderlyingType, attr);
-
- try {
- default_value = Convert.ChangeType (default_value, UnderlyingType);
- } catch {
- Error_ConstantValueCannotBeConverted (c, loc);
+ name = em.Name;
+ FieldBuilder fb = em.DefineMember ();
+
+ if (fb == null) {
return null;
+ }
+
+ if (! field_builders.Contains (fb)) {
+ field_builders.Add (fb);
}
- fb.SetConstant (default_value);
- field_builders.Add (fb);
- member_to_value [name] = default_value;
+ return em.GetValue ();
+ }
- if (!TypeManager.RegisterFieldValue (fb, default_value))
- return null;
-
- return default_value;
+ public override bool DefineMembers (TypeContainer parent)
+ {
+ return true;
}
public override bool Define (TypeContainer parent)
{
- //
- // If there was an error during DefineEnum, return
- //
if (TypeBuilder == null)
return false;
-
+ /*
EmitContext ec = new EmitContext (parent, this, Location, null,
UnderlyingType, ModFlags, false);
-
- object default_value = 0;
-
- FieldAttributes attr = FieldAttributes.Public | FieldAttributes.Static
- | FieldAttributes.Literal;
-
-
+ */
foreach (string name in ordered_enums) {
- //
- // Have we already been defined, thanks to some cross-referencing ?
- //
- if (member_to_value.Contains (name))
- continue;
-
- Location loc = (Mono.CSharp.Location) member_to_location [name];
-
- if (this [name] != null) {
- default_value = LookupEnumValue (ec, name, loc);
+ EnumMember em = this [name];
+ FieldBuilder fb = em.DefineMember ();
- if (default_value == null)
- return true;
-
- } else {
- FieldBuilder fb = TypeBuilder.DefineField (
- name, UnderlyingType, attr);
-
- if (default_value == null) {
- Report.Error (543, loc, "Enumerator value for '" + name + "' is too large to " +
- "fit in its type");
- return false;
- }
-
- try {
- default_value = Convert.ChangeType (default_value, UnderlyingType);
- } catch {
- Error_ConstantValueCannotBeConverted (default_value, loc);
- return false;
- }
+ if (fb == null) {
+ return false;
+ }
- fb.SetConstant (default_value);
+ if (!field_builders.Contains (fb)) {
field_builders.Add (fb);
- member_to_value [name] = default_value;
-
- if (!TypeManager.RegisterFieldValue (fb, default_value))
- return false;
}
-
- default_value = GetNextDefaultValue (default_value);
}
-
- Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes, Location);
+ if (OptAttributes != null)
+ OptAttributes.Emit (EmitContext, this);
+
return true;
}
//
- // Hack around System.Reflection as found everywhere else
+ // IMemberFinder
//
- 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 ();
if ((mt & MemberTypes.Field) != 0) {
+
+ if (criteria is string){
+ LookupEnumValue ((string) criteria);
+ }
+
foreach (FieldBuilder fb in field_builders)
if (filter (fb, criteria) == true)
members.Add (fb);
}
- 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 null;
}
-
- return null;
}
public ArrayList ValueNames {
}
// indexer
- public Expression this [string name] {
+ public EnumMember this [string name] {
+ get {
+ EnumMember em = (EnumMember) defined_names [name];
+
+ if (em != null)
+ return em;
+
+ name = name.ToLower();
+ foreach (string nm in ordered_enums) {
+ if (nm.ToLower() == name) {
+ em = (EnumMember) defined_names [name];
+ break;
+ }
+ }
+
+ return em;
+ }
+ }
+
+ public EnumMember this[int mem_index] {
+ get {
+ string mem_name = (string) ordered_enums [mem_index];;
+ return (EnumMember) defined_names[mem_name];
+ }
+ }
+
+ public EmitContext EmitContext {
get {
- return (Expression) defined_names [name];
+ return emit_context;
}
}
}