[runtime] Updates comments.
[mono.git] / mcs / mcs / module.cs
1 //
2 // module.cs: keeps a tree representation of the generated code
3 //
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 //          Marek Safar  (marek.safar@gmail.com)
6 //
7 // Dual licensed under the terms of the MIT X11 or GNU GPL
8 //
9 // Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10 // Copyright 2003-2008 Novell, Inc.
11 // Copyright 2011 Xamarin Inc
12 //
13
14 using System;
15 using System.Collections.Generic;
16 using System.Runtime.InteropServices;
17 using Mono.CompilerServices.SymbolWriter;
18 using System.Linq;
19 using System.IO;
20 using System.Security.Cryptography;
21 using Mono.Security.Cryptography;
22
23 #if STATIC
24 using IKVM.Reflection;
25 using IKVM.Reflection.Emit;
26 #else
27 using System.Reflection;
28 using System.Reflection.Emit;
29 #endif
30
31 namespace Mono.CSharp
32 {
33         //
34         // Module (top-level type) container
35         //
36         public sealed class ModuleContainer : TypeContainer
37         {
38 #if STATIC
39                 //
40                 // Compiler generated container for static data
41                 //
42                 sealed class StaticDataContainer : CompilerGeneratedContainer
43                 {
44                         readonly Dictionary<int, Struct> size_types;
45                         readonly Dictionary<string, FieldSpec> data_hashes;
46
47                         public StaticDataContainer (ModuleContainer module)
48                                 : base (module, new MemberName ("<PrivateImplementationDetails>", Location.Null),
49                                         Modifiers.STATIC | Modifiers.INTERNAL)
50                         {
51                                 size_types = new Dictionary<int, Struct> ();
52                                 data_hashes = new Dictionary<string, FieldSpec> (StringComparer.Ordinal);
53                         }
54
55                         public override void CloseContainer ()
56                         {
57                                 base.CloseContainer ();
58
59                                 foreach (var entry in size_types) {
60                                         entry.Value.CloseContainer ();
61                                 }
62                         }
63
64                         public FieldSpec DefineInitializedData (byte[] data, Location loc)
65                         {
66                                 Struct size_type;
67                                 if (!size_types.TryGetValue (data.Length, out size_type)) {
68                                         //
69                                         // Build common type for this data length. We cannot use
70                                         // DefineInitializedData because it creates public type,
71                                         // and its name is not unique among modules
72                                         //
73                                         size_type = new Struct (this, new MemberName ("$ArrayType=" + data.Length, loc), Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED, null);
74                                         size_type.CreateContainer ();
75                                         size_type.DefineContainer ();
76
77                                         size_types.Add (data.Length, size_type);
78
79                                         // It has to work even if StructLayoutAttribute does not exist
80                                         size_type.TypeBuilder.__SetLayout (1, data.Length);
81                                 }
82
83                                 FieldSpec fs;
84                                 var data_hash = GenerateDataFieldName (data);
85                                 if (!data_hashes.TryGetValue (data_hash, out fs)) {
86                                         var name = "$field-" + data_hash;
87                                         const Modifiers fmod = Modifiers.STATIC | Modifiers.INTERNAL | Modifiers.READONLY;
88                                         var fbuilder = TypeBuilder.DefineField (name, size_type.CurrentType.GetMetaInfo (), ModifiersExtensions.FieldAttr (fmod) | FieldAttributes.HasFieldRVA);
89                                         fbuilder.__SetDataAndRVA (data);
90
91                                         fs = new FieldSpec (CurrentType, null, size_type.CurrentType, fbuilder, fmod);
92                                         data_hashes.Add (data_hash, fs);
93                                 }
94
95                                 return fs;
96                         }
97
98                         static string GenerateDataFieldName (byte[] bytes)
99                         {
100                                 using (var hashProvider = new SHA1CryptoServiceProvider ())
101                                 {
102                                         return CryptoConvert.ToHex (hashProvider.ComputeHash (bytes));
103                                 }
104                         }
105                 }
106
107                 StaticDataContainer static_data;
108
109                 //
110                 // Makes const data field inside internal type container
111                 //
112                 public FieldSpec MakeStaticData (byte[] data, Location loc)
113                 {
114                         if (static_data == null) {
115                                 static_data = new StaticDataContainer (this);
116                                 static_data.CreateContainer ();
117                                 static_data.DefineContainer ();
118
119                                 AddCompilerGeneratedClass (static_data);
120                         }
121
122                         return static_data.DefineInitializedData (data, loc);
123                 }
124 #endif
125
126                 public sealed class PatternMatchingHelper : CompilerGeneratedContainer
127                 {
128                         public PatternMatchingHelper (ModuleContainer module)
129                                 : base (module, new MemberName ("<PatternMatchingHelper>", Location.Null),
130                                         Modifiers.STATIC | Modifiers.INTERNAL | Modifiers.DEBUGGER_HIDDEN)
131                         {
132                         }
133
134                         public Method NumberMatcher { get; private set; }
135
136                         protected override bool DoDefineMembers ()
137                         {
138                                 if (!base.DoDefineMembers ())
139                                         return false;
140
141                                 NumberMatcher = GenerateNumberMatcher ();
142                                 return true;
143                         }
144
145                         Method GenerateNumberMatcher ()
146                         {
147                                 var loc = Location;
148                                 var parameters = ParametersCompiled.CreateFullyResolved (
149                                         new [] {
150                                                 new Parameter (new TypeExpression (Compiler.BuiltinTypes.Object, loc), "obj", 0, null, loc),
151                                                 new Parameter (new TypeExpression (Compiler.BuiltinTypes.Object, loc), "value", 0, null, loc),
152                                                 new Parameter (new TypeExpression (Compiler.BuiltinTypes.Bool, loc), "enumType", 0, null, loc),
153                                         },
154                                         new [] {
155                                                 Compiler.BuiltinTypes.Object,
156                                                 Compiler.BuiltinTypes.Object,
157                                                 Compiler.BuiltinTypes.Bool
158                                         });
159
160                                 var m = new Method (this, new TypeExpression (Compiler.BuiltinTypes.Bool, loc),
161                                         Modifiers.PUBLIC | Modifiers.STATIC | Modifiers.DEBUGGER_HIDDEN, new MemberName ("NumberMatcher", loc),
162                                         parameters, null);
163
164                                 parameters [0].Resolve (m, 0);
165                                 parameters [1].Resolve (m, 1);
166                                 parameters [2].Resolve (m, 2);
167
168                                 ToplevelBlock top_block = new ToplevelBlock (Compiler, parameters, loc);
169                                 m.Block = top_block;
170
171                                 //
172                                 // if (enumType)
173                                 //              return Equals (obj, value);
174                                 //
175                                 var equals_args = new Arguments (2);
176                                 equals_args.Add (new Argument (top_block.GetParameterReference (0, loc)));
177                                 equals_args.Add (new Argument (top_block.GetParameterReference (1, loc)));
178
179                                 var if_type = new If (
180                                                       top_block.GetParameterReference (2, loc),
181                                                       new Return (new Invocation (new SimpleName ("Equals", loc), equals_args), loc),
182                                                       loc);
183
184                                 top_block.AddStatement (if_type);
185
186                                 //
187                                 // if (obj is Enum || obj == null)
188                                 //              return false;
189                                 //
190
191                                 var if_enum = new If (
192                                                       new Binary (Binary.Operator.LogicalOr,
193                                                               new Is (top_block.GetParameterReference (0, loc), new TypeExpression (Compiler.BuiltinTypes.Enum, loc), loc),
194                                                               new Binary (Binary.Operator.Equality, top_block.GetParameterReference (0, loc), new NullLiteral (loc))),
195                                                       new Return (new BoolLiteral (Compiler.BuiltinTypes, false, loc), loc),
196                                                       loc);
197
198                                 top_block.AddStatement (if_enum);
199
200
201                                 var system_convert = new MemberAccess (new QualifiedAliasMember ("global", "System", loc), "Convert", loc);
202                                 var expl_block = new ExplicitBlock (top_block, loc, loc);
203
204                                 //
205                                 // var converted = System.Convert.ChangeType (obj, System.Convert.GetTypeCode (value));
206                                 //
207                                 var lv_converted = LocalVariable.CreateCompilerGenerated (Compiler.BuiltinTypes.Object, top_block, loc);
208
209                                 var arguments_gettypecode = new Arguments (1);
210                                 arguments_gettypecode.Add (new Argument (top_block.GetParameterReference (1, loc)));
211
212                                 var gettypecode = new Invocation (new MemberAccess (system_convert, "GetTypeCode", loc), arguments_gettypecode);
213
214                                 var arguments_changetype = new Arguments (1);
215                                 arguments_changetype.Add (new Argument (top_block.GetParameterReference (0, loc)));
216                                 arguments_changetype.Add (new Argument (gettypecode));
217
218                                 var changetype = new Invocation (new MemberAccess (system_convert, "ChangeType", loc), arguments_changetype);
219
220                                 expl_block.AddStatement (new StatementExpression (new SimpleAssign (new LocalVariableReference (lv_converted, loc), changetype, loc)));
221
222
223                                 //
224                                 // return converted.Equals (value)
225                                 //
226                                 var equals_arguments = new Arguments (1);
227                                 equals_arguments.Add (new Argument (top_block.GetParameterReference (1, loc)));
228                                 var equals_invocation = new Invocation (new MemberAccess (new LocalVariableReference (lv_converted, loc), "Equals"), equals_arguments);
229                                 expl_block.AddStatement (new Return (equals_invocation, loc));
230
231                                 var catch_block = new ExplicitBlock (top_block, loc, loc);
232                                 catch_block.AddStatement (new Return (new BoolLiteral (Compiler.BuiltinTypes, false, loc), loc));
233                                 top_block.AddStatement (new TryCatch (expl_block, new List<Catch> () {
234                                         new Catch (catch_block, loc)
235                                 }, loc, false));
236
237                                 m.Define ();
238                                 m.PrepareEmit ();
239                                 AddMember (m);
240
241                                 return m;
242                         }
243                 }
244
245                 PatternMatchingHelper pmh;
246
247                 public PatternMatchingHelper CreatePatterMatchingHelper ()
248                 {
249                         if (pmh == null) {
250                                 pmh = new PatternMatchingHelper (this);
251
252                                 pmh.CreateContainer ();
253                                 pmh.DefineContainer ();
254                                 pmh.Define ();
255                                 AddCompilerGeneratedClass (pmh);
256                         }
257
258                         return pmh;
259                 }
260
261                 public CharSet? DefaultCharSet;
262                 public TypeAttributes DefaultCharSetType = TypeAttributes.AnsiClass;
263
264                 readonly Dictionary<int, List<AnonymousTypeClass>> anonymous_types;
265                 readonly Dictionary<ArrayContainer.TypeRankPair, ArrayContainer> array_types;
266                 readonly Dictionary<TypeSpec, PointerContainer> pointer_types;
267                 readonly Dictionary<TypeSpec, ReferenceContainer> reference_types;
268                 readonly Dictionary<TypeSpec, MethodSpec> attrs_cache;
269                 readonly Dictionary<TypeSpec, AwaiterDefinition> awaiters;
270
271                 AssemblyDefinition assembly;
272                 readonly CompilerContext context;
273                 readonly RootNamespace global_ns;
274                 readonly Dictionary<string, RootNamespace> alias_ns;
275
276                 ModuleBuilder builder;
277
278                 bool has_extenstion_method;
279
280                 PredefinedAttributes predefined_attributes;
281                 PredefinedTypes predefined_types;
282                 PredefinedMembers predefined_members;
283
284                 public Binary.PredefinedOperator[] OperatorsBinaryEqualityLifted;
285                 public Binary.PredefinedOperator[] OperatorsBinaryLifted;
286
287                 static readonly string[] attribute_targets = new string[] { "assembly", "module" };
288
289                 public ModuleContainer (CompilerContext context)
290                         : base (null, MemberName.Null, null, 0)
291                 {
292                         this.context = context;
293
294                         caching_flags &= ~(Flags.Obsolete_Undetected | Flags.Excluded_Undetected);
295
296                         containers = new List<TypeContainer> ();
297                         anonymous_types = new Dictionary<int, List<AnonymousTypeClass>> ();
298                         global_ns = new GlobalRootNamespace ();
299                         alias_ns = new Dictionary<string, RootNamespace> ();
300                         array_types = new Dictionary<ArrayContainer.TypeRankPair, ArrayContainer> ();
301                         pointer_types = new Dictionary<TypeSpec, PointerContainer> ();
302                         reference_types = new Dictionary<TypeSpec, ReferenceContainer> ();
303                         attrs_cache = new Dictionary<TypeSpec, MethodSpec> ();
304                         awaiters = new Dictionary<TypeSpec, AwaiterDefinition> ();
305                 }
306
307                 #region Properties
308
309                 internal Dictionary<ArrayContainer.TypeRankPair, ArrayContainer> ArrayTypesCache {
310                         get {
311                                 return array_types;
312                         }
313                 }
314
315                 //
316                 // Cache for parameter-less attributes
317                 //
318                 internal Dictionary<TypeSpec, MethodSpec> AttributeConstructorCache {
319                         get {
320                                 return attrs_cache;
321                         }
322                 }
323
324                 public override AttributeTargets AttributeTargets {
325                         get {
326                                 return AttributeTargets.Assembly;
327                         }
328                 }
329
330                 public ModuleBuilder Builder {
331                         get {
332                                 return builder;
333                         }
334                 }
335
336                 public override CompilerContext Compiler {
337                         get {
338                                 return context;
339                         }
340                 }
341
342                 public int CounterAnonymousTypes { get; set; }
343
344                 public AssemblyDefinition DeclaringAssembly {
345                         get {
346                                 return assembly;
347                         }
348                 }
349
350                 internal DocumentationBuilder DocumentationBuilder {
351                         get; set;
352                 }
353
354                 public override string DocCommentHeader {
355                         get {
356                                 throw new NotSupportedException ();
357                         }
358                 }
359
360                 public Evaluator Evaluator {
361                         get; set;
362                 }
363
364                 public bool HasDefaultCharSet {
365                         get {
366                                 return DefaultCharSet.HasValue;
367                         }
368                 }
369
370                 public bool HasExtensionMethod {
371                         get {
372                                 return has_extenstion_method;
373                         }
374                         set {
375                                 has_extenstion_method = value;
376                         }
377                 }
378
379                 public bool HasTypesFullyDefined {
380                         get; set;
381                 }
382
383                 //
384                 // Returns module global:: namespace
385                 //
386                 public RootNamespace GlobalRootNamespace {
387                     get {
388                         return global_ns;
389                     }
390                 }
391
392                 public override ModuleContainer Module {
393                         get {
394                                 return this;
395                         }
396                 }
397
398                 internal Dictionary<TypeSpec, PointerContainer> PointerTypesCache {
399                         get {
400                                 return pointer_types;
401                         }
402                 }
403
404                 internal PredefinedAttributes PredefinedAttributes {
405                         get {
406                                 return predefined_attributes;
407                         }
408                 }
409
410                 internal PredefinedMembers PredefinedMembers {
411                         get {
412                                 return predefined_members;
413                         }
414                 }
415
416                 internal PredefinedTypes PredefinedTypes {
417                         get {
418                                 return predefined_types;
419                         }
420                 }
421
422                 internal Dictionary<TypeSpec, ReferenceContainer> ReferenceTypesCache {
423                         get {
424                                 return reference_types;
425                         }
426                 }
427
428                 public override string[] ValidAttributeTargets {
429                         get {
430                                 return attribute_targets;
431                         }
432                 }
433
434                 public Dictionary<string, string> GetResourceStrings { get; private set; }
435
436                 #endregion
437
438                 public override void Accept (StructuralVisitor visitor)
439                 {
440                         visitor.Visit (this);
441                 }
442
443                 public void AddAnonymousType (AnonymousTypeClass type)
444                 {
445                         List<AnonymousTypeClass> existing;
446                         if (!anonymous_types.TryGetValue (type.Parameters.Count, out existing))
447                         if (existing == null) {
448                                 existing = new List<AnonymousTypeClass> ();
449                                 anonymous_types.Add (type.Parameters.Count, existing);
450                         }
451
452                         existing.Add (type);
453                 }
454
455                 public void AddAttribute (Attribute attr, IMemberContext context)
456                 {
457                         attr.AttachTo (this, context);
458
459                         if (attributes == null) {
460                                 attributes = new Attributes (attr);
461                                 return;
462                         }
463
464                         attributes.AddAttribute (attr);
465                 }
466
467                 public override void AddTypeContainer (TypeContainer tc)
468                 {
469                         AddTypeContainerMember (tc);
470                 }
471
472                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
473                 {
474                         if (a.Target == AttributeTargets.Assembly) {
475                                 assembly.ApplyAttributeBuilder (a, ctor, cdata, pa);
476                                 return;
477                         }
478
479                         if (a.Type == pa.DefaultCharset) {
480                                 switch (a.GetCharSetValue ()) {
481                                 case CharSet.Ansi:
482                                 case CharSet.None:
483                                         break;
484                                 case CharSet.Auto:
485                                         DefaultCharSet = CharSet.Auto;
486                                         DefaultCharSetType = TypeAttributes.AutoClass;
487                                         break;
488                                 case CharSet.Unicode:
489                                         DefaultCharSet = CharSet.Unicode;
490                                         DefaultCharSetType = TypeAttributes.UnicodeClass;
491                                         break;
492                                 default:
493                                         Report.Error (1724, a.Location, "Value specified for the argument to `{0}' is not valid",
494                                                 a.GetSignatureForError ());
495                                         break;
496                                 }
497                         } else if (a.Type == pa.CLSCompliant) {
498                                 Attribute cls = DeclaringAssembly.CLSCompliantAttribute;
499                                 if (cls == null) {
500                                         Report.Warning (3012, 1, a.Location,
501                                                 "You must specify the CLSCompliant attribute on the assembly, not the module, to enable CLS compliance checking");
502                                 } else if (DeclaringAssembly.IsCLSCompliant != a.GetBoolean ()) {
503                                         Report.SymbolRelatedToPreviousError (cls.Location, cls.GetSignatureForError ());
504                                         Report.Warning (3017, 1, a.Location,
505                                                 "You cannot specify the CLSCompliant attribute on a module that differs from the CLSCompliant attribute on the assembly");
506                                         return;
507                                 }
508                         }
509
510                         builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
511                 }
512
513                 public override void CloseContainer ()
514                 {
515                         if (anonymous_types != null) {
516                                 foreach (var atypes in anonymous_types)
517                                         foreach (var at in atypes.Value)
518                                                 at.CloseContainer ();
519                         }
520
521                         base.CloseContainer ();
522                 }
523
524                 public TypeBuilder CreateBuilder (string name, TypeAttributes attr, int typeSize)
525                 {
526                         return builder.DefineType (name, attr, null, typeSize);
527                 }
528
529                 //
530                 // Creates alias global namespace
531                 //
532                 public RootNamespace CreateRootNamespace (string alias)
533                 {
534                         if (alias == global_ns.Alias) {
535                                 RootNamespace.Error_GlobalNamespaceRedefined (Report, Location.Null);
536                                 return global_ns;
537                         }
538
539                         RootNamespace rn;
540                         if (!alias_ns.TryGetValue (alias, out rn)) {
541                                 rn = new RootNamespace (alias);
542                                 alias_ns.Add (alias, rn);
543                         }
544
545                         return rn;
546                 }
547
548                 public void Create (AssemblyDefinition assembly, ModuleBuilder moduleBuilder)
549                 {
550                         this.assembly = assembly;
551                         builder = moduleBuilder;
552                 }
553
554                 public override bool Define ()
555                 {
556                         DefineContainer ();
557
558                         ExpandBaseInterfaces ();
559
560                         base.Define ();
561
562                         HasTypesFullyDefined = true;
563
564                         return true;
565                 }
566
567                 public override bool DefineContainer ()
568                 {
569                         DefineNamespace ();
570
571                         return base.DefineContainer ();
572                 }
573
574                 public void EnableRedefinition ()
575                 {
576                         is_defined = false;
577                 }
578
579                 public override void EmitContainer ()
580                 {
581                         if (OptAttributes != null)
582                                 OptAttributes.Emit ();
583
584                         if (Compiler.Settings.Unsafe && !assembly.IsSatelliteAssembly) {
585                                 var pa = PredefinedAttributes.UnverifiableCode;
586                                 if (pa.IsDefined)
587                                         pa.EmitAttribute (builder);
588                         }
589
590                         foreach (var tc in containers) {
591                                 tc.PrepareEmit ();
592                         }
593
594                         base.EmitContainer ();
595
596                         if (Compiler.Report.Errors == 0 && !Compiler.Settings.WriteMetadataOnly)
597                                 VerifyMembers ();
598
599                         if (anonymous_types != null) {
600                                 foreach (var atypes in anonymous_types)
601                                         foreach (var at in atypes.Value)
602                                                 at.EmitContainer ();
603                         }
604                 }
605
606                 internal override void GenerateDocComment (DocumentationBuilder builder)
607                 {
608                         foreach (var tc in containers)
609                                 tc.GenerateDocComment (builder);
610                 }
611
612                 public AnonymousTypeClass GetAnonymousType (IList<AnonymousTypeParameter> parameters)
613                 {
614                         List<AnonymousTypeClass> candidates;
615                         if (!anonymous_types.TryGetValue (parameters.Count, out candidates))
616                                 return null;
617
618                         int i;
619                         foreach (AnonymousTypeClass at in candidates) {
620                                 for (i = 0; i < parameters.Count; ++i) {
621                                         if (!parameters [i].Equals (at.Parameters [i]))
622                                                 break;
623                                 }
624
625                                 if (i == parameters.Count)
626                                         return at;
627                         }
628
629                         return null;
630                 }
631
632                 //
633                 // Return container with awaiter definition. It never returns null
634                 // but all container member can be null for easier error reporting
635                 //
636                 public AwaiterDefinition GetAwaiter (TypeSpec type)
637                 {
638                         AwaiterDefinition awaiter;
639                         if (awaiters.TryGetValue (type, out awaiter))
640                                 return awaiter;
641
642                         awaiter = new AwaiterDefinition ();
643
644                         //
645                         // Predefined: bool IsCompleted { get; } 
646                         //
647                         awaiter.IsCompleted = MemberCache.FindMember (type, MemberFilter.Property ("IsCompleted", Compiler.BuiltinTypes.Bool),
648                                 BindingRestriction.InstanceOnly) as PropertySpec;
649
650                         //
651                         // Predefined: GetResult ()
652                         //
653                         // The method return type is also result type of await expression
654                         //
655                         awaiter.GetResult = MemberCache.FindMember (type, MemberFilter.Method ("GetResult", 0,
656                                 ParametersCompiled.EmptyReadOnlyParameters, null),
657                                 BindingRestriction.InstanceOnly) as MethodSpec;
658
659                         //
660                         // Predefined: INotifyCompletion.OnCompleted (System.Action)
661                         //
662                         var nc = PredefinedTypes.INotifyCompletion;
663                         awaiter.INotifyCompletion = !nc.Define () || type.ImplementsInterface (nc.TypeSpec, false);
664
665                         awaiters.Add (type, awaiter);
666                         return awaiter;
667                 }
668
669                 public override void GetCompletionStartingWith (string prefix, List<string> results)
670                 {
671                         var names = Evaluator.GetVarNames ();
672                         results.AddRange (names.Where (l => l.StartsWith (prefix)));
673                 }
674
675                 public RootNamespace GetRootNamespace (string name)
676                 {
677                         RootNamespace rn;
678                         alias_ns.TryGetValue (name, out rn);
679                         return rn;
680                 }
681
682                 public override string GetSignatureForError ()
683                 {
684                         return "<module>";
685                 }
686
687                 public Binary.PredefinedOperator[] GetPredefinedEnumAritmeticOperators (TypeSpec enumType, bool nullable)
688                 {
689                         TypeSpec underlying;
690                         Binary.Operator mask = 0;
691
692                         if (nullable) {
693                                 underlying = Nullable.NullableInfo.GetEnumUnderlyingType (this, enumType);
694                                 mask = Binary.Operator.NullableMask;
695                         } else {
696                                 underlying = EnumSpec.GetUnderlyingType (enumType);
697                         }
698
699                         var operators = new[] {
700                                 new Binary.PredefinedOperator (enumType, underlying,
701                                         mask | Binary.Operator.AdditionMask | Binary.Operator.SubtractionMask | Binary.Operator.DecomposedMask, enumType),
702                                 new Binary.PredefinedOperator (underlying, enumType,
703                                         mask | Binary.Operator.AdditionMask | Binary.Operator.SubtractionMask | Binary.Operator.DecomposedMask, enumType),
704                                 new Binary.PredefinedOperator (enumType, mask | Binary.Operator.SubtractionMask, underlying)
705                         };
706
707                         return operators;
708                 }
709
710                 public void InitializePredefinedTypes ()
711                 {
712                         predefined_attributes = new PredefinedAttributes (this);
713                         predefined_types = new PredefinedTypes (this);
714                         predefined_members = new PredefinedMembers (this);
715
716                         OperatorsBinaryEqualityLifted = Binary.CreateEqualityLiftedOperatorsTable (this);
717                         OperatorsBinaryLifted = Binary.CreateStandardLiftedOperatorsTable (this);
718                 }
719
720                 public override bool IsClsComplianceRequired ()
721                 {
722                         return DeclaringAssembly.IsCLSCompliant;
723                 }
724
725                 public Attribute ResolveAssemblyAttribute (PredefinedAttribute a_type)
726                 {
727                         Attribute a = OptAttributes.Search ("assembly", a_type);
728                         if (a != null) {
729                                 a.Resolve ();
730                         }
731                         return a;
732                 }
733
734                 public void SetDeclaringAssembly (AssemblyDefinition assembly)
735                 {
736                         // TODO: This setter is quite ugly but I have not found a way around it yet
737                         this.assembly = assembly;
738                 }
739
740                 public void LoadGetResourceStrings (string fileName)
741                 {
742                         if (!File.Exists (fileName)) {
743                                 Report.Error (1566, "Error reading resource file `{0}'", fileName);
744                                 return;
745                         }
746
747                         foreach (var l in File.ReadLines (fileName)) {
748                                 if (GetResourceStrings == null)
749                                         GetResourceStrings = new Dictionary<string, string> ();
750
751                                 var line = l.Trim ();
752                                 if (line.Length == 0 || line [0] == '#' || line [0] == ';')
753                                         continue;
754                                 
755                                 var epos = line.IndexOf ('=');
756                                 if (epos < 0)
757                                         continue;
758
759                                 var key = line.Substring (0, epos).Trim ();
760                                 var value = line.Substring (epos + 1).Trim ();
761
762                                 GetResourceStrings [key] = value;
763                         }
764                 }
765         }
766 }