Free cookie consent management tool by TermsFeed Policy Generator

source: branches/CodeEditor/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory.CSharp-5.5.0/Parser/mcs/typespec.cs @ 11700

Last change on this file since 11700 was 11700, checked in by jkarder, 9 years ago

#2077: created branch and added first version

File size: 45.1 KB
Line 
1//
2// typespec.cs: Type specification
3//
4// Authors: Marek Safar (marek.safar@gmail.com)
5//
6// Dual licensed under the terms of the MIT X11 or GNU GPL
7//
8// Copyright 2010 Novell, Inc
9// Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
10//
11
12using System;
13using System.Collections.Generic;
14using System.Text;
15using System.Linq;
16
17#if STATIC
18using MetaType = IKVM.Reflection.Type;
19using IKVM.Reflection;
20#else
21using MetaType = System.Type;
22using System.Reflection;
23#endif
24
25namespace Mono.CSharp
26{
27  //
28  // Inflated or non-inflated representation of any type.
29  //
30  public class TypeSpec : MemberSpec
31  {
32    protected MetaType info;
33    protected MemberCache cache;
34    protected IList<TypeSpec> ifaces;
35    TypeSpec base_type;
36
37    Dictionary<TypeSpec[], InflatedTypeSpec> inflated_instances;
38
39    public static readonly TypeSpec[] EmptyTypes = new TypeSpec[0];
40
41#if !STATIC
42    // Reflection Emit hacking
43    static readonly Type TypeBuilder;
44    static readonly Type GenericTypeBuilder;
45
46    static TypeSpec ()
47    {
48      var assembly = typeof (object).Assembly;
49      TypeBuilder = assembly.GetType ("System.Reflection.Emit.TypeBuilder");
50      GenericTypeBuilder = assembly.GetType ("System.Reflection.MonoGenericClass");
51      if (GenericTypeBuilder == null)
52        GenericTypeBuilder = assembly.GetType ("System.Reflection.Emit.TypeBuilderInstantiation");
53    }
54#endif
55
56    public TypeSpec (MemberKind kind, TypeSpec declaringType, ITypeDefinition definition, MetaType info, Modifiers modifiers)
57      : base (kind, declaringType, definition, modifiers)
58    {
59      this.declaringType = declaringType;
60      this.info = info;
61
62      if (definition != null && definition.TypeParametersCount > 0)
63        state |= StateFlags.IsGeneric;
64    }
65
66    #region Properties
67
68    public override int Arity {
69      get {
70        return MemberDefinition.TypeParametersCount;
71      }
72    }
73
74    public virtual TypeSpec BaseType {
75      get {
76        return base_type;
77      }
78      set {
79        base_type = value;
80      }
81    }
82
83    public virtual BuiltinTypeSpec.Type BuiltinType {
84      get {
85        return BuiltinTypeSpec.Type.None;
86      }
87    }
88
89    public bool HasDynamicElement {
90      get {
91        return (state & StateFlags.HasDynamicElement) != 0;
92      }
93    }
94
95    //
96    // Returns a list of all interfaces including
97    // interfaces from base type or base interfaces
98    //
99    public virtual IList<TypeSpec> Interfaces {
100      get {
101        if ((state & StateFlags.InterfacesImported) == 0) {
102          state |= StateFlags.InterfacesImported;
103
104          //
105          // Delay interfaces expansion to save memory and once all
106          // base types has been imported to avoid problems where
107          // interface references type before its base was imported
108          //
109          var imported = MemberDefinition as ImportedTypeDefinition;
110          if (imported != null && Kind != MemberKind.MissingType)
111            imported.DefineInterfaces (this);
112
113        }
114
115        return ifaces;
116      }
117      set {
118        ifaces = value;
119      }
120    }
121
122    public bool IsArray {
123      get {
124        return Kind == MemberKind.ArrayType;
125      }
126    }
127
128    public bool IsAttribute {
129      get {
130        if (!IsClass)
131          return false;
132
133        var type = this;
134        do {
135          if (type.BuiltinType == BuiltinTypeSpec.Type.Attribute)
136            return true;
137
138          if (type.IsGeneric)
139            return false;
140         
141          type = type.base_type;
142        } while (type != null);
143
144        return false;
145      }
146    }
147
148    public bool IsInterface {
149      get {
150        return Kind == MemberKind.Interface;
151      }
152    }
153
154    public bool IsClass {
155      get {
156        return Kind == MemberKind.Class;
157      }
158    }
159
160    public bool IsConstantCompatible {
161      get {
162        if ((Kind & (MemberKind.Enum | MemberKind.Class | MemberKind.Interface | MemberKind.Delegate | MemberKind.ArrayType)) != 0)
163          return true;
164
165        switch (BuiltinType) {
166        case BuiltinTypeSpec.Type.Int:
167        case BuiltinTypeSpec.Type.UInt:
168        case BuiltinTypeSpec.Type.Long:
169        case BuiltinTypeSpec.Type.ULong:
170        case BuiltinTypeSpec.Type.Float:
171        case BuiltinTypeSpec.Type.Double:
172        case BuiltinTypeSpec.Type.Char:
173        case BuiltinTypeSpec.Type.Short:
174        case BuiltinTypeSpec.Type.Decimal:
175        case BuiltinTypeSpec.Type.Bool:
176        case BuiltinTypeSpec.Type.SByte:
177        case BuiltinTypeSpec.Type.Byte:
178        case BuiltinTypeSpec.Type.UShort:
179        case BuiltinTypeSpec.Type.Dynamic:
180          return true;
181        }
182
183        return false;
184      }
185    }
186
187    public bool IsDelegate {
188      get {
189        return Kind == MemberKind.Delegate;
190      }
191    }
192
193    //
194    // Returns true for instances of Expression<T>
195    //
196    public virtual bool IsExpressionTreeType {
197      get {
198        return false;
199      }
200      set {
201        state = value ? state | StateFlags.InflatedExpressionType : state & ~StateFlags.InflatedExpressionType;
202      }
203    }
204
205    public bool IsEnum {
206      get {
207        return Kind == MemberKind.Enum;
208      }
209    }
210
211    //
212    // Returns true for instances of IList<T>, IEnumerable<T>, ICollection<T>
213    //
214    public virtual bool IsArrayGenericInterface {
215      get {
216        return false;
217      }
218      set {
219        state = value ? state | StateFlags.GenericIterateInterface : state & ~StateFlags.GenericIterateInterface;
220      }
221    }
222
223    //
224    // Returns true for instances of System.Threading.Tasks.Task<T>
225    //
226    public virtual bool IsGenericTask {
227      get {
228        return false;
229      }
230      set {
231        state = value ? state | StateFlags.GenericTask : state & ~StateFlags.GenericTask;
232      }
233    }
234
235    // TODO: Should probably do
236    // IsGenericType -- recursive
237    // HasTypeParameter -- non-recursive
238    public bool IsGenericOrParentIsGeneric {
239      get {
240        var ts = this;
241        do {
242          if (ts.IsGeneric)
243            return true;
244          ts = ts.declaringType;
245        } while (ts != null);
246
247        return false;
248      }
249    }
250
251    public bool IsGenericParameter {
252      get {
253        return Kind == MemberKind.TypeParameter;
254      }
255    }
256
257    //
258    // Returns true for instances of Nullable<T>
259    //
260    public virtual bool IsNullableType {
261      get {
262        return false;
263      }
264      set {
265        state = value ? state | StateFlags.InflatedNullableType : state & ~StateFlags.InflatedNullableType;
266      }
267    }
268
269    public bool IsNested {
270      get { return declaringType != null && Kind != MemberKind.TypeParameter; }
271    }
272
273    public bool IsPointer {
274      get {
275        return Kind == MemberKind.PointerType;
276      }
277    }
278
279    public bool IsSealed {
280      get { return (Modifiers & Modifiers.SEALED) != 0; }
281    }
282
283    public bool IsSpecialRuntimeType {
284      get {
285        return (state & StateFlags.SpecialRuntimeType) != 0;
286      }
287      set {
288        state = value ? state | StateFlags.SpecialRuntimeType : state & ~StateFlags.SpecialRuntimeType;
289      }
290    }
291
292    public bool IsStruct {
293      get {
294        return Kind == MemberKind.Struct;
295      }
296    }
297
298    public bool IsStructOrEnum {
299      get {
300        return (Kind & (MemberKind.Struct | MemberKind.Enum)) != 0;
301      }
302    }
303
304    public bool IsTypeBuilder {
305      get {
306#if STATIC
307        return true;
308#else
309        var meta = GetMetaInfo().GetType ();
310        return meta == TypeBuilder || meta == GenericTypeBuilder;
311#endif
312      }
313    }
314
315    //
316    // Whether a type is unmanaged. This is used by the unsafe code
317    //
318    public bool IsUnmanaged {
319      get {
320        if (IsPointer)
321          return ((ElementTypeSpec) this).Element.IsUnmanaged;
322
323        var ds = MemberDefinition as TypeDefinition;
324        if (ds != null)
325          return ds.IsUnmanagedType ();
326
327        if (Kind == MemberKind.Void)
328          return true;
329
330        if (Kind == MemberKind.TypeParameter)
331          return false;
332
333        if (IsNested && DeclaringType.IsGenericOrParentIsGeneric)
334          return false;
335
336        return IsValueType (this);
337      }
338    }
339
340    //
341    // A cache of all type members (including nested types)
342    //
343    public MemberCache MemberCache {
344      get {
345        if (cache == null || (state & StateFlags.PendingMemberCacheMembers) != 0)
346          InitializeMemberCache (false);
347
348        return cache;
349      }
350      set {
351        if (cache != null)
352          throw new InternalErrorException ("Membercache reset");
353
354        cache = value;
355      }
356    }
357
358    public MemberCache MemberCacheTypes {
359      get {
360        if (cache == null)
361          InitializeMemberCache (true);
362
363        return cache;
364      }
365    }
366
367    public new ITypeDefinition MemberDefinition {
368      get {
369        return (ITypeDefinition) definition;
370      }
371    }
372
373    // TODO: Wouldn't be better to rely on cast to InflatedTypeSpec and
374    // remove the property, YES IT WOULD !!!
375    public virtual TypeSpec[] TypeArguments {
376      get { return TypeSpec.EmptyTypes; }
377    }
378
379    #endregion
380
381    public virtual bool AddInterface (TypeSpec iface)
382    {
383      if ((state & StateFlags.InterfacesExpanded) != 0)
384        throw new InternalErrorException ("Modifying expanded interface list");
385
386      if (ifaces == null) {
387        ifaces = new List<TypeSpec> { iface };
388        return true;
389      }
390
391      if (!ifaces.Contains (iface)) {
392        ifaces.Add (iface);
393        return true;
394      }
395
396      return false;
397    }
398
399    //
400    // Special version used during type definition
401    //
402    public bool AddInterfaceDefined (TypeSpec iface)
403    {
404      if (!AddInterface (iface))
405        return false;
406
407      //
408      // We can get into a situation where a type is inflated before
409      // its interfaces are resoved. Consider this situation
410      //
411      // class A<T> : X<A<int>>, IFoo {}
412      //
413      // When resolving base class of X`1 we inflate context type A`1
414      // All this happens before we even hit IFoo resolve. Without
415      // additional expansion any inside usage of A<T> would miss IFoo
416      // interface because it comes from early inflated A`1 definition.
417      //
418      if (inflated_instances != null) {
419        //
420        // Inflate only existing instances not any new instances added
421        // during AddInterface
422        //
423        var inflated_existing = inflated_instances.Values.ToArray ();
424        foreach (var inflated in inflated_existing) {
425          inflated.AddInterface (iface);
426        }
427      }
428
429      return true;
430    }
431
432    //
433    // Returns all type arguments, usefull for nested types
434    //
435    public static TypeSpec[] GetAllTypeArguments (TypeSpec type)
436    {
437      IList<TypeSpec> targs = TypeSpec.EmptyTypes;
438
439      do {
440        if (type.Arity > 0) {
441          if (targs.Count == 0) {
442            targs = type.TypeArguments;
443          } else {
444            var list = targs as List<TypeSpec> ?? new List<TypeSpec> (targs);
445            list.AddRange (type.TypeArguments);
446            targs = list;
447          }
448        }
449
450        type = type.declaringType;
451      } while (type != null);
452
453      return targs as TypeSpec[] ?? ((List<TypeSpec>) targs).ToArray ();
454    }
455
456    public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
457    {
458      if (Kind != MemberKind.Class)
459        throw new InternalErrorException ();
460
461      if (!pa.IsDefined)
462        return Attribute.DefaultUsageAttribute;
463
464      AttributeUsageAttribute aua = null;
465      var type = this;
466      while (type != null) {
467        aua = type.MemberDefinition.GetAttributeUsage (pa);
468        if (aua != null)
469          break;
470
471        type = type.BaseType;
472      }
473
474      return aua;
475    }
476
477    //
478    // Return metadata information used during emit to describe the type
479    //
480    public virtual MetaType GetMetaInfo ()
481    {
482      return info;
483    }
484
485    public virtual TypeSpec GetDefinition ()
486    {
487      return this;
488    }
489
490    //
491    // Text representation of type used by documentation writer
492    //
493    public override string GetSignatureForDocumentation ()
494    {
495      StringBuilder sb = new StringBuilder ();
496      if (IsNested) {
497        sb.Append (DeclaringType.GetSignatureForDocumentation ());
498      } else {
499        sb.Append (MemberDefinition.Namespace);
500      }
501
502      if (sb.Length != 0)
503        sb.Append (".");
504
505      sb.Append (Name);
506      if (Arity > 0) {
507        if (this is InflatedTypeSpec) {
508            sb.Append ("{");
509            for (int i = 0; i < Arity; ++i) {
510                if (i > 0)
511                    sb.Append (",");
512
513                sb.Append (TypeArguments[i].GetSignatureForDocumentation ());
514            }
515            sb.Append ("}");
516        } else {
517          sb.Append ("`");
518          sb.Append (Arity.ToString ());
519        }
520      }
521
522      return sb.ToString ();
523    }
524
525    public string GetExplicitNameSignatureForDocumentation ()
526    {
527      StringBuilder sb = new StringBuilder ();
528      if (IsNested) {
529        sb.Append (DeclaringType.GetExplicitNameSignatureForDocumentation ());
530      } else if (MemberDefinition.Namespace != null) {
531        sb.Append (MemberDefinition.Namespace.Replace ('.', '#'));
532      }
533
534      if (sb.Length != 0)
535        sb.Append ("#");
536
537      sb.Append (Name);
538      if (Arity > 0) {
539        sb.Append ("{");
540        for (int i = 0; i < Arity; ++i) {
541          if (i > 0)
542            sb.Append (",");
543
544          sb.Append (TypeArguments[i].GetExplicitNameSignatureForDocumentation ());
545        }
546        sb.Append ("}");
547      }
548
549      return sb.ToString ();
550    }
551
552    public override string GetSignatureForError ()
553    {
554      string s;
555
556      if (IsNested) {
557        s = DeclaringType.GetSignatureForError ();
558      } else if (MemberDefinition is AnonymousTypeClass) {
559        return ((AnonymousTypeClass) MemberDefinition).GetSignatureForError ();
560      } else {
561        s = MemberDefinition.Namespace;
562      }
563
564      if (!string.IsNullOrEmpty (s))
565        s += ".";
566
567      return s + Name + GetTypeNameSignature ();
568    }
569
570    public string GetSignatureForErrorIncludingAssemblyName ()
571    {
572      return string.Format ("{0} [{1}]", GetSignatureForError (), MemberDefinition.DeclaringAssembly.FullName);
573    }
574
575    protected virtual string GetTypeNameSignature ()
576    {
577      if (!IsGeneric)
578        return null;
579
580      return "<" + TypeManager.CSharpName (MemberDefinition.TypeParameters) + ">";
581    }
582
583    public bool ImplementsInterface (TypeSpec iface, bool variantly)
584    {
585      var ifaces = Interfaces;
586      if (ifaces != null) {
587        for (int i = 0; i < ifaces.Count; ++i) {
588          if (TypeSpecComparer.IsEqual (ifaces[i], iface))
589            return true;
590
591          if (variantly && TypeSpecComparer.Variant.IsEqual (ifaces[i], iface))
592            return true;
593        }
594      }
595
596      return false;
597    }
598
599    protected virtual void InitializeMemberCache (bool onlyTypes)
600    {
601      try {
602        MemberDefinition.LoadMembers (this, onlyTypes, ref cache);
603      } catch (Exception e) {
604        throw new InternalErrorException (e, "Unexpected error when loading type `{0}'", GetSignatureForError ());
605      }
606
607      if (onlyTypes)
608        state |= StateFlags.PendingMemberCacheMembers;
609      else
610        state &= ~StateFlags.PendingMemberCacheMembers;
611    }
612
613    //
614    // Is @baseClass base implementation of @type. With enabled @dynamicIsEqual the slower
615    // comparison is used to hide differences between `object' and `dynamic' for generic
616    // types. Should not be used for comparisons where G<object> != G<dynamic>
617    //
618    public static bool IsBaseClass (TypeSpec type, TypeSpec baseClass, bool dynamicIsObject)
619    {
620      if (dynamicIsObject && baseClass.IsGeneric) {
621        //
622        // Returns true for a hierarchies like this when passing baseClass of A<dynamic>
623        //
624        // class B : A<object> {}
625        //
626        type = type.BaseType;
627        while (type != null) {
628          if (TypeSpecComparer.IsEqual (type, baseClass))
629            return true;
630
631          type = type.BaseType;
632        }
633
634        return false;
635      }
636
637      while (type != null) {
638        type = type.BaseType;
639        if (type == baseClass)
640          return true;
641      }
642
643      return false;
644    }
645
646    public static bool IsReferenceType (TypeSpec t)
647    {
648      switch (t.Kind) {
649      case MemberKind.TypeParameter:
650        return ((TypeParameterSpec) t).IsReferenceType;
651      case MemberKind.Struct:
652      case MemberKind.Enum:
653      case MemberKind.Void:
654      case MemberKind.PointerType:
655        return false;
656      case MemberKind.InternalCompilerType:
657        //
658        // Null is considered to be a reference type
659        //     
660        return t == InternalType.NullLiteral || t.BuiltinType == BuiltinTypeSpec.Type.Dynamic;
661      default:
662        return true;
663      }
664    }
665
666    public static bool IsNonNullableValueType (TypeSpec t)
667    {
668      switch (t.Kind) {
669      case MemberKind.TypeParameter:
670        return ((TypeParameterSpec) t).IsValueType;
671      case MemberKind.Struct:
672        return !t.IsNullableType;
673      case MemberKind.Enum:
674        return true;
675      default:
676        return false;
677      }
678    }
679
680    public static bool IsValueType (TypeSpec t)
681    {
682      switch (t.Kind) {
683      case MemberKind.TypeParameter:
684        return ((TypeParameterSpec) t).IsValueType;
685      case MemberKind.Struct:
686      case MemberKind.Enum:
687        return true;
688      default:
689        return false;
690      }
691    }
692
693    public override MemberSpec InflateMember (TypeParameterInflator inflator)
694    {
695      var targs = IsGeneric ? MemberDefinition.TypeParameters : TypeSpec.EmptyTypes;
696
697      //
698      // When inflating nested type from inside the type instance will be same
699      // because type parameters are same for all nested types
700      //
701      if (DeclaringType == inflator.TypeInstance) {
702        return MakeGenericType (inflator.Context, targs);
703      }
704
705      return new InflatedTypeSpec (inflator.Context, this, inflator.TypeInstance, targs);
706    }
707
708    //
709    // Inflates current type using specific type arguments
710    //
711    public InflatedTypeSpec MakeGenericType (IModuleContext context, TypeSpec[] targs)
712    {
713      if (targs.Length == 0 && !IsNested)
714        throw new ArgumentException ("Empty type arguments for type " + GetSignatureForError ());
715
716      InflatedTypeSpec instance;
717
718      if (inflated_instances == null) {
719        inflated_instances = new Dictionary<TypeSpec[], InflatedTypeSpec> (TypeSpecComparer.Default);
720
721        if (IsNested) {
722          instance = this as InflatedTypeSpec;
723          if (instance != null) {
724            //
725            // Nested types could be inflated on already inflated instances
726            // Caching this type ensured we are using same instance for
727            // inside/outside inflation using local type parameters
728            //
729            inflated_instances.Add (TypeArguments, instance);
730          }
731        }
732      }
733
734      if (!inflated_instances.TryGetValue (targs, out instance)) {
735        if (GetDefinition () != this && !IsNested)
736          throw new InternalErrorException ("`{0}' must be type definition or nested non-inflated type to MakeGenericType",
737            GetSignatureForError ());
738
739        instance = new InflatedTypeSpec (context, this, declaringType, targs);
740        inflated_instances.Add (targs, instance);
741      }
742
743      return instance;
744    }
745
746    public virtual TypeSpec Mutate (TypeParameterMutator mutator)
747    {
748      return this;
749    }
750
751    public override List<MissingTypeSpecReference> ResolveMissingDependencies (MemberSpec caller)
752    {
753      List<MissingTypeSpecReference> missing = null;
754
755      if (Kind == MemberKind.MissingType) {
756        missing = new List<MissingTypeSpecReference> ();
757        missing.Add (new MissingTypeSpecReference (this, caller));
758        return missing;
759      }
760
761      foreach (var targ in TypeArguments) {
762        if (targ.Kind == MemberKind.MissingType) {
763          if (missing == null)
764            missing = new List<MissingTypeSpecReference> ();
765
766          missing.Add (new MissingTypeSpecReference (targ, caller));
767        }
768      }
769
770      if (Interfaces != null) {
771        foreach (var iface in Interfaces) {
772          if (iface.Kind == MemberKind.MissingType) {
773            if (missing == null)
774              missing = new List<MissingTypeSpecReference> ();
775
776            missing.Add (new MissingTypeSpecReference (iface, caller));
777          }
778        }
779      }
780
781      if (MemberDefinition.TypeParametersCount > 0) {
782        foreach (var tp in MemberDefinition.TypeParameters) {
783          var tp_missing = tp.GetMissingDependencies (this);
784          if (tp_missing != null) {
785            if (missing == null)
786              missing = new List<MissingTypeSpecReference> ();
787
788            missing.AddRange (tp_missing);
789          }
790        }
791      }
792
793      if (missing != null || BaseType == null)
794        return missing;
795
796      return BaseType.ResolveMissingDependencies (this);
797    }
798
799    public void SetMetaInfo (MetaType info)
800    {
801      if (this.info != null)
802        throw new InternalErrorException ("MetaInfo reset");
803
804      this.info = info;
805    }
806
807    public void SetExtensionMethodContainer ()
808    {
809      modifiers |= Modifiers.METHOD_EXTENSION;
810    }
811
812    public void UpdateInflatedInstancesBaseType ()
813    {
814      //
815      // When nested class has a partial part the situation where parent type
816      // is inflated before its base type is defined can occur. In such case
817      // all inflated (should be only 1) instansted need to be updated
818      //
819      // partial class A<T> {
820      //   partial class B : A<int> { }
821      // }
822      //
823      // partial class A<T> : X {}
824      //
825      if (inflated_instances == null)
826        return;
827
828      foreach (var inflated in inflated_instances) {
829        //
830        // Don't need to inflate possible generic type because for now the method
831        // is always used from within the nested type
832        //
833        inflated.Value.BaseType = base_type;
834      }
835    }
836  }
837
838  //
839  // Special version used for types which must exist in corlib or
840  // the compiler cannot work
841  //
842  public sealed class BuiltinTypeSpec : TypeSpec
843  {
844    public enum Type
845    {
846      None = 0,
847
848      // Ordered carefully for fast compares
849      FirstPrimitive = 1,
850      Bool = 1,
851      Byte = 2,
852      SByte = 3,
853      Char = 4,
854      Short = 5,
855      UShort = 6,
856      Int = 7,
857      UInt = 8,
858      Long = 9,
859      ULong = 10,
860      Float = 11,
861      Double = 12,
862      LastPrimitive = 12,
863      Decimal = 13,
864
865      IntPtr = 14,
866      UIntPtr = 15,
867
868      Object = 16,
869      Dynamic = 17,
870      String = 18,
871      Type = 19,
872
873      ValueType = 20,
874      Enum = 21,
875      Delegate = 22,
876      MulticastDelegate = 23,
877      Array = 24,
878
879      IEnumerator,
880      IEnumerable,
881      IDisposable,
882      Exception,
883      Attribute,
884      Other,
885    }
886
887    readonly Type type;
888    readonly string ns;
889    readonly string name;
890
891    public BuiltinTypeSpec (MemberKind kind, string ns, string name, Type builtinKind)
892      : base (kind, null, null, null, Modifiers.PUBLIC)
893    {
894      this.type = builtinKind;
895      this.ns = ns;
896      this.name = name;
897    }
898
899    public BuiltinTypeSpec (string name, Type builtinKind)
900      : this (MemberKind.InternalCompilerType, "", name, builtinKind)
901    {
902      // Make all internal types CLS-compliant, non-obsolete, compact
903      state = (state & ~(StateFlags.CLSCompliant_Undetected | StateFlags.Obsolete_Undetected | StateFlags.MissingDependency_Undetected)) | StateFlags.CLSCompliant;
904    }
905
906    #region Properties
907
908    public override int Arity {
909      get {
910        return 0;
911      }
912    }
913
914    public override BuiltinTypeSpec.Type BuiltinType {
915      get {
916        return type;
917      }
918    }
919
920    public string FullName {
921      get {
922        return ns + '.' + name;
923      }
924    }
925
926    public override string Name {
927      get {
928        return name;
929      }
930    }
931
932    public string Namespace {
933      get {
934        return ns;
935      }
936    }
937
938    #endregion
939
940    public static bool IsPrimitiveType (TypeSpec type)
941    {
942      return type.BuiltinType >= Type.FirstPrimitive && type.BuiltinType <= Type.LastPrimitive;
943    }
944
945    public static bool IsPrimitiveTypeOrDecimal (TypeSpec type)
946    {
947      return type.BuiltinType >= Type.FirstPrimitive && type.BuiltinType <= Type.Decimal;
948    }
949
950    public override string GetSignatureForError ()
951    {
952      switch (Name) {
953      case "Int32": return "int";
954      case "Int64": return "long";
955      case "String": return "string";
956      case "Boolean": return "bool";
957      case "Void": return "void";
958      case "Object": return "object";
959      case "UInt32": return "uint";
960      case "Int16": return "short";
961      case "UInt16": return "ushort";
962      case "UInt64": return "ulong";
963      case "Single": return "float";
964      case "Double": return "double";
965      case "Decimal": return "decimal";
966      case "Char": return "char";
967      case "Byte": return "byte";
968      case "SByte": return "sbyte";
969      }
970
971      if (ns.Length == 0)
972        return name;
973
974      return FullName;
975    }
976
977    //
978    // Returns the size of type if known, otherwise, 0
979    //
980    public static int GetSize (TypeSpec type)
981    {
982      switch (type.BuiltinType) {
983      case Type.Int:
984      case Type.UInt:
985      case Type.Float:
986        return 4;
987      case Type.Long:
988      case Type.ULong:
989      case Type.Double:
990        return 8;
991      case Type.Byte:
992      case Type.SByte:
993      case Type.Bool:
994        return 1;
995      case Type.Short:
996      case Type.Char:
997      case Type.UShort:
998        return 2;
999      case Type.Decimal:
1000        return 16;
1001      default:
1002        return 0;
1003      }
1004    }
1005
1006    public void SetDefinition (ITypeDefinition td, MetaType type, Modifiers mod)
1007    {
1008      this.definition = td;
1009      this.info = type;
1010      this.modifiers |= (mod & ~Modifiers.AccessibilityMask);
1011    }
1012
1013    public void SetDefinition (TypeSpec ts)
1014    {
1015      this.definition = ts.MemberDefinition;
1016      this.info = ts.GetMetaInfo ();
1017      this.BaseType = ts.BaseType;
1018      this.Interfaces = ts.Interfaces;
1019      this.modifiers = ts.Modifiers;
1020    }
1021  }
1022
1023  //
1024  // Various type comparers used by compiler
1025  //
1026  static class TypeSpecComparer
1027  {
1028    //
1029    // Does strict reference comparion only
1030    //
1031    public static readonly DefaultImpl Default = new DefaultImpl ();
1032
1033    public class DefaultImpl : IEqualityComparer<TypeSpec[]>
1034    {
1035      #region IEqualityComparer<TypeSpec[]> Members
1036
1037      bool IEqualityComparer<TypeSpec[]>.Equals (TypeSpec[] x, TypeSpec[] y)
1038      {
1039        if (x == y)
1040          return true;
1041
1042        if (x.Length != y.Length)
1043          return false;
1044
1045        for (int i = 0; i < x.Length; ++i)
1046          if (x[i] != y[i])
1047            return false;
1048
1049        return true;
1050      }
1051
1052      int IEqualityComparer<TypeSpec[]>.GetHashCode (TypeSpec[] obj)
1053      {
1054        int hash = 0;
1055        for (int i = 0; i < obj.Length; ++i)
1056          hash = (hash << 5) - hash + obj[i].GetHashCode ();
1057
1058        return hash;
1059      }
1060
1061      #endregion
1062    }
1063
1064    //
1065    // When comparing type signature of overrides or overloads
1066    // this version tolerates different MVARs at same position
1067    //
1068    public static class Override
1069    {
1070      public static bool IsEqual (TypeSpec a, TypeSpec b)
1071      {
1072        if (a == b)
1073          return true;
1074
1075        //
1076        // Consider the following example:
1077        //
1078        //     public abstract class A
1079        //     {
1080        //        public abstract T Foo<T>();
1081        //     }
1082        //
1083        //     public class B : A
1084        //     {
1085        //        public override U Foo<T>() { return default (U); }
1086        //     }
1087        //
1088        // Here, `T' and `U' are method type parameters from different methods
1089        // (A.Foo and B.Foo), so both `==' and Equals() will fail.
1090        //
1091        // However, since we're determining whether B.Foo() overrides A.Foo(),
1092        // we need to do a signature based comparision and consider them equal.
1093        //
1094
1095        var tp_a = a as TypeParameterSpec;
1096        if (tp_a != null) {
1097          var tp_b = b as TypeParameterSpec;
1098          return tp_b != null && tp_a.IsMethodOwned == tp_b.IsMethodOwned && tp_a.DeclaredPosition == tp_b.DeclaredPosition;
1099        }
1100
1101        var ac_a = a as ArrayContainer;
1102        if (ac_a != null) {
1103          var ac_b = b as ArrayContainer;
1104          return ac_b != null && ac_a.Rank == ac_b.Rank && IsEqual (ac_a.Element, ac_b.Element);
1105        }
1106
1107        if (a.BuiltinType == BuiltinTypeSpec.Type.Dynamic || b.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
1108          return b.BuiltinType == BuiltinTypeSpec.Type.Object || a.BuiltinType == BuiltinTypeSpec.Type.Object;
1109
1110        if (a.MemberDefinition != b.MemberDefinition)
1111          return false;
1112
1113        do {
1114          for (int i = 0; i < a.TypeArguments.Length; ++i) {
1115            if (!IsEqual (a.TypeArguments[i], b.TypeArguments[i]))
1116              return false;
1117          }
1118
1119          a = a.DeclaringType;
1120          b = b.DeclaringType;
1121        } while (a != null);
1122
1123        return true;
1124      }
1125
1126      public static bool IsEqual (TypeSpec[] a, TypeSpec[] b)
1127      {
1128        if (a == b)
1129          return true;
1130
1131        if (a.Length != b.Length)
1132          return false;
1133
1134        for (int i = 0; i < a.Length; ++i) {
1135          if (!IsEqual (a[i], b[i]))
1136            return false;
1137        }
1138
1139        return true;
1140      }
1141
1142
1143      //
1144      // Compares unordered arrays
1145      //
1146      public static bool IsSame (TypeSpec[] a, TypeSpec[] b)
1147      {
1148        if (a == b)
1149          return true;
1150
1151        if (a == null || b == null || a.Length != b.Length)
1152          return false;
1153
1154        for (int ai = 0; ai < a.Length; ++ai) {
1155          bool found = false;
1156          for (int bi = 0; bi < b.Length; ++bi) {
1157            if (IsEqual (a[ai], b[bi])) {
1158              found = true;
1159              break;
1160            }
1161          }
1162
1163          if (!found)
1164            return false;
1165        }
1166
1167        return true;
1168      }
1169
1170      public static bool IsEqual (AParametersCollection a, AParametersCollection b)
1171      {
1172        if (a == b)
1173          return true;
1174
1175        if (a.Count != b.Count)
1176          return false;
1177
1178        for (int i = 0; i < a.Count; ++i) {
1179          if (!IsEqual (a.Types[i], b.Types[i]))
1180            return false;
1181
1182          if ((a.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask) != (b.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask))
1183            return false;
1184        }
1185
1186        return true;
1187      }
1188    }
1189
1190    //
1191    // Type variance equality comparison
1192    //
1193    public static class Variant
1194    {
1195      public static bool IsEqual (TypeSpec type1, TypeSpec type2)
1196      {
1197        if (!type1.IsGeneric || !type2.IsGeneric)
1198          return false;
1199
1200        var target_type_def = type2.MemberDefinition;
1201        if (type1.MemberDefinition != target_type_def)
1202          return false;
1203
1204        var t1_targs = type1.TypeArguments;
1205        var t2_targs = type2.TypeArguments;
1206        var targs_definition = target_type_def.TypeParameters;
1207
1208        if (!type1.IsInterface && !type1.IsDelegate) {
1209          return false;
1210        }
1211
1212        for (int i = 0; i < targs_definition.Length; ++i) {
1213          if (TypeSpecComparer.IsEqual (t1_targs[i], t2_targs[i]))
1214            continue;
1215
1216          Variance v = targs_definition[i].Variance;
1217          if (v == Variance.None) {
1218            return false;
1219          }
1220
1221          if (v == Variance.Covariant) {
1222            if (!Convert.ImplicitReferenceConversionExists (t1_targs[i], t2_targs[i]))
1223              return false;
1224          } else if (!Convert.ImplicitReferenceConversionExists (t2_targs[i], t1_targs[i])) {
1225            return false;
1226          }
1227        }
1228
1229        return true;
1230      }
1231    }
1232
1233    //
1234    // Checks whether two generic instances may become equal for some
1235    // particular instantiation (26.3.1).
1236    //
1237    public static class Unify
1238    {
1239      //
1240      // Either @a or @b must be generic type
1241      //
1242      public static bool IsEqual (TypeSpec a, TypeSpec b)
1243      {
1244        if (a.MemberDefinition != b.MemberDefinition) {
1245          var base_ifaces = a.Interfaces;
1246          if (base_ifaces != null) {
1247            foreach (var base_iface in base_ifaces) {
1248              if (base_iface.Arity > 0 && IsEqual (base_iface, b))
1249                return true;
1250            }
1251          }
1252
1253          return false;
1254        }
1255
1256        var ta = a.TypeArguments;
1257        var tb = b.TypeArguments;
1258        for (int i = 0; i < ta.Length; i++) {
1259          if (!MayBecomeEqualGenericTypes (ta[i], tb[i]))
1260            return false;
1261        }
1262
1263        if (a.IsNested && b.IsNested)
1264          return IsEqual (a.DeclaringType, b.DeclaringType);
1265
1266        return true;
1267      }
1268
1269      static bool ContainsTypeParameter (TypeSpec tparam, TypeSpec type)
1270      {
1271        TypeSpec[] targs = type.TypeArguments;
1272        for (int i = 0; i < targs.Length; i++) {
1273          if (tparam == targs[i])
1274            return true;
1275
1276          if (ContainsTypeParameter (tparam, targs[i]))
1277            return true;
1278        }
1279
1280        return false;
1281      }
1282
1283      /// <summary>
1284      ///   Check whether `a' and `b' may become equal generic types.
1285      ///   The algorithm to do that is a little bit complicated.
1286      /// </summary>
1287      static bool MayBecomeEqualGenericTypes (TypeSpec a, TypeSpec b)
1288      {
1289        if (a.IsGenericParameter) {
1290          //
1291          // If a is an array of a's type, they may never
1292          // become equal.
1293          //
1294          if (b.IsArray)
1295            return false;
1296
1297          //
1298          // If b is a generic parameter or an actual type,
1299          // they may become equal:
1300          //
1301          //    class X<T,U> : I<T>, I<U>
1302          //    class X<T> : I<T>, I<float>
1303          //
1304          if (b.IsGenericParameter)
1305            return a != b && a.DeclaringType == b.DeclaringType;
1306
1307          //
1308          // We're now comparing a type parameter with a
1309          // generic instance.  They may become equal unless
1310          // the type parameter appears anywhere in the
1311          // generic instance:
1312          //
1313          //    class X<T,U> : I<T>, I<X<U>>
1314          //        -> error because you could instanciate it as
1315          //           X<X<int>,int>
1316          //
1317          //    class X<T> : I<T>, I<X<T>> -> ok
1318          //
1319
1320          return !ContainsTypeParameter (a, b);
1321        }
1322
1323        if (b.IsGenericParameter)
1324          return MayBecomeEqualGenericTypes (b, a);
1325
1326        //
1327        // At this point, neither a nor b are a type parameter.
1328        //
1329        // If one of them is a generic instance, compare them (if the
1330        // other one is not a generic instance, they can never
1331        // become equal).
1332        //
1333        if (TypeManager.IsGenericType (a) || TypeManager.IsGenericType (b))
1334          return IsEqual (a, b);
1335
1336        //
1337        // If both of them are arrays.
1338        //
1339        var a_ac = a as ArrayContainer;
1340        if (a_ac != null) {
1341          var b_ac = b as ArrayContainer;
1342          if (b_ac == null || a_ac.Rank != b_ac.Rank)
1343            return false;
1344
1345          return MayBecomeEqualGenericTypes (a_ac.Element, b_ac.Element);
1346        }
1347
1348        //
1349        // Ok, two ordinary types.
1350        //
1351        return false;
1352      }
1353    }
1354
1355    public static bool Equals (TypeSpec[] x, TypeSpec[] y)
1356    {
1357      if (x == y)
1358        return true;
1359
1360      if (x.Length != y.Length)
1361        return false;
1362
1363      for (int i = 0; i < x.Length; ++i)
1364        if (!IsEqual (x[i], y[i]))
1365          return false;
1366
1367      return true;
1368    }
1369
1370    //
1371    // Identity type conversion
1372    //
1373    // Default reference comparison, it has to be used when comparing
1374    // two possible dynamic/internal types
1375    //
1376    public static bool IsEqual (TypeSpec a, TypeSpec b)
1377    {
1378      if (a == b) {
1379        // This also rejects dynamic == dynamic
1380        return a.Kind != MemberKind.InternalCompilerType || a.BuiltinType == BuiltinTypeSpec.Type.Dynamic;
1381      }
1382
1383      if (a == null || b == null)
1384        return false;
1385
1386      if (a.IsArray) {
1387        var a_a = (ArrayContainer) a;
1388        var b_a = b as ArrayContainer;
1389        if (b_a == null)
1390          return false;
1391
1392        return a_a.Rank == b_a.Rank && IsEqual (a_a.Element, b_a.Element);
1393      }
1394
1395      if (!a.IsGeneric || !b.IsGeneric) {
1396        //
1397        // object and dynamic are considered equivalent there is an identity conversion
1398        // between object and dynamic, and between constructed types that are the same
1399        // when replacing all occurences of dynamic with object.
1400        //
1401        if (a.BuiltinType == BuiltinTypeSpec.Type.Dynamic || b.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
1402          return b.BuiltinType == BuiltinTypeSpec.Type.Object || a.BuiltinType == BuiltinTypeSpec.Type.Object;
1403
1404        return false;
1405      }
1406
1407      if (a.MemberDefinition != b.MemberDefinition)
1408        return false;
1409
1410      do {
1411        if (!Equals (a.TypeArguments, b.TypeArguments))
1412          return false;
1413
1414        a = a.DeclaringType;
1415        b = b.DeclaringType;
1416      } while (a != null);
1417
1418      return true;
1419    }
1420  }
1421
1422  public interface ITypeDefinition : IMemberDefinition
1423  {
1424    IAssemblyDefinition DeclaringAssembly { get; }
1425    string Namespace { get; }
1426    bool IsPartial { get; }
1427    bool IsComImport { get; }
1428    bool IsTypeForwarder { get; }
1429    bool IsCyclicTypeForwarder { get; }
1430    int TypeParametersCount { get; }
1431    TypeParameterSpec[] TypeParameters { get; }
1432
1433    TypeSpec GetAttributeCoClass ();
1434    string GetAttributeDefaultMember ();
1435    AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa);
1436    bool IsInternalAsPublic (IAssemblyDefinition assembly);
1437    void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache);
1438  }
1439
1440  class InternalType : TypeSpec, ITypeDefinition
1441  {
1442    public static readonly InternalType AnonymousMethod = new InternalType ("anonymous method");
1443    public static readonly InternalType Arglist = new InternalType ("__arglist");
1444    public static readonly InternalType MethodGroup = new InternalType ("method group");
1445    public static readonly InternalType NullLiteral = new InternalType ("null");
1446    public static readonly InternalType FakeInternalType = new InternalType ("<fake$type>");
1447    public static readonly InternalType Namespace = new InternalType ("<namespace>");
1448    public static readonly InternalType ErrorType = new InternalType ("<error>");
1449
1450    readonly string name;
1451
1452    InternalType (string name)
1453      : base (MemberKind.InternalCompilerType, null, null, null, Modifiers.PUBLIC)
1454    {
1455      this.name = name;
1456      this.definition = this;
1457      cache = MemberCache.Empty;
1458
1459      // Make all internal types CLS-compliant, non-obsolete
1460      state = (state & ~(StateFlags.CLSCompliant_Undetected | StateFlags.Obsolete_Undetected | StateFlags.MissingDependency_Undetected)) | StateFlags.CLSCompliant;
1461    }
1462
1463    #region Properties
1464
1465    public override int Arity {
1466      get {
1467        return 0;
1468      }
1469    }
1470
1471    IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
1472      get {
1473        throw new NotImplementedException ();
1474      }
1475    }
1476
1477    bool ITypeDefinition.IsComImport {
1478      get {
1479        return false;
1480      }
1481    }
1482
1483    bool IMemberDefinition.IsImported {
1484      get {
1485        return false;
1486      }
1487    }
1488
1489    bool ITypeDefinition.IsPartial {
1490      get {
1491        return false;
1492      }
1493    }
1494
1495    bool ITypeDefinition.IsTypeForwarder {
1496      get {
1497        return false;
1498      }
1499    }
1500
1501    bool ITypeDefinition.IsCyclicTypeForwarder {
1502      get {
1503        return false;
1504      }
1505    }
1506
1507    public override string Name {
1508      get {
1509        return name;
1510      }
1511    }
1512
1513    string ITypeDefinition.Namespace {
1514      get {
1515        return null;
1516      }
1517    }
1518
1519    int ITypeDefinition.TypeParametersCount {
1520      get {
1521        return 0;
1522      }
1523    }
1524
1525    TypeParameterSpec[] ITypeDefinition.TypeParameters {
1526      get {
1527        return null;
1528      }
1529    }
1530
1531    #endregion
1532
1533    public override string GetSignatureForError ()
1534    {
1535      return name;
1536    }
1537
1538    #region ITypeDefinition Members
1539
1540    TypeSpec ITypeDefinition.GetAttributeCoClass ()
1541    {
1542      return null;
1543    }
1544
1545    string ITypeDefinition.GetAttributeDefaultMember ()
1546    {
1547      return null;
1548    }
1549
1550    AttributeUsageAttribute ITypeDefinition.GetAttributeUsage (PredefinedAttribute pa)
1551    {
1552      return null;
1553    }
1554
1555    bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
1556    {
1557      throw new NotImplementedException ();
1558    }
1559
1560    void ITypeDefinition.LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
1561    {
1562      throw new NotImplementedException ();
1563    }
1564
1565    string[] IMemberDefinition.ConditionalConditions ()
1566    {
1567      return null;
1568    }
1569
1570    ObsoleteAttribute IMemberDefinition.GetAttributeObsolete ()
1571    {
1572      return null;
1573    }
1574
1575    bool? IMemberDefinition.CLSAttributeValue {
1576      get {
1577        return null;
1578      }
1579    }
1580
1581    void IMemberDefinition.SetIsAssigned ()
1582    {
1583    }
1584
1585    void IMemberDefinition.SetIsUsed ()
1586    {
1587    }
1588
1589    #endregion
1590  }
1591
1592  //
1593  // Common base class for composite types
1594  //
1595  public abstract class ElementTypeSpec : TypeSpec, ITypeDefinition
1596  {
1597    protected ElementTypeSpec (MemberKind kind, TypeSpec element, MetaType info)
1598      : base (kind, element.DeclaringType, null, info, element.Modifiers)
1599    {
1600      this.Element = element;
1601
1602      state &= ~SharedStateFlags;
1603      state |= (element.state & SharedStateFlags);
1604
1605      if (element.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
1606        state |= StateFlags.HasDynamicElement;
1607
1608      // Has to use its own type definition instead of just element definition to
1609      // correctly identify itself for cases like x.MemberDefininition == predefined.MemberDefinition
1610      this.definition = this;
1611
1612      cache = MemberCache.Empty;
1613    }
1614
1615    #region Properties
1616
1617    public TypeSpec Element { get; private set; }
1618
1619    bool ITypeDefinition.IsComImport {
1620      get {
1621        return false;
1622      }
1623    }
1624
1625    bool ITypeDefinition.IsPartial {
1626      get {
1627        return false;
1628      }
1629    }
1630
1631    bool ITypeDefinition.IsTypeForwarder {
1632      get {
1633        return false;
1634      }
1635    }
1636
1637    bool ITypeDefinition.IsCyclicTypeForwarder {
1638      get {
1639        return false;
1640      }
1641    }
1642
1643    public override string Name {
1644      get {
1645        throw new NotSupportedException ();
1646      }
1647    }
1648
1649    #endregion
1650
1651    public override ObsoleteAttribute GetAttributeObsolete ()
1652    {
1653      return Element.GetAttributeObsolete ();
1654    }
1655
1656    protected virtual string GetPostfixSignature ()
1657    {
1658      return null;
1659    }
1660
1661    public override string GetSignatureForDocumentation ()
1662    {
1663      return Element.GetSignatureForDocumentation () + GetPostfixSignature ();
1664    }
1665
1666    public override string GetSignatureForError ()
1667    {
1668      return Element.GetSignatureForError () + GetPostfixSignature ();
1669    }
1670
1671    public override TypeSpec Mutate (TypeParameterMutator mutator)
1672    {
1673      var me = Element.Mutate (mutator);
1674      if (me == Element)
1675        return this;
1676
1677      var mutated = (ElementTypeSpec) MemberwiseClone ();
1678      mutated.Element = me;
1679      mutated.info = null;
1680      return mutated;
1681    }
1682
1683    #region ITypeDefinition Members
1684
1685    IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
1686      get {
1687        return Element.MemberDefinition.DeclaringAssembly;
1688      }
1689    }
1690
1691    bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
1692    {
1693      return Element.MemberDefinition.IsInternalAsPublic (assembly);
1694    }
1695
1696    public string Namespace {
1697      get { throw new NotImplementedException (); }
1698    }
1699
1700    public int TypeParametersCount {
1701      get {
1702        return 0;
1703      }
1704    }
1705
1706    public TypeParameterSpec[] TypeParameters {
1707      get {
1708        throw new NotSupportedException ();
1709      }
1710    }
1711
1712    public TypeSpec GetAttributeCoClass ()
1713    {
1714      return Element.MemberDefinition.GetAttributeCoClass ();
1715    }
1716
1717    public string GetAttributeDefaultMember ()
1718    {
1719      return Element.MemberDefinition.GetAttributeDefaultMember ();
1720    }
1721
1722    public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
1723    {
1724      Element.MemberDefinition.LoadMembers (declaringType, onlyTypes, ref cache);
1725    }
1726
1727    public bool IsImported {
1728      get {
1729        return Element.MemberDefinition.IsImported;
1730      }
1731    }
1732
1733    public string[] ConditionalConditions ()
1734    {
1735      return Element.MemberDefinition.ConditionalConditions ();
1736    }
1737
1738    bool? IMemberDefinition.CLSAttributeValue {
1739      get {
1740        return Element.MemberDefinition.CLSAttributeValue;
1741      }
1742    }
1743
1744    public void SetIsAssigned ()
1745    {
1746      Element.MemberDefinition.SetIsAssigned ();
1747    }
1748
1749    public void SetIsUsed ()
1750    {
1751      Element.MemberDefinition.SetIsUsed ();
1752    }
1753
1754    #endregion
1755  }
1756
1757  public class ArrayContainer : ElementTypeSpec
1758  {
1759    public struct TypeRankPair : IEquatable<TypeRankPair>
1760    {
1761      TypeSpec ts;
1762      int rank;
1763
1764      public TypeRankPair (TypeSpec ts, int rank)
1765      {
1766        this.ts = ts;
1767        this.rank = rank;
1768      }
1769
1770      public override int GetHashCode ()
1771      {
1772        return ts.GetHashCode () ^ rank.GetHashCode ();
1773      }
1774
1775      #region IEquatable<Tuple<T1,T2>> Members
1776
1777      public bool Equals (TypeRankPair other)
1778      {
1779        return other.ts == ts && other.rank == rank;
1780      }
1781
1782      #endregion
1783    }
1784
1785    readonly int rank;
1786    readonly ModuleContainer module;
1787
1788    private ArrayContainer (ModuleContainer module, TypeSpec element, int rank)
1789      : base (MemberKind.ArrayType, element, null)
1790    {
1791      this.module = module;
1792      this.rank = rank;
1793    }
1794
1795    public int Rank {
1796      get {
1797        return rank;
1798      }
1799    }
1800
1801    public MethodInfo GetConstructor ()
1802    {
1803      var mb = module.Builder;
1804
1805      var arg_types = new MetaType[rank];
1806      for (int i = 0; i < rank; i++)
1807        arg_types[i] = module.Compiler.BuiltinTypes.Int.GetMetaInfo ();
1808
1809      var ctor = mb.GetArrayMethod (
1810        GetMetaInfo (), Constructor.ConstructorName,
1811        CallingConventions.HasThis,
1812        null, arg_types);
1813
1814      return ctor;
1815    }
1816
1817    public MethodInfo GetAddressMethod ()
1818    {
1819      var mb = module.Builder;
1820
1821      var arg_types = new MetaType[rank];
1822      for (int i = 0; i < rank; i++)
1823        arg_types[i] = module.Compiler.BuiltinTypes.Int.GetMetaInfo ();
1824
1825      var address = mb.GetArrayMethod (
1826        GetMetaInfo (), "Address",
1827        CallingConventions.HasThis | CallingConventions.Standard,
1828        ReferenceContainer.MakeType (module, Element).GetMetaInfo (), arg_types);
1829
1830      return address;
1831    }
1832
1833    public MethodInfo GetGetMethod ()
1834    {
1835      var mb = module.Builder;
1836
1837      var arg_types = new MetaType[rank];
1838      for (int i = 0; i < rank; i++)
1839        arg_types[i] = module.Compiler.BuiltinTypes.Int.GetMetaInfo ();
1840
1841      var get = mb.GetArrayMethod (
1842        GetMetaInfo (), "Get",
1843        CallingConventions.HasThis | CallingConventions.Standard,
1844        Element.GetMetaInfo (), arg_types);
1845
1846      return get;
1847    }
1848
1849    public MethodInfo GetSetMethod ()
1850    {
1851      var mb = module.Builder;
1852
1853      var arg_types = new MetaType[rank + 1];
1854      for (int i = 0; i < rank; i++)
1855        arg_types[i] = module.Compiler.BuiltinTypes.Int.GetMetaInfo ();
1856
1857      arg_types[rank] = Element.GetMetaInfo ();
1858
1859      var set = mb.GetArrayMethod (
1860        GetMetaInfo (), "Set",
1861        CallingConventions.HasThis | CallingConventions.Standard,
1862        module.Compiler.BuiltinTypes.Void.GetMetaInfo (), arg_types);
1863
1864      return set;
1865    }
1866
1867    public override MetaType GetMetaInfo ()
1868    {
1869      if (info == null) {
1870        if (rank == 1)
1871          info = Element.GetMetaInfo ().MakeArrayType ();
1872        else
1873          info = Element.GetMetaInfo ().MakeArrayType (rank);
1874      }
1875
1876      return info;
1877    }
1878
1879    protected override string GetPostfixSignature()
1880    {
1881      return GetPostfixSignature (rank);
1882    }
1883
1884    public static string GetPostfixSignature (int rank)
1885    {
1886      StringBuilder sb = new StringBuilder ();
1887      sb.Append ("[");
1888      for (int i = 1; i < rank; i++) {
1889        sb.Append (",");
1890      }
1891      sb.Append ("]");
1892
1893      return sb.ToString ();
1894    }
1895
1896    public override string GetSignatureForDocumentation ()
1897    {
1898      StringBuilder sb = new StringBuilder ();
1899      GetElementSignatureForDocumentation (sb);
1900      return sb.ToString ();
1901    }
1902
1903    void GetElementSignatureForDocumentation (StringBuilder sb)
1904    {
1905      var ac = Element as ArrayContainer;
1906      if (ac == null)
1907        sb.Append (Element.GetSignatureForDocumentation ());
1908      else
1909        ac.GetElementSignatureForDocumentation (sb);
1910
1911      sb.Append ("[");
1912      for (int i = 1; i < rank; i++) {
1913        if (i == 1)
1914          sb.Append ("0:");
1915
1916        sb.Append (",0:");
1917      }
1918      sb.Append ("]");
1919    }
1920
1921    public static ArrayContainer MakeType (ModuleContainer module, TypeSpec element)
1922    {
1923      return MakeType (module, element, 1);
1924    }
1925
1926    public static ArrayContainer MakeType (ModuleContainer module, TypeSpec element, int rank)
1927    {
1928      ArrayContainer ac;
1929      var key = new TypeRankPair (element, rank);
1930      if (!module.ArrayTypesCache.TryGetValue (key, out ac)) {
1931        ac = new ArrayContainer (module, element, rank);
1932        ac.BaseType = module.Compiler.BuiltinTypes.Array;
1933        ac.Interfaces = ac.BaseType.Interfaces;
1934
1935        module.ArrayTypesCache.Add (key, ac);
1936      }
1937
1938      return ac;
1939    }
1940
1941    public override List<MissingTypeSpecReference> ResolveMissingDependencies (MemberSpec caller)
1942    {
1943      return Element.ResolveMissingDependencies (caller);
1944    }
1945  }
1946
1947  class ReferenceContainer : ElementTypeSpec
1948  {
1949    private ReferenceContainer (TypeSpec element)
1950      : base (MemberKind.Class, element, null)  // TODO: Kind.Class is most likely wrong
1951    {
1952    }
1953
1954    public override MetaType GetMetaInfo ()
1955    {
1956      if (info == null) {
1957        info = Element.GetMetaInfo ().MakeByRefType ();
1958      }
1959
1960      return info;
1961    }
1962
1963    public static ReferenceContainer MakeType (ModuleContainer module, TypeSpec element)
1964    {
1965      ReferenceContainer pc;
1966      if (!module.ReferenceTypesCache.TryGetValue (element, out pc)) {
1967        pc = new ReferenceContainer (element);
1968        module.ReferenceTypesCache.Add (element, pc);
1969      }
1970
1971      return pc;
1972    }
1973  }
1974
1975  class PointerContainer : ElementTypeSpec
1976  {
1977    private PointerContainer (TypeSpec element)
1978      : base (MemberKind.PointerType, element, null)
1979    {
1980      // It's never CLS-Compliant
1981      state &= ~StateFlags.CLSCompliant_Undetected;
1982    }
1983
1984    public override MetaType GetMetaInfo ()
1985    {
1986      if (info == null) {
1987        info = Element.GetMetaInfo ().MakePointerType ();
1988      }
1989
1990      return info;
1991    }
1992
1993    protected override string GetPostfixSignature()
1994    {
1995      return "*";
1996    }
1997
1998    public static PointerContainer MakeType (ModuleContainer module, TypeSpec element)
1999    {
2000      PointerContainer pc;
2001      if (!module.PointerTypesCache.TryGetValue (element, out pc)) {
2002        pc = new PointerContainer (element);
2003        module.PointerTypesCache.Add (element, pc);
2004      }
2005
2006      return pc;
2007    }
2008  }
2009
2010  public class MissingTypeSpecReference
2011  {
2012    public MissingTypeSpecReference (TypeSpec type, MemberSpec caller)
2013    {
2014      Type = type;
2015      Caller = caller;
2016    }
2017
2018    public TypeSpec Type { get; private set; }
2019    public MemberSpec Caller { get; private set; }
2020  }
2021}
Note: See TracBrowser for help on using the repository browser.