2004-05-27 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / gmcs / enum.cs
1 //
2 // enum.cs: Enum handling.
3 //
4 // Author: Miguel de Icaza (miguel@gnu.org)
5 //         Ravi Pratap     (ravi@ximian.com)
6 //
7 // Licensed under the terms of the GNU GPL
8 //
9 // (C) 2001 Ximian, Inc (http://www.ximian.com)
10 //
11
12 using System;
13 using System.Collections;
14 using System.Reflection;
15 using System.Reflection.Emit;
16
17 namespace Mono.CSharp {
18
19         class EnumMember: Attributable {
20                 string name;
21                 Enum parent;
22                 Location loc;
23
24                 static string[] attribute_targets = new string [] { "field" };
25
26                 public FieldBuilder builder;
27
28                 public EnumMember (string name, Enum parent, Location loc, Attributes attrs):
29                         base (attrs)
30                 {
31                         this.name = name;
32                         this.parent = parent;
33                         this.loc = loc;
34                 }
35
36                 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
37                 {
38                         if (a.Type == TypeManager.marshal_as_attr_type) {
39                                 UnmanagedMarshal marshal = a.GetMarshal ();
40                                 if (marshal != null) {
41                                         builder.SetMarshal (marshal);
42                                         return;
43                                 }
44                                 Report.Warning_T (-24, a.Location);
45                                 return;
46                         }
47
48                         builder.SetCustomAttribute (cb);
49                 }
50
51                 public override AttributeTargets AttributeTargets {
52                         get {
53                                 return AttributeTargets.Field;
54                         }
55                 }
56
57                 public override bool IsClsCompliaceRequired(DeclSpace ds)
58                 {
59                         return parent.IsClsCompliaceRequired (ds);
60                 }
61
62                 public void DefineMember (TypeBuilder tb)
63                 {
64                         FieldAttributes attr = FieldAttributes.Public | FieldAttributes.Static
65                                 | FieldAttributes.Literal;
66                         
67                         builder = tb.DefineField (name, tb, attr);
68                 }
69
70                 public void Emit (EmitContext ec)
71                 {
72                         if (OptAttributes != null)
73                                 OptAttributes.Emit (ec, this); 
74                 }
75
76                 protected override string[] ValidAttributeTargets {
77                         get {
78                                 return attribute_targets;
79                         }
80                 }
81         }
82
83         /// <summary>
84         ///   Enumeration container
85         /// </summary>
86         public class Enum : DeclSpace {
87                 ArrayList ordered_enums;
88                 
89                 public Expression BaseType;
90                 
91                 public Type UnderlyingType;
92
93                 Hashtable member_to_location;
94                 Hashtable member_to_attributes;
95
96                 //
97                 // This is for members that have been defined
98                 //
99                 Hashtable member_to_value;
100
101                 //
102                 // This is used to mark members we're currently defining
103                 //
104                 Hashtable in_transit;
105                 
106                 ArrayList field_builders;
107                 
108
109                 Hashtable name_to_member;
110                 
111                 public const int AllowedModifiers =
112                         Modifiers.NEW |
113                         Modifiers.PUBLIC |
114                         Modifiers.PROTECTED |
115                         Modifiers.INTERNAL |
116                         Modifiers.PRIVATE;
117
118                 public Enum (NamespaceEntry ns, TypeContainer parent, Expression type,
119                              int mod_flags, MemberName name, Attributes attrs, Location l)
120                         : base (ns, parent, name, attrs, l)
121                 {
122                         this.BaseType = type;
123                         ModFlags = Modifiers.Check (AllowedModifiers, mod_flags,
124                                                     IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE, l);
125
126                         ordered_enums = new ArrayList ();
127                         member_to_location = new Hashtable ();
128                         member_to_value = new Hashtable ();
129                         in_transit = new Hashtable ();
130                         field_builders = new ArrayList ();
131
132                         name_to_member = new Hashtable ();
133                 }
134
135                 /// <summary>
136                 ///   Adds @name to the enumeration space, with @expr
137                 ///   being its definition.  
138                 /// </summary>
139                 public AdditionResult AddEnumMember (string name, Expression expr, Location loc,
140                                                      Attributes opt_attrs)
141                 {
142                         if (defined_names.Contains (name))
143                                 return AdditionResult.NameExists;
144
145                         if (name == "value__") {
146                                 Report.Error (76, loc, "An item in an enumeration can't have an identifier `value__'");
147                                 return AdditionResult.Error;
148                         }
149
150                         DefineName (name, expr);
151
152                         ordered_enums.Add (name);
153                         member_to_location.Add (name, loc);
154
155                         if (member_to_attributes == null)
156                                 member_to_attributes = new Hashtable ();
157
158                         member_to_attributes.Add (name, opt_attrs);
159                         
160                         name_to_member.Add (name, new EnumMember (name, this, loc, opt_attrs));
161
162                         return AdditionResult.Success;
163                 }
164
165                 //
166                 // This is used by corlib compilation: we map from our
167                 // type to a type that is consumable by the DefineField
168                 //
169                 Type MapToInternalType (Type t)
170                 {
171                         if (t == TypeManager.int32_type)
172                                 return typeof (int);
173                         if (t == TypeManager.int64_type)
174                                 return typeof (long);
175                         if (t == TypeManager.uint32_type)
176                                 return typeof (uint);
177                         if (t == TypeManager.uint64_type)
178                                 return typeof (ulong);
179                         if (t == TypeManager.float_type)
180                                 return typeof (float);
181                         if (t == TypeManager.double_type)
182                                 return typeof (double);
183                         if (t == TypeManager.byte_type)
184                                 return typeof (byte);
185                         if (t == TypeManager.sbyte_type)
186                                 return typeof (sbyte);
187                         if (t == TypeManager.char_type)
188                                 return typeof (char);
189                         if (t == TypeManager.short_type)
190                                 return typeof (short);
191                         if (t == TypeManager.ushort_type)
192                                 return typeof (ushort);
193
194                         throw new Exception ();
195                 }
196                 
197                 public override TypeBuilder DefineType ()
198                 {
199                         if (TypeBuilder != null)
200                                 return TypeBuilder;
201
202                         TypeAttributes attr = Modifiers.TypeAttr (ModFlags, IsTopLevel);
203
204                         attr |= TypeAttributes.Class | TypeAttributes.Sealed;
205
206                         UnderlyingType = ResolveType (BaseType, false, Location);
207
208                         if (UnderlyingType != TypeManager.int32_type &&
209                             UnderlyingType != TypeManager.uint32_type &&
210                             UnderlyingType != TypeManager.int64_type &&
211                             UnderlyingType != TypeManager.uint64_type &&
212                             UnderlyingType != TypeManager.short_type &&
213                             UnderlyingType != TypeManager.ushort_type &&
214                             UnderlyingType != TypeManager.byte_type  &&
215                             UnderlyingType != TypeManager.sbyte_type) {
216                                 Report.Error (1008, Location,
217                                               "Type byte, sbyte, short, ushort, int, uint, " +
218                                               "long, or ulong expected (got: " +
219                                               TypeManager.CSharpName (UnderlyingType) + ")");
220                                 return null;
221                         }
222
223                         if (IsTopLevel) {
224                                 if (TypeManager.NamespaceClash (Name, Location))
225                                         return null;
226                                 
227                                 ModuleBuilder builder = CodeGen.Module.Builder;
228
229                                 TypeBuilder = builder.DefineType (Name, attr, TypeManager.enum_type);
230                         } else {
231                                 TypeBuilder builder = Parent.TypeBuilder;
232
233                                 TypeBuilder = builder.DefineNestedType (
234                                         Basename, attr, TypeManager.enum_type);
235                         }
236
237                         //
238                         // Call MapToInternalType for corlib
239                         //
240                         TypeBuilder.DefineField ("value__", UnderlyingType,
241                                                  FieldAttributes.Public | FieldAttributes.SpecialName
242                                                  | FieldAttributes.RTSpecialName);
243
244                         TypeManager.AddEnumType (Name, TypeBuilder, this);
245
246                         return TypeBuilder;
247                 }
248
249                 bool IsValidEnumConstant (Expression e)
250                 {
251                         if (!(e is Constant))
252                                 return false;
253
254                         if (e is IntConstant || e is UIntConstant || e is LongConstant ||
255                             e is ByteConstant || e is SByteConstant || e is ShortConstant ||
256                             e is UShortConstant || e is ULongConstant || e is EnumConstant ||
257                             e is CharConstant)
258                                 return true;
259                         else
260                                 return false;
261                 }
262
263                 object GetNextDefaultValue (object default_value)
264                 {
265                         if (UnderlyingType == TypeManager.int32_type) {
266                                 int i = (int) default_value;
267                                 
268                                 if (i < System.Int32.MaxValue)
269                                         return ++i;
270                                 else
271                                         return null;
272                         } else if (UnderlyingType == TypeManager.uint32_type) {
273                                 uint i = (uint) default_value;
274
275                                 if (i < System.UInt32.MaxValue)
276                                         return ++i;
277                                 else
278                                         return null;
279                         } else if (UnderlyingType == TypeManager.int64_type) {
280                                 long i = (long) default_value;
281
282                                 if (i < System.Int64.MaxValue)
283                                         return ++i;
284                                 else
285                                         return null;
286                         } else if (UnderlyingType == TypeManager.uint64_type) {
287                                 ulong i = (ulong) default_value;
288
289                                 if (i < System.UInt64.MaxValue)
290                                         return ++i;
291                                 else
292                                         return null;
293                         } else if (UnderlyingType == TypeManager.short_type) {
294                                 short i = (short) default_value;
295
296                                 if (i < System.Int16.MaxValue)
297                                         return ++i;
298                                 else
299                                         return null;
300                         } else if (UnderlyingType == TypeManager.ushort_type) {
301                                 ushort i = (ushort) default_value;
302
303                                 if (i < System.UInt16.MaxValue)
304                                         return ++i;
305                                 else
306                                         return null;
307                         } else if (UnderlyingType == TypeManager.byte_type) {
308                                 byte i = (byte) default_value;
309
310                                 if (i < System.Byte.MaxValue)
311                                         return ++i;
312                                 else
313                                         return null;
314                         } else if (UnderlyingType == TypeManager.sbyte_type) {
315                                 sbyte i = (sbyte) default_value;
316
317                                 if (i < System.SByte.MaxValue)
318                                         return ++i;
319                                 else
320                                         return null;
321                         }
322
323                         return null;
324                 }
325
326                 void Error_ConstantValueCannotBeConverted (object val, Location loc)
327                 {
328                         if (val is Constant)
329                                 Report.Error (31, loc, "Constant value '" + ((Constant) val).AsString () +
330                                               "' cannot be converted" +
331                                               " to a " + TypeManager.CSharpName (UnderlyingType));
332                         else 
333                                 Report.Error (31, loc, "Constant value '" + val +
334                                               "' cannot be converted" +
335                                               " to a " + TypeManager.CSharpName (UnderlyingType));
336                         return;
337                 }
338
339                 /// <summary>
340                 ///  Determines if a standard implicit conversion exists from
341                 ///  expr_type to target_type
342                 /// </summary>
343                 public static bool ImplicitConversionExists (Type expr_type, Type target_type)
344                 {
345                         expr_type = TypeManager.TypeToCoreType (expr_type);
346
347                         if (expr_type == TypeManager.void_type)
348                                 return false;
349                         
350                         if (expr_type == target_type)
351                                 return true;
352
353                         // First numeric conversions 
354
355                         if (expr_type == TypeManager.sbyte_type){
356                                 //
357                                 // From sbyte to short, int, long, float, double.
358                                 //
359                                 if ((target_type == TypeManager.int32_type) || 
360                                     (target_type == TypeManager.int64_type) ||
361                                     (target_type == TypeManager.double_type) ||
362                                     (target_type == TypeManager.float_type)  ||
363                                     (target_type == TypeManager.short_type) ||
364                                     (target_type == TypeManager.decimal_type))
365                                         return true;
366                                 
367                         } else if (expr_type == TypeManager.byte_type){
368                                 //
369                                 // From byte to short, ushort, int, uint, long, ulong, float, double
370                                 // 
371                                 if ((target_type == TypeManager.short_type) ||
372                                     (target_type == TypeManager.ushort_type) ||
373                                     (target_type == TypeManager.int32_type) ||
374                                     (target_type == TypeManager.uint32_type) ||
375                                     (target_type == TypeManager.uint64_type) ||
376                                     (target_type == TypeManager.int64_type) ||
377                                     (target_type == TypeManager.float_type) ||
378                                     (target_type == TypeManager.double_type) ||
379                                     (target_type == TypeManager.decimal_type))
380                                         return true;
381         
382                         } else if (expr_type == TypeManager.short_type){
383                                 //
384                                 // From short to int, long, float, double
385                                 // 
386                                 if ((target_type == TypeManager.int32_type) ||
387                                     (target_type == TypeManager.int64_type) ||
388                                     (target_type == TypeManager.double_type) ||
389                                     (target_type == TypeManager.float_type) ||
390                                     (target_type == TypeManager.decimal_type))
391                                         return true;
392                                         
393                         } else if (expr_type == TypeManager.ushort_type){
394                                 //
395                                 // From ushort to int, uint, long, ulong, float, double
396                                 //
397                                 if ((target_type == TypeManager.uint32_type) ||
398                                     (target_type == TypeManager.uint64_type) ||
399                                     (target_type == TypeManager.int32_type) ||
400                                     (target_type == TypeManager.int64_type) ||
401                                     (target_type == TypeManager.double_type) ||
402                                     (target_type == TypeManager.float_type) ||
403                                     (target_type == TypeManager.decimal_type))
404                                         return true;
405                                     
406                         } else if (expr_type == TypeManager.int32_type){
407                                 //
408                                 // From int to long, float, double
409                                 //
410                                 if ((target_type == TypeManager.int64_type) ||
411                                     (target_type == TypeManager.double_type) ||
412                                     (target_type == TypeManager.float_type) ||
413                                     (target_type == TypeManager.decimal_type))
414                                         return true;
415                                         
416                         } else if (expr_type == TypeManager.uint32_type){
417                                 //
418                                 // From uint to long, ulong, float, double
419                                 //
420                                 if ((target_type == TypeManager.int64_type) ||
421                                     (target_type == TypeManager.uint64_type) ||
422                                     (target_type == TypeManager.double_type) ||
423                                     (target_type == TypeManager.float_type) ||
424                                     (target_type == TypeManager.decimal_type))
425                                         return true;
426                                         
427                         } else if ((expr_type == TypeManager.uint64_type) ||
428                                    (expr_type == TypeManager.int64_type)) {
429                                 //
430                                 // From long/ulong to float, double
431                                 //
432                                 if ((target_type == TypeManager.double_type) ||
433                                     (target_type == TypeManager.float_type) ||
434                                     (target_type == TypeManager.decimal_type))
435                                         return true;
436                                     
437                         } else if (expr_type == TypeManager.char_type){
438                                 //
439                                 // From char to ushort, int, uint, long, ulong, float, double
440                                 // 
441                                 if ((target_type == TypeManager.ushort_type) ||
442                                     (target_type == TypeManager.int32_type) ||
443                                     (target_type == TypeManager.uint32_type) ||
444                                     (target_type == TypeManager.uint64_type) ||
445                                     (target_type == TypeManager.int64_type) ||
446                                     (target_type == TypeManager.float_type) ||
447                                     (target_type == TypeManager.double_type) ||
448                                     (target_type == TypeManager.decimal_type))
449                                         return true;
450
451                         } else if (expr_type == TypeManager.float_type){
452                                 //
453                                 // float to double
454                                 //
455                                 if (target_type == TypeManager.double_type)
456                                         return true;
457                         }       
458                         
459                         return false;
460                 }
461
462                 //
463                 // Horrible, horrible.  But there is no other way we can pass the EmitContext
464                 // to the recursive definition triggered by the evaluation of a forward
465                 // expression
466                 //
467                 static EmitContext current_ec = null;
468                 
469                 /// <summary>
470                 ///  This is used to lookup the value of an enum member. If the member is undefined,
471                 ///  it attempts to define it and return its value
472                 /// </summary>
473                 public object LookupEnumValue (EmitContext ec, string name, Location loc)
474                 {
475                         
476                         object default_value = null;
477                         Constant c = null;
478
479                         default_value = member_to_value [name];
480
481                         if (default_value != null)
482                                 return default_value;
483
484                         //
485                         // This may happen if we're calling a method in System.Enum, for instance
486                         // Enum.IsDefined().
487                         //
488                         if (!defined_names.Contains (name))
489                                 return null;
490
491                         if (in_transit.Contains (name)) {
492                                 Report.Error (110, loc, "The evaluation of the constant value for `" +
493                                               Name + "." + name + "' involves a circular definition.");
494                                 return null;
495                         }
496
497                         //
498                         // So if the above doesn't happen, we have a member that is undefined
499                         // We now proceed to define it 
500                         //
501                         Expression val = this [name];
502
503                         if (val == null) {
504                                 
505                                 int idx = ordered_enums.IndexOf (name);
506
507                                 if (idx == 0)
508                                         default_value = 0;
509                                 else {
510                                         for (int i = 0; i < idx; ++i) {
511                                                 string n = (string) ordered_enums [i];
512                                                 Location m_loc = (Mono.CSharp.Location)
513                                                         member_to_location [n];
514                                                 in_transit.Add (name, true);
515
516                                                 EmitContext old_ec = current_ec;
517                                                 current_ec = ec;
518                         
519                                                 default_value = LookupEnumValue (ec, n, m_loc);
520
521                                                 current_ec = old_ec;
522                                                 
523                                                 in_transit.Remove (name);
524                                                 if (default_value == null)
525                                                         return null;
526                                         }
527                                         
528                                         default_value = GetNextDefaultValue (default_value);
529                                 }
530                                 
531                         } else {
532                                 bool old = ec.InEnumContext;
533                                 ec.InEnumContext = true;
534                                 in_transit.Add (name, true);
535
536                                 EmitContext old_ec = current_ec;
537                                 current_ec = ec;
538                                 val = val.Resolve (ec);
539                                 current_ec = old_ec;
540                                 
541                                 in_transit.Remove (name);
542                                 ec.InEnumContext = old;
543
544                                 if (val == null)
545                                         return null;
546
547                                 if (!IsValidEnumConstant (val)) {
548                                         Report.Error (
549                                                 1008, loc,
550                                                 "Type byte, sbyte, short, ushort, int, uint, long, or " +
551                                                 "ulong expected (have: " + val + ")");
552                                         return null;
553                                 }
554
555                                 c = (Constant) val;
556                                 default_value = c.GetValue ();
557
558                                 if (default_value == null) {
559                                         Error_ConstantValueCannotBeConverted (c, loc);
560                                         return null;
561                                 }
562
563                                 if (val is EnumConstant){
564                                         Type etype = TypeManager.EnumToUnderlying (c.Type);
565                                         
566                                         if (!ImplicitConversionExists (etype, UnderlyingType)){
567                                                 Convert.Error_CannotImplicitConversion (
568                                                         loc, c.Type, UnderlyingType);
569                                                 return null;
570                                         }
571                                 }
572                         }
573
574                         EnumMember em = name_to_member [name] as EnumMember;
575                         em.DefineMember (TypeBuilder);
576
577                         bool fail;
578                         default_value = TypeManager.ChangeType (default_value, UnderlyingType, out fail);
579                         if (fail){
580                                 Error_ConstantValueCannotBeConverted (c, loc);
581                                 return null;
582                         }
583
584                         em.builder.SetConstant (default_value);
585                         field_builders.Add (em.builder);
586                         member_to_value [name] = default_value;
587
588                         if (!TypeManager.RegisterFieldValue (em.builder, default_value))
589                                 return null;
590
591                         return default_value;
592                 }
593
594                 public override bool DefineMembers (TypeContainer parent)
595                 {
596                         return true;
597                 }
598                 
599                 public override bool Define (TypeContainer parent)
600                 {
601                         //
602                         // If there was an error during DefineEnum, return
603                         //
604                         if (TypeBuilder == null)
605                                 return false;
606                         
607                         EmitContext ec = new EmitContext (this, this, Location, null,
608                                                           UnderlyingType, ModFlags, false);
609
610                         
611                         object default_value = 0;
612                         
613                         
614                         foreach (string name in ordered_enums) {
615                                 //
616                                 // Have we already been defined, thanks to some cross-referencing ?
617                                 // 
618                                 if (member_to_value.Contains (name))
619                                         continue;
620                                 
621                                 Location loc = (Mono.CSharp.Location) member_to_location [name];
622
623                                 if (this [name] != null) {
624                                         default_value = LookupEnumValue (ec, name, loc);
625
626                                         if (default_value == null)
627                                                 return true;
628                                 } else {
629                                         if (name == "value__"){
630                                                 Report.Error (76, loc, "The name `value__' is reserved for enumerations");
631                                                 return false;
632                                         }
633
634                                         EnumMember em = name_to_member [name] as EnumMember;
635
636                                         em.DefineMember (TypeBuilder);
637                                         FieldBuilder fb = em.builder;
638                                         
639                                         if (default_value == null) {
640                                            Report.Error (543, loc, "Enumerator value for '" + name + "' is too large to " +
641                                                               "fit in its type");
642                                                 return false;
643                                         }
644
645                                         bool fail;
646                                         default_value = TypeManager.ChangeType (default_value, UnderlyingType, out fail);
647                                         if (fail){
648                                                 Error_ConstantValueCannotBeConverted (default_value, loc);
649                                                 return false;
650                                         }
651
652                                         fb.SetConstant (default_value);
653                                         field_builders.Add (fb);
654                                         member_to_value [name] = default_value;
655                                         
656                                         if (!TypeManager.RegisterFieldValue (fb, default_value))
657                                                 return false;
658                                 }
659
660                                 default_value = GetNextDefaultValue (default_value);
661                         }
662                         return true;
663                 }
664                         
665                 public override void Emit (TypeContainer tc)
666                 {
667                                 EmitContext ec = new EmitContext (tc, this, Location, null, null, ModFlags, false);
668
669                         if (OptAttributes != null) {
670                                 OptAttributes.Emit (ec, this);
671                         }
672
673                         foreach (EnumMember em in name_to_member.Values) {
674                                 em.Emit (ec);
675                         }
676
677                         base.Emit (tc);
678                 }
679                 
680                 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
681                 {
682                         if (!base.IsIdentifierClsCompliant (ds))
683                                 return false;
684
685                         for (int i = 1; i < ordered_enums.Count; ++i) {
686                                 string checked_name = ordered_enums [i] as string;
687                                 for (int ii = 0; ii < ordered_enums.Count; ++ii) {
688                                         if (ii == i)
689                                                 continue;
690
691                                         string enumerator_name = ordered_enums [ii] as string;
692                                         if (String.Compare (checked_name, enumerator_name, true) == 0) {
693                                                 Report.SymbolRelatedToPreviousError ((Location)member_to_location [enumerator_name], enumerator_name);
694                                                 Report.Error_T (3005, (Location)member_to_location [checked_name], GetEnumeratorName (checked_name));
695                                                 break;
696                                         }
697                                 }
698                         }
699                         return true;
700                 }
701
702                 protected override bool VerifyClsCompliance (DeclSpace ds)
703                 {
704                         if (!base.VerifyClsCompliance (ds))
705                                 return false;
706
707                         if (!AttributeTester.IsClsCompliant (UnderlyingType)) {
708                                 Report.Error_T (3009, Location, GetSignatureForError (), TypeManager.CSharpName (UnderlyingType));
709                         }
710
711                         return true;
712                 }
713                 
714                 /// <summary>
715                 /// Returns full enum name.
716                 /// </summary>
717                 string GetEnumeratorName (string valueName)
718                 {
719                         return String.Concat (Name, ".", valueName);
720                 }
721
722                 //
723                 // IMemberFinder
724                 //
725                 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
726                                                         MemberFilter filter, object criteria)
727                 {
728                         ArrayList members = new ArrayList ();
729
730                         if ((mt & MemberTypes.Field) != 0) {
731                                 if (criteria is string){
732                                         if (member_to_value [criteria] == null && current_ec != null){
733                                                 LookupEnumValue (current_ec, (string) criteria, Location.Null);
734                                         }
735                                 }
736                                 
737                                 foreach (FieldBuilder fb in field_builders)
738                                         if (filter (fb, criteria) == true)
739                                                 members.Add (fb);
740                         }
741
742                         return new MemberList (members);
743                 }
744
745                 public override MemberCache MemberCache {
746                         get {
747                                 return null;
748                         }
749                 }
750
751                 public ArrayList ValueNames {
752                         get {
753                                 return ordered_enums;
754                         }
755                 }
756
757                 // indexer
758                 public Expression this [string name] {
759                         get {
760                                 return (Expression) defined_names [name];
761                         }
762                 }
763
764                 public override AttributeTargets AttributeTargets {
765                         get {
766                                 return AttributeTargets.Enum;
767                         }
768                 }
769
770         }
771 }