2 // typespec.cs: Type specification
4 // Authors: Marek Safar (marek.safar@gmail.com)
6 // Dual licensed under the terms of the MIT X11 or GNU GPL
8 // Copyright 2010 Novell, Inc
12 using System.Collections.Generic;
14 using System.Reflection;
18 public class TypeSpec : MemberSpec
21 protected MemberCache cache;
22 protected IList<TypeSpec> ifaces;
25 Dictionary<TypeSpec[], InflatedTypeSpec> inflated_instances;
27 public static readonly TypeSpec[] EmptyTypes = new TypeSpec[0];
29 // Reflection Emit hacking
30 static readonly Type TypeBuilder;
31 static readonly Type GenericTypeBuilder;
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;
48 if (definition != null && definition.TypeParametersCount > 0)
49 state |= StateFlags.IsGeneric;
54 public override int Arity {
56 return MemberDefinition.TypeParametersCount;
60 public virtual TypeSpec BaseType {
69 public virtual BuildinTypeSpec.Type BuildinType {
71 return BuildinTypeSpec.Type.None;
75 public bool HasDynamicElement {
77 return (state & StateFlags.HasDynamicElement) != 0;
81 public virtual IList<TypeSpec> Interfaces {
92 return Kind == MemberKind.ArrayType;
96 public bool IsAttribute {
106 if (type == TypeManager.attribute_type)
109 type = type.base_type;
110 } while (type != null);
116 public bool IsInterface {
118 return Kind == MemberKind.Interface;
122 public bool IsClass {
124 return Kind == MemberKind.Class;
128 public bool IsConstantCompatible {
130 if ((Kind & (MemberKind.Enum | MemberKind.Class | MemberKind.Interface | MemberKind.Delegate | MemberKind.ArrayType)) != 0)
133 return TypeManager.IsPrimitiveType (this) || this == TypeManager.decimal_type || this == InternalType.Dynamic;
137 public bool IsDelegate {
139 return Kind == MemberKind.Delegate;
144 get { return Kind == MemberKind.Enum; }
147 // TODO: Should probably do
148 // IsGenericType -- recursive
149 // HasTypeParameter -- non-recursive
150 public bool IsGenericOrParentIsGeneric {
156 ts = ts.declaringType;
157 } while (ts != null);
163 public bool IsGenericParameter {
164 get { return Kind == MemberKind.TypeParameter; }
167 public bool IsNested {
168 get { return declaringType != null && Kind != MemberKind.TypeParameter; }
171 public bool IsPointer {
173 return Kind == MemberKind.PointerType;
177 public bool IsSealed {
178 get { return (Modifiers & Modifiers.SEALED) != 0; }
181 public bool IsStruct {
183 return Kind == MemberKind.Struct;
187 public bool IsTypeBuilder {
189 var meta = GetMetaInfo().GetType ();
190 return meta == TypeBuilder || meta == GenericTypeBuilder;
194 public MemberCache MemberCache {
196 if (cache == null || (state & StateFlags.PendingMemberCacheMembers) != 0)
197 InitializeMemberCache (false);
203 throw new InternalErrorException ("Membercache reset");
209 public MemberCache MemberCacheTypes {
212 InitializeMemberCache (true);
218 public new ITypeDefinition MemberDefinition {
220 return (ITypeDefinition) definition;
224 // TODO: Wouldn't be better to rely on cast to InflatedTypeSpec and
225 // remove the property, YES IT WOULD !!!
226 public virtual TypeSpec[] TypeArguments {
227 get { return TypeSpec.EmptyTypes; }
232 public bool AddInterface (TypeSpec iface)
234 if ((state & StateFlags.InterfacesExpanded) != 0)
235 throw new InternalErrorException ("Modifying expanded interface list");
237 if (ifaces == null) {
238 ifaces = new List<TypeSpec> () { iface };
242 if (!ifaces.Contains (iface)) {
250 public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
252 if (Kind != MemberKind.Class)
253 throw new InternalErrorException ();
256 return Attribute.DefaultUsageAttribute;
258 AttributeUsageAttribute aua = null;
260 while (type != null) {
261 aua = type.MemberDefinition.GetAttributeUsage (pa);
265 type = type.BaseType;
271 public virtual Type GetMetaInfo ()
276 public virtual TypeSpec GetDefinition ()
281 public override string GetSignatureForError ()
286 s = DeclaringType.GetSignatureForError ();
287 } else if (MemberDefinition is AnonymousTypeClass) {
288 return ((AnonymousTypeClass) MemberDefinition).GetSignatureForError ();
290 s = MemberDefinition.Namespace;
293 if (!string.IsNullOrEmpty (s))
296 return s + Name + GetTypeNameSignature ();
299 protected virtual string GetTypeNameSignature ()
304 return "<" + TypeManager.CSharpName (MemberDefinition.TypeParameters) + ">";
307 public bool ImplementsInterface (TypeSpec iface, bool variantly)
311 if (t.Interfaces != null) { // TODO: Try t.iface
312 foreach (TypeSpec i in t.Interfaces) {
313 if (i == iface || TypeSpecComparer.IsEqual (i, iface))
316 if (variantly && TypeSpecComparer.Variant.IsEqual (i, iface))
327 protected virtual void InitializeMemberCache (bool onlyTypes)
329 MemberDefinition.LoadMembers (this, onlyTypes, ref cache);
332 state |= StateFlags.PendingMemberCacheMembers;
334 state &= ~StateFlags.PendingMemberCacheMembers;
338 // Is @baseClass base implementation of @type. With enabled @dynamicIsEqual the slower
339 // comparison is used to hide differences between `object' and `dynamic' for generic
340 // types. Should not be used for comparisons where G<object> != G<dynamic>
342 public static bool IsBaseClass (TypeSpec type, TypeSpec baseClass, bool dynamicIsObject)
344 if (dynamicIsObject && baseClass.IsGeneric) {
346 // Returns true for a hierarchies like this when passing baseClass of A<dynamic>
348 // class B : A<object> {}
350 while (type != null) {
351 type = type.BaseType;
352 if (TypeSpecComparer.IsEqual (type, baseClass))
359 while (type != null) {
360 type = type.BaseType;
361 if (type == baseClass)
368 public override MemberSpec InflateMember (TypeParameterInflator inflator)
370 var targs = IsGeneric ? MemberDefinition.TypeParameters : TypeSpec.EmptyTypes;
373 // When inflating nested type from inside the type instance will be same
374 // because type parameters are same for all nested types
376 if (DeclaringType == inflator.TypeInstance) {
377 return MakeGenericType (targs);
380 return new InflatedTypeSpec (this, inflator.TypeInstance, targs);
383 public InflatedTypeSpec MakeGenericType (TypeSpec[] targs)
385 if (targs.Length == 0 && !IsNested)
386 throw new ArgumentException ("Empty type arguments for type " + GetSignatureForError ());
388 InflatedTypeSpec instance;
390 if (inflated_instances == null) {
391 inflated_instances = new Dictionary<TypeSpec[], InflatedTypeSpec> (TypeSpecComparer.Default);
394 instance = this as InflatedTypeSpec;
395 if (instance != null) {
397 // Nested types could be inflated on already inflated instances
398 // Caching this type ensured we are using same instance for
399 // inside/outside inflation using local type parameters
401 inflated_instances.Add (TypeArguments, instance);
406 if (!inflated_instances.TryGetValue (targs, out instance)) {
407 if (GetDefinition () != this && !IsNested)
408 throw new InternalErrorException ("`{0}' must be type definition or nested non-inflated type to MakeGenericType",
409 GetSignatureForError ());
411 instance = new InflatedTypeSpec (this, declaringType, targs);
412 inflated_instances.Add (targs, instance);
418 public virtual TypeSpec Mutate (TypeParameterMutator mutator)
423 public void SetMetaInfo (Type info)
425 if (this.info != null)
426 throw new InternalErrorException ("MetaInfo reset");
431 public void SetExtensionMethodContainer ()
433 modifiers |= Modifiers.METHOD_EXTENSION;
437 public sealed class BuildinTypeSpec : TypeSpec
443 // TODO: Reorder it more carefully so we can do fast compares
482 readonly string name;
484 public BuildinTypeSpec (MemberKind kind, string ns, string name, Type buildinKind)
485 : base (kind, null, null, null, Modifiers.PUBLIC)
487 if (kind == MemberKind.Struct)
488 modifiers |= Modifiers.SEALED;
490 this.type = buildinKind;
495 public BuildinTypeSpec (string name, Type buildinKind)
496 : this (MemberKind.InternalCompilerType, "", name, buildinKind)
498 // Make all internal types CLS-compliant, non-obsolete
499 state = (state & ~(StateFlags.CLSCompliant_Undetected | StateFlags.Obsolete_Undetected)) | StateFlags.CLSCompliant;
504 public override int Arity {
510 public override BuildinTypeSpec.Type BuildinType {
516 public string FullName {
518 return ns + '.' + name;
522 public override string Name {
528 public string Namespace {
536 public override string GetSignatureForError ()
539 case "Int32": return "int";
540 case "Int64": return "long";
541 case "String": return "string";
542 case "Boolean": return "bool";
543 case "Void": return "void";
544 case "Object": return "object";
545 case "UInt32": return "uint";
546 case "Int16": return "short";
547 case "UInt16": return "ushort";
548 case "UInt64": return "ulong";
549 case "Single": return "float";
550 case "Double": return "double";
551 case "Decimal": return "decimal";
552 case "Char": return "char";
553 case "Byte": return "byte";
554 case "SByte": return "sbyte";
563 public void SetDefinition (ITypeDefinition td, System.Type type)
565 this.definition = td;
569 public void SetDefinition (TypeSpec ts)
571 this.definition = ts.MemberDefinition;
572 this.info = ts.GetMetaInfo ();
573 this.BaseType = ts.BaseType;
574 this.Interfaces = ts.Interfaces;
578 static class TypeSpecComparer
581 // Does strict reference comparion only
583 public static readonly DefaultImpl Default = new DefaultImpl ();
585 public class DefaultImpl : IEqualityComparer<TypeSpec[]>
587 #region IEqualityComparer<TypeSpec[]> Members
589 bool IEqualityComparer<TypeSpec[]>.Equals (TypeSpec[] x, TypeSpec[] y)
594 if (x.Length != y.Length)
597 for (int i = 0; i < x.Length; ++i)
604 int IEqualityComparer<TypeSpec[]>.GetHashCode (TypeSpec[] obj)
607 for (int i = 0; i < obj.Length; ++i)
608 hash = (hash << 5) - hash + obj[i].GetHashCode ();
617 // When comparing type signature of overrides or overloads
618 // this version tolerates different MVARs at same position
620 public static class Override
622 public static bool IsEqual (TypeSpec a, TypeSpec b)
628 // Consider the following example:
630 // public abstract class A
632 // public abstract T Foo<T>();
635 // public class B : A
637 // public override U Foo<T>() { return default (U); }
640 // Here, `T' and `U' are method type parameters from different methods
641 // (A.Foo and B.Foo), so both `==' and Equals() will fail.
643 // However, since we're determining whether B.Foo() overrides A.Foo(),
644 // we need to do a signature based comparision and consider them equal.
647 var tp_a = a as TypeParameterSpec;
649 var tp_b = b as TypeParameterSpec;
650 return tp_b != null && tp_a.IsMethodOwned == tp_b.IsMethodOwned && tp_a.DeclaredPosition == tp_b.DeclaredPosition;
653 var ac_a = a as ArrayContainer;
655 var ac_b = b as ArrayContainer;
656 return ac_b != null && ac_a.Rank == ac_b.Rank && IsEqual (ac_a.Element, ac_b.Element);
659 if (a == InternalType.Dynamic || b == InternalType.Dynamic)
660 return b == TypeManager.object_type || a == TypeManager.object_type;
662 if (a.MemberDefinition != b.MemberDefinition)
666 for (int i = 0; i < a.TypeArguments.Length; ++i) {
667 if (!IsEqual (a.TypeArguments[i], b.TypeArguments[i]))
679 // Compares unordered arrays
681 public static bool IsSame (TypeSpec[] a, TypeSpec[] b)
686 if (a == null || b == null || a.Length != b.Length)
689 for (int ai = 0; ai < a.Length; ++ai) {
691 for (int bi = 0; bi < b.Length; ++bi) {
692 if (IsEqual (a[ai], b[bi])) {
705 public static bool IsEqual (AParametersCollection a, AParametersCollection b)
710 if (a.Count != b.Count)
713 for (int i = 0; i < a.Count; ++i) {
714 if (!IsEqual (a.Types[i], b.Types[i]))
717 const Parameter.Modifier ref_out = Parameter.Modifier.REF | Parameter.Modifier.OUT;
718 if ((a.FixedParameters[i].ModFlags & ref_out) != (b.FixedParameters[i].ModFlags & ref_out))
727 // Type variance equality comparison
729 public static class Variant
731 public static bool IsEqual (TypeSpec type1, TypeSpec type2)
733 if (!type1.IsGeneric || !type2.IsGeneric)
736 var target_type_def = type2.MemberDefinition;
737 if (type1.MemberDefinition != target_type_def)
740 var t1_targs = type1.TypeArguments;
741 var t2_targs = type2.TypeArguments;
742 var targs_definition = target_type_def.TypeParameters;
744 if (!type1.IsInterface && !type1.IsDelegate) {
748 for (int i = 0; i < targs_definition.Length; ++i) {
749 Variance v = targs_definition[i].Variance;
750 if (v == Variance.None) {
751 if (t1_targs[i] == t2_targs[i])
756 if (v == Variance.Covariant) {
757 if (!Convert.ImplicitReferenceConversionExists (new EmptyExpression (t1_targs[i]), t2_targs[i]))
759 } else if (!Convert.ImplicitReferenceConversionExists (new EmptyExpression (t2_targs[i]), t1_targs[i])) {
769 // Checks whether two generic instances may become equal for some
770 // particular instantiation (26.3.1).
772 public static class Unify
775 // Either @a or @b must be generic type
777 public static bool IsEqual (TypeSpec a, TypeSpec b)
779 if (a.MemberDefinition != b.MemberDefinition)
782 var ta = a.TypeArguments;
783 var tb = b.TypeArguments;
784 for (int i = 0; i < ta.Length; i++) {
785 if (!MayBecomeEqualGenericTypes (ta[i], tb[i]))
792 static bool ContainsTypeParameter (TypeSpec tparam, TypeSpec type)
794 TypeSpec[] targs = type.TypeArguments;
795 for (int i = 0; i < targs.Length; i++) {
796 if (tparam == targs[i])
799 if (ContainsTypeParameter (tparam, targs[i]))
807 /// Check whether `a' and `b' may become equal generic types.
808 /// The algorithm to do that is a little bit complicated.
810 static bool MayBecomeEqualGenericTypes (TypeSpec a, TypeSpec b)
812 if (a.IsGenericParameter) {
814 // If a is an array of a's type, they may never
821 // If b is a generic parameter or an actual type,
822 // they may become equal:
824 // class X<T,U> : I<T>, I<U>
825 // class X<T> : I<T>, I<float>
827 if (b.IsGenericParameter)
828 return a.DeclaringType == b.DeclaringType;
831 // We're now comparing a type parameter with a
832 // generic instance. They may become equal unless
833 // the type parameter appears anywhere in the
836 // class X<T,U> : I<T>, I<X<U>>
837 // -> error because you could instanciate it as
840 // class X<T> : I<T>, I<X<T>> -> ok
843 return !ContainsTypeParameter (a, b);
846 if (b.IsGenericParameter)
847 return MayBecomeEqualGenericTypes (b, a);
850 // At this point, neither a nor b are a type parameter.
852 // If one of them is a generic instance, compare them (if the
853 // other one is not a generic instance, they can never
856 if (TypeManager.IsGenericType (a) || TypeManager.IsGenericType (b))
857 return IsEqual (a, b);
860 // If both of them are arrays.
862 var a_ac = a as ArrayContainer;
864 var b_ac = b as ArrayContainer;
865 if (b_ac == null || a_ac.Rank != b_ac.Rank)
868 return MayBecomeEqualGenericTypes (a_ac.Element, b_ac.Element);
872 // Ok, two ordinary types.
878 public static bool Equals (TypeSpec[] x, TypeSpec[] y)
883 if (x.Length != y.Length)
886 for (int i = 0; i < x.Length; ++i)
887 if (!IsEqual (x[i], y[i]))
894 // Identity type conversion
896 // Default reference comparison, it has to be used when comparing
897 // two possible dynamic/internal types
899 public static bool IsEqual (TypeSpec a, TypeSpec b)
902 // This also rejects dynamic == dynamic
903 return a.Kind != MemberKind.InternalCompilerType || a == InternalType.Dynamic;
907 // object and dynamic are considered equivalent there is an identity conversion
908 // between object and dynamic, and between constructed types that are the same
909 // when replacing all occurences of dynamic with object.
911 if (a == InternalType.Dynamic || b == InternalType.Dynamic)
912 return b == TypeManager.object_type || a == TypeManager.object_type;
918 var a_a = (ArrayContainer) a;
919 var b_a = b as ArrayContainer;
923 return IsEqual (a_a.Element, b_a.Element) && a_a.Rank == b_a.Rank;
926 if (!a.IsGeneric || b == null || !b.IsGeneric)
929 if (a.MemberDefinition != b.MemberDefinition)
933 if (!Equals (a.TypeArguments, b.TypeArguments))
944 public interface ITypeDefinition : IMemberDefinition
946 IAssemblyDefinition DeclaringAssembly { get; }
947 string Namespace { get; }
948 int TypeParametersCount { get; }
949 TypeParameterSpec[] TypeParameters { get; }
951 TypeSpec GetAttributeCoClass ();
952 string GetAttributeDefaultMember ();
953 AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa);
954 bool IsInternalAsPublic (IAssemblyDefinition assembly);
955 void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache);
958 class InternalType : TypeSpec, ITypeDefinition
960 public static readonly InternalType AnonymousMethod = new InternalType ("anonymous method");
961 public static readonly InternalType Arglist = new InternalType ("__arglist");
962 public static BuildinTypeSpec Dynamic;
963 public static readonly InternalType MethodGroup = new InternalType ("method group");
964 public static BuildinTypeSpec Null;
965 public static readonly InternalType FakeInternalType = new InternalType ("<fake$type>");
967 readonly string name;
969 InternalType (string name, MemberCache cache)
975 InternalType (string name)
976 : base (MemberKind.InternalCompilerType, null, null, null, Modifiers.PUBLIC)
979 this.definition = this;
980 cache = MemberCache.Empty;
982 // Make all internal types CLS-compliant, non-obsolete
983 state = (state & ~(StateFlags.CLSCompliant_Undetected | StateFlags.Obsolete_Undetected)) | StateFlags.CLSCompliant;
988 public override int Arity {
994 IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
996 throw new NotImplementedException ();
1000 bool IMemberDefinition.IsImported {
1006 public override string Name {
1012 string ITypeDefinition.Namespace {
1018 int ITypeDefinition.TypeParametersCount {
1024 TypeParameterSpec[] ITypeDefinition.TypeParameters {
1032 public override string GetSignatureForError ()
1037 #region ITypeDefinition Members
1039 TypeSpec ITypeDefinition.GetAttributeCoClass ()
1044 string ITypeDefinition.GetAttributeDefaultMember ()
1049 AttributeUsageAttribute ITypeDefinition.GetAttributeUsage (PredefinedAttribute pa)
1054 bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
1056 throw new NotImplementedException ();
1059 void ITypeDefinition.LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
1061 throw new NotImplementedException ();
1064 string[] IMemberDefinition.ConditionalConditions ()
1069 ObsoleteAttribute IMemberDefinition.GetAttributeObsolete ()
1074 bool IMemberDefinition.IsNotCLSCompliant ()
1079 void IMemberDefinition.SetIsAssigned ()
1083 void IMemberDefinition.SetIsUsed ()
1090 public abstract class ElementTypeSpec : TypeSpec, ITypeDefinition
1092 protected ElementTypeSpec (MemberKind kind, TypeSpec element, Type info)
1093 : base (kind, element.DeclaringType, null, info, element.Modifiers)
1095 this.Element = element;
1097 // Some flags can be copied directly from the element
1098 const StateFlags shared_flags = StateFlags.CLSCompliant | StateFlags.CLSCompliant_Undetected
1099 | StateFlags.Obsolete | StateFlags.Obsolete_Undetected | StateFlags.HasDynamicElement;
1100 state &= ~shared_flags;
1101 state |= (element.state & shared_flags);
1103 if (element == InternalType.Dynamic)
1104 state |= StateFlags.HasDynamicElement;
1106 // Has to use its own type definition instead of just element definition to
1107 // correctly identify itself for cases like x.MemberDefininition == predefined.MemberDefinition
1108 this.definition = this;
1110 cache = MemberCache.Empty;
1115 public TypeSpec Element { get; private set; }
1117 public override string Name {
1119 throw new NotSupportedException ();
1125 public override ObsoleteAttribute GetAttributeObsolete ()
1127 return Element.GetAttributeObsolete ();
1130 protected virtual string GetPostfixSignature ()
1135 public override string GetSignatureForError ()
1137 return Element.GetSignatureForError () + GetPostfixSignature ();
1140 public override TypeSpec Mutate (TypeParameterMutator mutator)
1142 var me = Element.Mutate (mutator);
1146 var mutated = (ElementTypeSpec) MemberwiseClone ();
1147 mutated.Element = me;
1148 mutated.info = null;
1152 #region ITypeDefinition Members
1154 IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
1156 return Element.MemberDefinition.DeclaringAssembly;
1160 bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
1162 return Element.MemberDefinition.IsInternalAsPublic (assembly);
1165 public string Namespace {
1166 get { throw new NotImplementedException (); }
1169 public int TypeParametersCount {
1175 public TypeParameterSpec[] TypeParameters {
1177 throw new NotSupportedException ();
1181 public TypeSpec GetAttributeCoClass ()
1183 return Element.MemberDefinition.GetAttributeCoClass ();
1186 public string GetAttributeDefaultMember ()
1188 return Element.MemberDefinition.GetAttributeDefaultMember ();
1191 public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
1193 Element.MemberDefinition.LoadMembers (declaringType, onlyTypes, ref cache);
1196 public bool IsImported {
1198 return Element.MemberDefinition.IsImported;
1202 public string[] ConditionalConditions ()
1204 return Element.MemberDefinition.ConditionalConditions ();
1207 bool IMemberDefinition.IsNotCLSCompliant ()
1209 return Element.MemberDefinition.IsNotCLSCompliant ();
1212 public void SetIsAssigned ()
1214 Element.MemberDefinition.SetIsAssigned ();
1217 public void SetIsUsed ()
1219 Element.MemberDefinition.SetIsUsed ();
1225 public class ArrayContainer : ElementTypeSpec
1227 struct TypeRankPair : IEquatable<TypeRankPair>
1232 public TypeRankPair (TypeSpec ts, int rank)
1238 public override int GetHashCode ()
1240 return ts.GetHashCode () ^ rank.GetHashCode ();
1243 #region IEquatable<Tuple<T1,T2>> Members
1245 public bool Equals (TypeRankPair other)
1247 return other.ts == ts && other.rank == rank;
1254 static Dictionary<TypeRankPair, ArrayContainer> instances = new Dictionary<TypeRankPair, ArrayContainer> ();
1256 private ArrayContainer (TypeSpec element, int rank)
1257 : base (MemberKind.ArrayType, element, null)
1268 public MethodInfo GetConstructor ()
1270 var mb = RootContext.ToplevelTypes.Builder;
1272 var arg_types = new Type[rank];
1273 for (int i = 0; i < rank; i++)
1274 arg_types[i] = TypeManager.int32_type.GetMetaInfo ();
1276 var ctor = mb.GetArrayMethod (
1277 GetMetaInfo (), Constructor.ConstructorName,
1278 CallingConventions.HasThis,
1284 public MethodInfo GetAddressMethod ()
1286 var mb = RootContext.ToplevelTypes.Builder;
1288 var arg_types = new Type[rank];
1289 for (int i = 0; i < rank; i++)
1290 arg_types[i] = TypeManager.int32_type.GetMetaInfo ();
1292 var address = mb.GetArrayMethod (
1293 GetMetaInfo (), "Address",
1294 CallingConventions.HasThis | CallingConventions.Standard,
1295 ReferenceContainer.MakeType (Element).GetMetaInfo (), arg_types);
1300 public MethodInfo GetGetMethod ()
1302 var mb = RootContext.ToplevelTypes.Builder;
1304 var arg_types = new Type[rank];
1305 for (int i = 0; i < rank; i++)
1306 arg_types[i] = TypeManager.int32_type.GetMetaInfo ();
1308 var get = mb.GetArrayMethod (
1309 GetMetaInfo (), "Get",
1310 CallingConventions.HasThis | CallingConventions.Standard,
1311 Element.GetMetaInfo (), arg_types);
1316 public MethodInfo GetSetMethod ()
1318 var mb = RootContext.ToplevelTypes.Builder;
1320 var arg_types = new Type[rank + 1];
1321 for (int i = 0; i < rank; i++)
1322 arg_types[i] = TypeManager.int32_type.GetMetaInfo ();
1324 arg_types[rank] = Element.GetMetaInfo ();
1326 var set = mb.GetArrayMethod (
1327 GetMetaInfo (), "Set",
1328 CallingConventions.HasThis | CallingConventions.Standard,
1329 TypeManager.void_type.GetMetaInfo (), arg_types);
1334 public override Type GetMetaInfo ()
1338 info = Element.GetMetaInfo ().MakeArrayType ();
1340 info = Element.GetMetaInfo ().MakeArrayType (rank);
1346 protected override string GetPostfixSignature()
1348 return GetPostfixSignature (rank);
1351 public static string GetPostfixSignature (int rank)
1353 StringBuilder sb = new StringBuilder ();
1355 for (int i = 1; i < rank; i++) {
1360 return sb.ToString ();
1363 public static ArrayContainer MakeType (TypeSpec element)
1365 return MakeType (element, 1);
1368 public static ArrayContainer MakeType (TypeSpec element, int rank)
1371 var key = new TypeRankPair (element, rank);
1372 if (!instances.TryGetValue (key, out ac)) {
1373 ac = new ArrayContainer (element, rank) {
1374 BaseType = TypeManager.array_type
1377 instances.Add (key, ac);
1383 public static void Reset ()
1385 instances = new Dictionary<TypeRankPair, ArrayContainer> ();
1389 class ReferenceContainer : ElementTypeSpec
1391 static Dictionary<TypeSpec, ReferenceContainer> instances = new Dictionary<TypeSpec, ReferenceContainer> ();
1393 private ReferenceContainer (TypeSpec element)
1394 : base (MemberKind.Class, element, null) // TODO: Kind.Class is most likely wrong
1398 public override Type GetMetaInfo ()
1401 info = Element.GetMetaInfo ().MakeByRefType ();
1407 public static ReferenceContainer MakeType (TypeSpec element)
1409 ReferenceContainer pc;
1410 if (!instances.TryGetValue (element, out pc)) {
1411 pc = new ReferenceContainer (element);
1412 instances.Add (element, pc);
1418 public static void Reset ()
1420 instances = new Dictionary<TypeSpec, ReferenceContainer> ();
1424 class PointerContainer : ElementTypeSpec
1426 static Dictionary<TypeSpec, PointerContainer> instances = new Dictionary<TypeSpec, PointerContainer> ();
1428 private PointerContainer (TypeSpec element)
1429 : base (MemberKind.PointerType, element, null)
1431 // It's never CLS-Compliant
1432 state &= ~StateFlags.CLSCompliant_Undetected;
1435 public override Type GetMetaInfo ()
1438 info = Element.GetMetaInfo ().MakePointerType ();
1444 protected override string GetPostfixSignature()
1449 public static PointerContainer MakeType (TypeSpec element)
1451 PointerContainer pc;
1452 if (!instances.TryGetValue (element, out pc)) {
1453 pc = new PointerContainer (element);
1454 instances.Add (element, pc);
1460 public static void Reset ()
1462 instances = new Dictionary<TypeSpec, PointerContainer> ();