2010-06-21 Atsushi Enomoto <atsushi@ximian.com>
[mcs.git] / mcs / typespec.cs
blob22278a08dacd4806887da44e02ad0cfb9f93184e
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 //
11 using System;
12 using System.Collections.Generic;
13 using System.Text;
14 using System.Linq;
16 namespace Mono.CSharp
18 public class TypeSpec : MemberSpec
20 protected Type info;
21 protected MemberCache cache;
22 protected IList<TypeSpec> ifaces;
23 TypeSpec base_type;
25 Dictionary<TypeSpec[], InflatedTypeSpec> inflated_instances;
27 public static readonly TypeSpec[] EmptyTypes = new TypeSpec[0];
29 // Reflection Emit hacking
30 static Type TypeBuilder;
31 static Type GenericTypeBuilder;
33 static TypeSpec ()
35 var assembly = typeof (object).Assembly;
36 TypeBuilder = assembly.GetType ("System.Reflection.Emit.TypeBuilder");
37 GenericTypeBuilder = assembly.GetType ("System.Reflection.MonoGenericClass");
38 if (GenericTypeBuilder == null)
39 GenericTypeBuilder = assembly.GetType ("System.Reflection.Emit.TypeBuilderInstantiation");
42 public TypeSpec (MemberKind kind, TypeSpec declaringType, ITypeDefinition definition, Type info, Modifiers modifiers)
43 : base (kind, declaringType, definition, modifiers)
45 this.declaringType = declaringType;
46 this.info = info;
48 if (definition != null && definition.TypeParametersCount > 0)
49 state |= StateFlags.IsGeneric;
52 #region Properties
54 public override int Arity {
55 get {
56 return MemberDefinition.TypeParametersCount;
60 public virtual TypeSpec BaseType {
61 get {
62 return base_type;
64 set {
65 base_type = value;
69 public virtual IList<TypeSpec> Interfaces {
70 get {
71 return ifaces;
73 set {
74 ifaces = value;
78 public bool IsArray {
79 get {
80 return Kind == MemberKind.ArrayType;
84 public bool IsAttribute {
85 get {
86 if (!IsClass)
87 return false;
89 var type = this;
90 do {
91 if (type.IsGeneric)
92 return false;
94 if (type == TypeManager.attribute_type)
95 return true;
97 type = type.base_type;
98 } while (type != null);
100 return false;
104 public bool IsInterface {
105 get {
106 return Kind == MemberKind.Interface;
110 public bool IsClass {
111 get {
112 return Kind == MemberKind.Class;
116 public bool IsConstantCompatible {
117 get {
118 if ((Kind & (MemberKind.Enum | MemberKind.Class | MemberKind.Interface | MemberKind.Delegate | MemberKind.ArrayType)) != 0)
119 return true;
121 return TypeManager.IsPrimitiveType (this) || this == TypeManager.decimal_type || this == InternalType.Dynamic;
125 public bool IsDelegate {
126 get {
127 return Kind == MemberKind.Delegate;
131 public bool IsEnum {
132 get { return Kind == MemberKind.Enum; }
135 // TODO: Should probably do
136 // IsGenericType -- recursive
137 // HasTypeParameter -- non-recursive
138 public bool IsGenericOrParentIsGeneric {
139 get {
140 var ts = this;
141 do {
142 if (ts.IsGeneric)
143 return true;
144 ts = ts.declaringType;
145 } while (ts != null);
147 return false;
151 public bool IsGenericParameter {
152 get { return Kind == MemberKind.TypeParameter; }
155 public bool IsNested {
156 get { return declaringType != null && Kind != MemberKind.TypeParameter; }
159 public bool IsPointer {
160 get {
161 return Kind == MemberKind.PointerType;
165 public bool IsSealed {
166 get { return (Modifiers & Modifiers.SEALED) != 0; }
169 public bool IsStruct {
170 get {
171 return Kind == MemberKind.Struct;
175 public bool IsTypeBuilder {
176 get {
177 var meta = GetMetaInfo().GetType ();
178 return meta == TypeBuilder || meta == GenericTypeBuilder;
182 public MemberCache MemberCache {
183 get {
184 if (cache == null || (state & StateFlags.PendingMemberCacheMembers) != 0)
185 InitializeMemberCache (false);
187 return cache;
189 set {
190 if (cache != null)
191 throw new InternalErrorException ("Membercache reset");
193 cache = value;
197 public virtual MemberCache MemberCacheTypes {
198 get {
199 return MemberCache;
203 public new ITypeDefinition MemberDefinition {
204 get {
205 return (ITypeDefinition) definition;
209 // TODO: Wouldn't be better to rely on cast to InflatedTypeSpec and
210 // remove the property, YES IT WOULD !!!
211 public virtual TypeSpec[] TypeArguments {
212 get { return TypeSpec.EmptyTypes; }
215 #endregion
217 public bool AddInterface (TypeSpec iface)
219 if ((state & StateFlags.InterfacesExpanded) != 0)
220 throw new InternalErrorException ("Modifying expanded interface list");
222 if (ifaces == null) {
223 ifaces = new List<TypeSpec> () { iface };
224 return true;
227 if (!ifaces.Contains (iface)) {
228 ifaces.Add (iface);
229 return true;
232 return false;
235 public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
237 if (Kind != MemberKind.Class)
238 throw new InternalErrorException ();
240 if (!pa.IsDefined)
241 return Attribute.DefaultUsageAttribute;
243 AttributeUsageAttribute aua = null;
244 var type = this;
245 while (type != null) {
246 aua = type.MemberDefinition.GetAttributeUsage (pa);
247 if (aua != null)
248 break;
250 type = type.BaseType;
253 return aua;
256 public virtual Type GetMetaInfo ()
258 return info;
261 public virtual TypeSpec GetDefinition ()
263 return this;
266 public override string GetSignatureForError ()
268 string s;
270 if (IsNested) {
271 s = DeclaringType.GetSignatureForError ();
272 } else {
273 s = MemberDefinition.Namespace;
276 if (!string.IsNullOrEmpty (s))
277 s += ".";
279 return s + Name + GetTypeNameSignature ();
282 protected virtual string GetTypeNameSignature ()
284 if (!IsGeneric)
285 return null;
287 return "<" + TypeManager.CSharpName (MemberDefinition.TypeParameters) + ">";
290 public bool ImplementsInterface (TypeSpec iface)
292 var t = this;
293 do {
294 if (t.Interfaces != null) { // TODO: Try t.iface
295 foreach (TypeSpec i in t.Interfaces) {
296 if (i == iface || TypeSpecComparer.Variant.IsEqual (i, iface))
297 return true;
301 t = t.BaseType;
302 } while (t != null);
304 return false;
307 protected virtual void InitializeMemberCache (bool onlyTypes)
310 // Not interested in members of nested private types
312 if (IsPrivate) {
313 cache = new MemberCache (0);
314 } else {
315 cache = MemberDefinition.LoadMembers (this);
319 public override MemberSpec InflateMember (TypeParameterInflator inflator)
321 var targs = IsGeneric ? MemberDefinition.TypeParameters : TypeSpec.EmptyTypes;
324 // When inflating nested type from inside the type instance will be same
325 // because type parameters are same for all nested types
327 if (DeclaringType == inflator.TypeInstance)
328 return MakeGenericType (targs);
330 return new InflatedTypeSpec (this, inflator.TypeInstance, targs);
333 public InflatedTypeSpec MakeGenericType (TypeSpec[] targs)
335 if (targs.Length == 0 && !IsNested)
336 throw new ArgumentException ("Empty type arguments");
338 InflatedTypeSpec instance;
340 if (inflated_instances == null)
341 inflated_instances = new Dictionary<TypeSpec[], InflatedTypeSpec> (TypeSpecComparer.Default);
343 if (!inflated_instances.TryGetValue (targs, out instance)) {
344 if (GetDefinition () != this && !IsNested)
345 throw new InternalErrorException ("Only type definition or nested non-inflated types can be used to call MakeGenericType");
347 instance = new InflatedTypeSpec (this, declaringType, targs);
348 inflated_instances.Add (targs, instance);
351 return instance;
354 public virtual TypeSpec Mutate (TypeParameterMutator mutator)
356 return this;
359 public void SetMetaInfo (Type info)
361 if (this.info != null)
362 throw new InternalErrorException ("MetaInfo reset");
364 this.info = info;
367 public void SetExtensionMethodContainer ()
369 modifiers |= Modifiers.METHOD_EXTENSION;
373 public class PredefinedTypeSpec : TypeSpec
375 string name;
376 string ns;
378 public PredefinedTypeSpec (MemberKind kind, string ns, string name)
379 : base (kind, null, null, null, Modifiers.PUBLIC)
381 this.name = name;
382 this.ns = ns;
385 public override int Arity {
386 get {
387 return 0;
391 public override string Name {
392 get {
393 return name;
397 public string Namespace {
398 get {
399 return ns;
403 public override string GetSignatureForError ()
405 switch (name) {
406 case "Int32": return "int";
407 case "Int64": return "long";
408 case "String": return "string";
409 case "Boolean": return "bool";
410 case "Void": return "void";
411 case "Object": return "object";
412 case "UInt32": return "uint";
413 case "Int16": return "short";
414 case "UInt16": return "ushort";
415 case "UInt64": return "ulong";
416 case "Single": return "float";
417 case "Double": return "double";
418 case "Decimal": return "decimal";
419 case "Char": return "char";
420 case "Byte": return "byte";
421 case "SByte": return "sbyte";
424 return ns + "." + name;
427 public void SetDefinition (ITypeDefinition td, Type type)
429 this.definition = td;
430 this.info = type;
433 public void SetDefinition (TypeSpec ts)
435 this.definition = ts.MemberDefinition;
436 this.info = ts.GetMetaInfo ();
437 this.BaseType = ts.BaseType;
438 this.Interfaces = ts.Interfaces;
442 static class TypeSpecComparer
445 // Default reference comparison
447 public static readonly DefaultImpl Default = new DefaultImpl ();
449 public class DefaultImpl : IEqualityComparer<TypeSpec[]>, IEqualityComparer<Tuple<TypeSpec, TypeSpec[]>>
451 #region IEqualityComparer<TypeSpec[]> Members
453 public bool Equals (TypeSpec[] x, TypeSpec[] y)
455 if (x.Length != y.Length)
456 return false;
458 if (x == y)
459 return true;
461 for (int i = 0; i < x.Length; ++i)
462 if (x[i] != y[i])
463 return false;
465 return true;
468 public int GetHashCode (TypeSpec[] obj)
470 int hash = 0;
471 for (int i = 0; i < obj.Length; ++i)
472 hash = (hash << 5) - hash + obj[i].GetHashCode ();
474 return hash;
477 #endregion
479 #region IEqualityComparer<Tuple<TypeSpec,TypeSpec[]>> Members
481 bool IEqualityComparer<Tuple<TypeSpec, TypeSpec[]>>.Equals (Tuple<TypeSpec, TypeSpec[]> x, Tuple<TypeSpec, TypeSpec[]> y)
483 return Equals (x.Item2, y.Item2) && x.Item1 == y.Item1;
486 int IEqualityComparer<Tuple<TypeSpec, TypeSpec[]>>.GetHashCode (Tuple<TypeSpec, TypeSpec[]> obj)
488 return GetHashCode (obj.Item2) ^ obj.Item1.GetHashCode ();
491 #endregion
495 // When comparing type signature of overrides or overloads
496 // this version tolerates different MVARs at same position
498 public static class Override
500 public static bool IsEqual (TypeSpec a, TypeSpec b)
502 if (a == b)
503 return true;
506 // Consider the following example:
508 // public abstract class A
509 // {
510 // public abstract T Foo<T>();
511 // }
513 // public class B : A
514 // {
515 // public override U Foo<T>() { return default (U); }
516 // }
518 // Here, `T' and `U' are method type parameters from different methods
519 // (A.Foo and B.Foo), so both `==' and Equals() will fail.
521 // However, since we're determining whether B.Foo() overrides A.Foo(),
522 // we need to do a signature based comparision and consider them equal.
525 var tp_a = a as TypeParameterSpec;
526 if (tp_a != null) {
527 var tp_b = b as TypeParameterSpec;
528 return tp_b != null && tp_a.IsMethodOwned == tp_b.IsMethodOwned && tp_a.DeclaredPosition == tp_b.DeclaredPosition;
531 if (a.TypeArguments.Length != b.TypeArguments.Length)
532 return false;
534 if (a.TypeArguments.Length != 0) {
535 if (a.MemberDefinition != b.MemberDefinition)
536 return false;
538 for (int i = 0; i < a.TypeArguments.Length; ++i) {
539 if (!IsEqual (a.TypeArguments[i], b.TypeArguments[i]))
540 return false;
543 return true;
546 var ac_a = a as ArrayContainer;
547 if (ac_a != null) {
548 var ac_b = b as ArrayContainer;
549 return ac_b != null && ac_a.Rank == ac_b.Rank && IsEqual (ac_a.Element, ac_b.Element);
552 if (a == InternalType.Dynamic || b == InternalType.Dynamic)
553 return b == TypeManager.object_type || a == TypeManager.object_type;
555 return false;
559 // Compares unordered arrays
561 public static bool IsSame (TypeSpec[] a, TypeSpec[] b)
563 if (a == b)
564 return true;
566 if (a == null || b == null || a.Length != b.Length)
567 return false;
569 for (int ai = 0; ai < a.Length; ++ai) {
570 bool found = false;
571 for (int bi = 0; bi < b.Length; ++bi) {
572 if (IsEqual (a[ai], b[bi])) {
573 found = true;
574 break;
578 if (!found)
579 return false;
582 return true;
585 public static bool IsEqual (AParametersCollection a, AParametersCollection b)
587 if (a == b)
588 return true;
590 if (a.Count != b.Count)
591 return false;
593 for (int i = 0; i < a.Count; ++i) {
594 if (!IsEqual (a.Types[i], b.Types[i]))
595 return false;
597 const Parameter.Modifier ref_out = Parameter.Modifier.REF | Parameter.Modifier.OUT;
598 if ((a.FixedParameters[i].ModFlags & ref_out) != (b.FixedParameters[i].ModFlags & ref_out))
599 return false;
602 return true;
607 // Type variance equality comparison
609 public static class Variant
611 public static bool IsEqual (TypeSpec type1, TypeSpec type2)
613 if (!type1.IsGeneric || !type2.IsGeneric)
614 return false;
616 var target_type_def = type2.MemberDefinition;
617 if (type1.MemberDefinition != target_type_def)
618 return false;
620 var t1_targs = type1.TypeArguments;
621 var t2_targs = type2.TypeArguments;
622 var targs_definition = target_type_def.TypeParameters;
624 if (!type1.IsInterface && !type1.IsDelegate) {
626 // Internal compiler variance between G<object> and G<dynamic>
628 for (int i = 0; i < targs_definition.Length; ++i) {
629 if ((t1_targs[i] != TypeManager.object_type && t1_targs[i] != InternalType.Dynamic) ||
630 (t2_targs[i] != TypeManager.object_type && t2_targs[i] != InternalType.Dynamic))
631 return false;
634 return true;
637 for (int i = 0; i < targs_definition.Length; ++i) {
638 Variance v = targs_definition[i].Variance;
639 if (v == Variance.None) {
640 if (t1_targs[i] == t2_targs[i])
641 continue;
642 return false;
645 if (v == Variance.Covariant) {
646 if (!Convert.ImplicitReferenceConversionExists (new EmptyExpression (t1_targs[i]), t2_targs[i]))
647 return false;
648 } else if (!Convert.ImplicitReferenceConversionExists (new EmptyExpression (t2_targs[i]), t1_targs[i])) {
649 return false;
653 return true;
658 // Checks whether two generic instances may become equal for some
659 // particular instantiation (26.3.1).
661 public static class Unify
664 // Either @a or @b must be generic type
666 public static bool IsEqual (TypeSpec a, TypeSpec b)
668 if (a.MemberDefinition != b.MemberDefinition)
669 return false;
671 var ta = a.TypeArguments;
672 var tb = b.TypeArguments;
673 for (int i = 0; i < ta.Length; i++) {
674 if (!MayBecomeEqualGenericTypes (ta[i], tb[i]))
675 return false;
678 return true;
681 static bool ContainsTypeParameter (TypeSpec tparam, TypeSpec type)
683 TypeSpec[] targs = type.TypeArguments;
684 for (int i = 0; i < targs.Length; i++) {
685 if (tparam == targs[i])
686 return true;
688 if (ContainsTypeParameter (tparam, targs[i]))
689 return true;
692 return false;
695 /// <summary>
696 /// Check whether `a' and `b' may become equal generic types.
697 /// The algorithm to do that is a little bit complicated.
698 /// </summary>
699 static bool MayBecomeEqualGenericTypes (TypeSpec a, TypeSpec b)
701 if (a.IsGenericParameter) {
703 // If a is an array of a's type, they may never
704 // become equal.
706 if (b.IsArray)
707 return false;
710 // If b is a generic parameter or an actual type,
711 // they may become equal:
713 // class X<T,U> : I<T>, I<U>
714 // class X<T> : I<T>, I<float>
716 if (b.IsGenericParameter)
717 return a.DeclaringType == b.DeclaringType;
720 // We're now comparing a type parameter with a
721 // generic instance. They may become equal unless
722 // the type parameter appears anywhere in the
723 // generic instance:
725 // class X<T,U> : I<T>, I<X<U>>
726 // -> error because you could instanciate it as
727 // X<X<int>,int>
729 // class X<T> : I<T>, I<X<T>> -> ok
732 return !ContainsTypeParameter (a, b);
735 if (b.IsGenericParameter)
736 return MayBecomeEqualGenericTypes (b, a);
739 // At this point, neither a nor b are a type parameter.
741 // If one of them is a generic instance, compare them (if the
742 // other one is not a generic instance, they can never
743 // become equal).
745 if (TypeManager.IsGenericType (a) || TypeManager.IsGenericType (b))
746 return IsEqual (a, b);
749 // If both of them are arrays.
751 var a_ac = a as ArrayContainer;
752 if (a_ac != null) {
753 var b_ac = b as ArrayContainer;
754 if (b_ac == null || a_ac.Rank != b_ac.Rank)
755 return false;
757 return MayBecomeEqualGenericTypes (a_ac.Element, b_ac.Element);
761 // Ok, two ordinary types.
763 return false;
768 public interface ITypeDefinition : IMemberDefinition
770 string Namespace { get; }
771 int TypeParametersCount { get; }
772 TypeParameterSpec[] TypeParameters { get; }
774 TypeSpec GetAttributeCoClass ();
775 string GetAttributeDefaultMember ();
776 AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa);
777 MemberCache LoadMembers (TypeSpec declaringType);
780 class InternalType : TypeSpec
782 private class DynamicType : InternalType
784 public DynamicType ()
785 : base ("dynamic")
789 public override Type GetMetaInfo ()
791 return typeof (object);
795 public static readonly TypeSpec AnonymousMethod = new InternalType ("anonymous method");
796 public static readonly TypeSpec Arglist = new InternalType ("__arglist");
797 public static readonly TypeSpec Dynamic = new DynamicType ();
798 public static readonly TypeSpec MethodGroup = new InternalType ("method group");
799 public static readonly TypeSpec Null = new InternalType ("null");
800 public static readonly TypeSpec FakeInternalType = new InternalType ("<fake$type>");
802 readonly string name;
804 protected InternalType (string name)
805 : base (MemberKind.InternalCompilerType, null, null, null, Modifiers.PUBLIC)
807 this.name = name;
808 cache = MemberCache.Empty;
810 // Make all internal types CLS-compliant, non-obsolete
811 state = (state & ~(StateFlags.CLSCompliant_Undetected | StateFlags.Obsolete_Undetected)) | StateFlags.CLSCompliant;
814 public override int Arity {
815 get {
816 return 0;
820 public override string Name {
821 get {
822 return name;
826 public override string GetSignatureForError ()
828 return name;
832 public abstract class ElementTypeSpec : TypeSpec, ITypeDefinition
834 protected ElementTypeSpec (MemberKind kind, TypeSpec element, Type info)
835 : base (kind, element.DeclaringType, null, info, element.Modifiers)
837 this.Element = element;
839 // Has to use its own type definition instead of just element definition to
840 // correctly identify itself for cases like x.MemberDefininition == predefined.MemberDefinition
841 this.definition = this;
843 cache = MemberCache.Empty;
846 #region Properties
848 public TypeSpec Element { get; private set; }
850 public override string Name {
851 get {
852 throw new NotSupportedException ();
856 #endregion
858 public override ObsoleteAttribute GetAttributeObsolete ()
860 return Element.GetAttributeObsolete ();
863 protected virtual string GetPostfixSignature ()
865 return null;
868 public override string GetSignatureForError ()
870 return Element.GetSignatureForError () + GetPostfixSignature ();
873 public override TypeSpec Mutate (TypeParameterMutator mutator)
875 var me = Element.Mutate (mutator);
876 if (me == Element)
877 return this;
879 var mutated = (ElementTypeSpec) MemberwiseClone ();
880 mutated.Element = me;
881 mutated.info = null;
882 return mutated;
885 #region ITypeDefinition Members
887 System.Reflection.Assembly IMemberDefinition.Assembly {
888 get {
889 return Element.Assembly;
893 public string Namespace {
894 get { throw new NotImplementedException (); }
897 public int TypeParametersCount {
898 get {
899 return 0;
903 public TypeParameterSpec[] TypeParameters {
904 get {
905 throw new NotSupportedException ();
909 public TypeSpec GetAttributeCoClass ()
911 return Element.MemberDefinition.GetAttributeCoClass ();
914 public string GetAttributeDefaultMember ()
916 return Element.MemberDefinition.GetAttributeDefaultMember ();
919 public MemberCache LoadMembers (TypeSpec declaringType)
921 return Element.MemberDefinition.LoadMembers (declaringType);
924 public bool IsImported {
925 get {
926 return Element.MemberDefinition.IsImported;
930 public string[] ConditionalConditions ()
932 return Element.MemberDefinition.ConditionalConditions ();
935 bool IMemberDefinition.IsNotCLSCompliant ()
937 return Element.MemberDefinition.IsNotCLSCompliant ();
940 public void SetIsAssigned ()
942 Element.MemberDefinition.SetIsAssigned ();
945 public void SetIsUsed ()
947 Element.MemberDefinition.SetIsUsed ();
950 #endregion
953 public class ArrayContainer : ElementTypeSpec
955 struct TypeRankPair : IEquatable<TypeRankPair>
957 TypeSpec ts;
958 int rank;
960 public TypeRankPair (TypeSpec ts, int rank)
962 this.ts = ts;
963 this.rank = rank;
966 public override int GetHashCode ()
968 return ts.GetHashCode () ^ rank.GetHashCode ();
971 #region IEquatable<Tuple<T1,T2>> Members
973 public bool Equals (TypeRankPair other)
975 return other.ts == ts && other.rank == rank;
978 #endregion
981 readonly int rank;
982 static Dictionary<TypeRankPair, ArrayContainer> instances = new Dictionary<TypeRankPair, ArrayContainer> ();
984 private ArrayContainer (TypeSpec element, int rank)
985 : base (MemberKind.ArrayType, element, null)
987 this.rank = rank;
990 public int Rank {
991 get {
992 return rank;
996 public System.Reflection.MethodInfo GetConstructor ()
998 var mb = RootContext.ToplevelTypes.Builder;
1000 var arg_types = new Type[rank];
1001 for (int i = 0; i < rank; i++)
1002 arg_types[i] = TypeManager.int32_type.GetMetaInfo ();
1004 var ctor = mb.GetArrayMethod (
1005 GetMetaInfo (), ".ctor",
1006 System.Reflection.CallingConventions.HasThis,
1007 null, arg_types);
1009 return ctor;
1012 public System.Reflection.MethodInfo GetAddressMethod ()
1014 var mb = RootContext.ToplevelTypes.Builder;
1016 var arg_types = new Type[rank];
1017 for (int i = 0; i < rank; i++)
1018 arg_types[i] = TypeManager.int32_type.GetMetaInfo ();
1020 var address = mb.GetArrayMethod (
1021 GetMetaInfo (), "Address",
1022 System.Reflection.CallingConventions.HasThis | System.Reflection.CallingConventions.Standard,
1023 ReferenceContainer.MakeType (Element).GetMetaInfo (), arg_types);
1025 return address;
1028 public System.Reflection.MethodInfo GetGetMethod ()
1030 var mb = RootContext.ToplevelTypes.Builder;
1032 var arg_types = new Type[rank];
1033 for (int i = 0; i < rank; i++)
1034 arg_types[i] = TypeManager.int32_type.GetMetaInfo ();
1036 var get = mb.GetArrayMethod (
1037 GetMetaInfo (), "Get",
1038 System.Reflection.CallingConventions.HasThis | System.Reflection.CallingConventions.Standard,
1039 Element.GetMetaInfo (), arg_types);
1041 return get;
1044 public System.Reflection.MethodInfo GetSetMethod ()
1046 var mb = RootContext.ToplevelTypes.Builder;
1048 var arg_types = new Type[rank + 1];
1049 for (int i = 0; i < rank; i++)
1050 arg_types[i] = TypeManager.int32_type.GetMetaInfo ();
1052 arg_types[rank] = Element.GetMetaInfo ();
1054 var set = mb.GetArrayMethod (
1055 GetMetaInfo (), "Set",
1056 System.Reflection.CallingConventions.HasThis | System.Reflection.CallingConventions.Standard,
1057 TypeManager.void_type.GetMetaInfo (), arg_types);
1059 return set;
1062 public override Type GetMetaInfo ()
1064 if (info == null) {
1065 if (rank == 1)
1066 info = Element.GetMetaInfo ().MakeArrayType ();
1067 else
1068 info = Element.GetMetaInfo ().MakeArrayType (rank);
1071 return info;
1074 protected override string GetPostfixSignature()
1076 return GetPostfixSignature (rank);
1079 public static string GetPostfixSignature (int rank)
1081 StringBuilder sb = new StringBuilder ();
1082 sb.Append ("[");
1083 for (int i = 1; i < rank; i++) {
1084 sb.Append (",");
1086 sb.Append ("]");
1088 return sb.ToString ();
1091 public static ArrayContainer MakeType (TypeSpec element)
1093 return MakeType (element, 1);
1096 public static ArrayContainer MakeType (TypeSpec element, int rank)
1098 ArrayContainer ac;
1099 var key = new TypeRankPair (element, rank);
1100 if (!instances.TryGetValue (key, out ac)) {
1101 ac = new ArrayContainer (element, rank) {
1102 BaseType = TypeManager.array_type
1105 instances.Add (key, ac);
1108 return ac;
1111 public static void Reset ()
1113 instances = new Dictionary<TypeRankPair, ArrayContainer> ();
1117 class ReferenceContainer : ElementTypeSpec
1119 static Dictionary<TypeSpec, ReferenceContainer> instances = new Dictionary<TypeSpec, ReferenceContainer> ();
1121 private ReferenceContainer (TypeSpec element)
1122 : base (MemberKind.Class, element, null) // TODO: Kind.Class is most likely wrong
1126 public override Type GetMetaInfo ()
1128 if (info == null) {
1129 info = Element.GetMetaInfo ().MakeByRefType ();
1132 return info;
1135 public static ReferenceContainer MakeType (TypeSpec element)
1137 ReferenceContainer pc;
1138 if (!instances.TryGetValue (element, out pc)) {
1139 pc = new ReferenceContainer (element);
1140 instances.Add (element, pc);
1143 return pc;
1146 public static void Reset ()
1148 instances = new Dictionary<TypeSpec, ReferenceContainer> ();
1152 class PointerContainer : ElementTypeSpec
1154 static Dictionary<TypeSpec, PointerContainer> instances = new Dictionary<TypeSpec, PointerContainer> ();
1156 private PointerContainer (TypeSpec element)
1157 : base (MemberKind.PointerType, element, null)
1159 // It's never CLS-Compliant
1160 state &= ~StateFlags.CLSCompliant_Undetected;
1163 public override Type GetMetaInfo ()
1165 if (info == null) {
1166 info = Element.GetMetaInfo ().MakePointerType ();
1169 return info;
1172 protected override string GetPostfixSignature()
1174 return "*";
1177 public static PointerContainer MakeType (TypeSpec element)
1179 PointerContainer pc;
1180 if (!instances.TryGetValue (element, out pc)) {
1181 pc = new PointerContainer (element);
1182 instances.Add (element, pc);
1185 return pc;
1188 public static void Reset ()
1190 instances = new Dictionary<TypeSpec, PointerContainer> ();