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;
16 using MetaType = IKVM.Reflection.Type;
17 using IKVM.Reflection;
19 using MetaType = System.Type;
20 using System.Reflection;
25 public class TypeSpec : MemberSpec
27 protected MetaType info;
28 protected MemberCache cache;
29 protected IList<TypeSpec> ifaces;
32 Dictionary<TypeSpec[], InflatedTypeSpec> inflated_instances;
34 public static readonly TypeSpec[] EmptyTypes = new TypeSpec[0];
37 // Reflection Emit hacking
38 static readonly Type TypeBuilder;
39 static readonly Type GenericTypeBuilder;
43 var assembly = typeof (object).Assembly;
44 TypeBuilder = assembly.GetType ("System.Reflection.Emit.TypeBuilder");
45 GenericTypeBuilder = assembly.GetType ("System.Reflection.MonoGenericClass");
46 if (GenericTypeBuilder == null)
47 GenericTypeBuilder = assembly.GetType ("System.Reflection.Emit.TypeBuilderInstantiation");
51 public TypeSpec (MemberKind kind, TypeSpec declaringType, ITypeDefinition definition, MetaType info, Modifiers modifiers)
52 : base (kind, declaringType, definition, modifiers)
54 this.declaringType = declaringType;
57 if (definition != null && definition.TypeParametersCount > 0)
58 state |= StateFlags.IsGeneric;
63 public override int Arity {
65 return MemberDefinition.TypeParametersCount;
69 public virtual TypeSpec BaseType {
78 public virtual BuildinTypeSpec.Type BuildinType {
80 return BuildinTypeSpec.Type.None;
84 public bool HasDynamicElement {
86 return (state & StateFlags.HasDynamicElement) != 0;
90 public virtual IList<TypeSpec> Interfaces {
101 return Kind == MemberKind.ArrayType;
105 public bool IsAttribute {
115 if (type == TypeManager.attribute_type)
118 type = type.base_type;
119 } while (type != null);
125 public bool IsInterface {
127 return Kind == MemberKind.Interface;
131 public bool IsClass {
133 return Kind == MemberKind.Class;
137 public bool IsConstantCompatible {
139 if ((Kind & (MemberKind.Enum | MemberKind.Class | MemberKind.Interface | MemberKind.Delegate | MemberKind.ArrayType)) != 0)
142 return TypeManager.IsPrimitiveType (this) || this == TypeManager.decimal_type || this == InternalType.Dynamic;
146 public bool IsDelegate {
148 return Kind == MemberKind.Delegate;
153 get { return Kind == MemberKind.Enum; }
156 // TODO: Should probably do
157 // IsGenericType -- recursive
158 // HasTypeParameter -- non-recursive
159 public bool IsGenericOrParentIsGeneric {
165 ts = ts.declaringType;
166 } while (ts != null);
172 public bool IsGenericParameter {
173 get { return Kind == MemberKind.TypeParameter; }
176 public bool IsNested {
177 get { return declaringType != null && Kind != MemberKind.TypeParameter; }
180 public bool IsPointer {
182 return Kind == MemberKind.PointerType;
186 public bool IsSealed {
187 get { return (Modifiers & Modifiers.SEALED) != 0; }
190 public bool IsStruct {
192 return Kind == MemberKind.Struct;
196 public bool IsTypeBuilder {
201 var meta = GetMetaInfo().GetType ();
202 return meta == TypeBuilder || meta == GenericTypeBuilder;
207 public MemberCache MemberCache {
209 if (cache == null || (state & StateFlags.PendingMemberCacheMembers) != 0)
210 InitializeMemberCache (false);
216 throw new InternalErrorException ("Membercache reset");
222 public MemberCache MemberCacheTypes {
225 InitializeMemberCache (true);
231 public new ITypeDefinition MemberDefinition {
233 return (ITypeDefinition) definition;
237 // TODO: Wouldn't be better to rely on cast to InflatedTypeSpec and
238 // remove the property, YES IT WOULD !!!
239 public virtual TypeSpec[] TypeArguments {
240 get { return TypeSpec.EmptyTypes; }
245 public bool AddInterface (TypeSpec iface)
247 if ((state & StateFlags.InterfacesExpanded) != 0)
248 throw new InternalErrorException ("Modifying expanded interface list");
250 if (ifaces == null) {
251 ifaces = new List<TypeSpec> () { iface };
255 if (!ifaces.Contains (iface)) {
263 public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
265 if (Kind != MemberKind.Class)
266 throw new InternalErrorException ();
269 return Attribute.DefaultUsageAttribute;
271 AttributeUsageAttribute aua = null;
273 while (type != null) {
274 aua = type.MemberDefinition.GetAttributeUsage (pa);
278 type = type.BaseType;
284 public virtual MetaType GetMetaInfo ()
289 public virtual TypeSpec GetDefinition ()
294 public override string GetSignatureForError ()
299 s = DeclaringType.GetSignatureForError ();
300 } else if (MemberDefinition is AnonymousTypeClass) {
301 return ((AnonymousTypeClass) MemberDefinition).GetSignatureForError ();
303 s = MemberDefinition.Namespace;
306 if (!string.IsNullOrEmpty (s))
309 return s + Name + GetTypeNameSignature ();
312 protected virtual string GetTypeNameSignature ()
317 return "<" + TypeManager.CSharpName (MemberDefinition.TypeParameters) + ">";
320 public bool ImplementsInterface (TypeSpec iface, bool variantly)
324 if (t.Interfaces != null) { // TODO: Try t.iface
325 foreach (TypeSpec i in t.Interfaces) {
326 if (i == iface || TypeSpecComparer.IsEqual (i, iface))
329 if (variantly && TypeSpecComparer.Variant.IsEqual (i, iface))
340 protected virtual void InitializeMemberCache (bool onlyTypes)
342 MemberDefinition.LoadMembers (this, onlyTypes, ref cache);
345 state |= StateFlags.PendingMemberCacheMembers;
347 state &= ~StateFlags.PendingMemberCacheMembers;
351 // Is @baseClass base implementation of @type. With enabled @dynamicIsEqual the slower
352 // comparison is used to hide differences between `object' and `dynamic' for generic
353 // types. Should not be used for comparisons where G<object> != G<dynamic>
355 public static bool IsBaseClass (TypeSpec type, TypeSpec baseClass, bool dynamicIsObject)
357 if (dynamicIsObject && baseClass.IsGeneric) {
359 // Returns true for a hierarchies like this when passing baseClass of A<dynamic>
361 // class B : A<object> {}
363 while (type != null) {
364 type = type.BaseType;
365 if (TypeSpecComparer.IsEqual (type, baseClass))
372 while (type != null) {
373 type = type.BaseType;
374 if (type == baseClass)
381 public override MemberSpec InflateMember (TypeParameterInflator inflator)
383 var targs = IsGeneric ? MemberDefinition.TypeParameters : TypeSpec.EmptyTypes;
386 // When inflating nested type from inside the type instance will be same
387 // because type parameters are same for all nested types
389 if (DeclaringType == inflator.TypeInstance) {
390 return MakeGenericType (targs);
393 return new InflatedTypeSpec (this, inflator.TypeInstance, targs);
396 public InflatedTypeSpec MakeGenericType (TypeSpec[] targs)
398 if (targs.Length == 0 && !IsNested)
399 throw new ArgumentException ("Empty type arguments for type " + GetSignatureForError ());
401 InflatedTypeSpec instance;
403 if (inflated_instances == null) {
404 inflated_instances = new Dictionary<TypeSpec[], InflatedTypeSpec> (TypeSpecComparer.Default);
407 instance = this as InflatedTypeSpec;
408 if (instance != null) {
410 // Nested types could be inflated on already inflated instances
411 // Caching this type ensured we are using same instance for
412 // inside/outside inflation using local type parameters
414 inflated_instances.Add (TypeArguments, instance);
419 if (!inflated_instances.TryGetValue (targs, out instance)) {
420 if (GetDefinition () != this && !IsNested)
421 throw new InternalErrorException ("`{0}' must be type definition or nested non-inflated type to MakeGenericType",
422 GetSignatureForError ());
424 instance = new InflatedTypeSpec (this, declaringType, targs);
425 inflated_instances.Add (targs, instance);
431 public virtual TypeSpec Mutate (TypeParameterMutator mutator)
436 public override List<TypeSpec> ResolveMissingDependencies ()
438 List<TypeSpec> missing = null;
440 if (Kind == MemberKind.MissingType) {
441 missing = new List<TypeSpec> ();
446 foreach (var targ in TypeArguments) {
447 if (targ.Kind == MemberKind.MissingType) {
449 missing = new List<TypeSpec> ();
455 if (Interfaces != null) {
456 foreach (var iface in Interfaces) {
457 if (iface.Kind == MemberKind.MissingType) {
459 missing = new List<TypeSpec> ();
466 if (missing != null || BaseType == null)
469 return BaseType.ResolveMissingDependencies ();
472 public void SetMetaInfo (MetaType info)
474 if (this.info != null)
475 throw new InternalErrorException ("MetaInfo reset");
480 public void SetExtensionMethodContainer ()
482 modifiers |= Modifiers.METHOD_EXTENSION;
486 public sealed class BuildinTypeSpec : TypeSpec
492 // TODO: Reorder it more carefully so we can do fast compares
531 readonly string name;
533 public BuildinTypeSpec (MemberKind kind, string ns, string name, Type buildinKind)
534 : base (kind, null, null, null, Modifiers.PUBLIC)
536 this.type = buildinKind;
541 public BuildinTypeSpec (string name, Type buildinKind)
542 : this (MemberKind.InternalCompilerType, "", name, buildinKind)
544 // Make all internal types CLS-compliant, non-obsolete, compact
545 state = (state & ~(StateFlags.CLSCompliant_Undetected | StateFlags.Obsolete_Undetected | StateFlags.MissingDependency_Undetected)) | StateFlags.CLSCompliant;
550 public override int Arity {
556 public override BuildinTypeSpec.Type BuildinType {
562 public string FullName {
564 return ns + '.' + name;
568 public override string Name {
574 public string Namespace {
582 public override string GetSignatureForError ()
585 case "Int32": return "int";
586 case "Int64": return "long";
587 case "String": return "string";
588 case "Boolean": return "bool";
589 case "Void": return "void";
590 case "Object": return "object";
591 case "UInt32": return "uint";
592 case "Int16": return "short";
593 case "UInt16": return "ushort";
594 case "UInt64": return "ulong";
595 case "Single": return "float";
596 case "Double": return "double";
597 case "Decimal": return "decimal";
598 case "Char": return "char";
599 case "Byte": return "byte";
600 case "SByte": return "sbyte";
609 public void SetDefinition (ITypeDefinition td, MetaType type, Modifiers mod)
611 this.definition = td;
613 this.modifiers |= (mod & ~Modifiers.AccessibilityMask);
616 public void SetDefinition (TypeSpec ts)
618 this.definition = ts.MemberDefinition;
619 this.info = ts.GetMetaInfo ();
620 this.BaseType = ts.BaseType;
621 this.Interfaces = ts.Interfaces;
622 this.modifiers = ts.Modifiers;
626 static class TypeSpecComparer
629 // Does strict reference comparion only
631 public static readonly DefaultImpl Default = new DefaultImpl ();
633 public class DefaultImpl : IEqualityComparer<TypeSpec[]>
635 #region IEqualityComparer<TypeSpec[]> Members
637 bool IEqualityComparer<TypeSpec[]>.Equals (TypeSpec[] x, TypeSpec[] y)
642 if (x.Length != y.Length)
645 for (int i = 0; i < x.Length; ++i)
652 int IEqualityComparer<TypeSpec[]>.GetHashCode (TypeSpec[] obj)
655 for (int i = 0; i < obj.Length; ++i)
656 hash = (hash << 5) - hash + obj[i].GetHashCode ();
665 // When comparing type signature of overrides or overloads
666 // this version tolerates different MVARs at same position
668 public static class Override
670 public static bool IsEqual (TypeSpec a, TypeSpec b)
676 // Consider the following example:
678 // public abstract class A
680 // public abstract T Foo<T>();
683 // public class B : A
685 // public override U Foo<T>() { return default (U); }
688 // Here, `T' and `U' are method type parameters from different methods
689 // (A.Foo and B.Foo), so both `==' and Equals() will fail.
691 // However, since we're determining whether B.Foo() overrides A.Foo(),
692 // we need to do a signature based comparision and consider them equal.
695 var tp_a = a as TypeParameterSpec;
697 var tp_b = b as TypeParameterSpec;
698 return tp_b != null && tp_a.IsMethodOwned == tp_b.IsMethodOwned && tp_a.DeclaredPosition == tp_b.DeclaredPosition;
701 var ac_a = a as ArrayContainer;
703 var ac_b = b as ArrayContainer;
704 return ac_b != null && ac_a.Rank == ac_b.Rank && IsEqual (ac_a.Element, ac_b.Element);
707 if (a == InternalType.Dynamic || b == InternalType.Dynamic)
708 return b == TypeManager.object_type || a == TypeManager.object_type;
710 if (a.MemberDefinition != b.MemberDefinition)
714 for (int i = 0; i < a.TypeArguments.Length; ++i) {
715 if (!IsEqual (a.TypeArguments[i], b.TypeArguments[i]))
727 // Compares unordered arrays
729 public static bool IsSame (TypeSpec[] a, TypeSpec[] b)
734 if (a == null || b == null || a.Length != b.Length)
737 for (int ai = 0; ai < a.Length; ++ai) {
739 for (int bi = 0; bi < b.Length; ++bi) {
740 if (IsEqual (a[ai], b[bi])) {
753 public static bool IsEqual (AParametersCollection a, AParametersCollection b)
758 if (a.Count != b.Count)
761 for (int i = 0; i < a.Count; ++i) {
762 if (!IsEqual (a.Types[i], b.Types[i]))
765 const Parameter.Modifier ref_out = Parameter.Modifier.REF | Parameter.Modifier.OUT;
766 if ((a.FixedParameters[i].ModFlags & ref_out) != (b.FixedParameters[i].ModFlags & ref_out))
775 // Type variance equality comparison
777 public static class Variant
779 public static bool IsEqual (TypeSpec type1, TypeSpec type2)
781 if (!type1.IsGeneric || !type2.IsGeneric)
784 var target_type_def = type2.MemberDefinition;
785 if (type1.MemberDefinition != target_type_def)
788 var t1_targs = type1.TypeArguments;
789 var t2_targs = type2.TypeArguments;
790 var targs_definition = target_type_def.TypeParameters;
792 if (!type1.IsInterface && !type1.IsDelegate) {
796 for (int i = 0; i < targs_definition.Length; ++i) {
797 Variance v = targs_definition[i].Variance;
798 if (v == Variance.None) {
799 if (t1_targs[i] == t2_targs[i])
804 if (v == Variance.Covariant) {
805 if (!Convert.ImplicitReferenceConversionExists (new EmptyExpression (t1_targs[i]), t2_targs[i]))
807 } else if (!Convert.ImplicitReferenceConversionExists (new EmptyExpression (t2_targs[i]), t1_targs[i])) {
817 // Checks whether two generic instances may become equal for some
818 // particular instantiation (26.3.1).
820 public static class Unify
823 // Either @a or @b must be generic type
825 public static bool IsEqual (TypeSpec a, TypeSpec b)
827 if (a.MemberDefinition != b.MemberDefinition)
830 var ta = a.TypeArguments;
831 var tb = b.TypeArguments;
832 for (int i = 0; i < ta.Length; i++) {
833 if (!MayBecomeEqualGenericTypes (ta[i], tb[i]))
840 static bool ContainsTypeParameter (TypeSpec tparam, TypeSpec type)
842 TypeSpec[] targs = type.TypeArguments;
843 for (int i = 0; i < targs.Length; i++) {
844 if (tparam == targs[i])
847 if (ContainsTypeParameter (tparam, targs[i]))
855 /// Check whether `a' and `b' may become equal generic types.
856 /// The algorithm to do that is a little bit complicated.
858 static bool MayBecomeEqualGenericTypes (TypeSpec a, TypeSpec b)
860 if (a.IsGenericParameter) {
862 // If a is an array of a's type, they may never
869 // If b is a generic parameter or an actual type,
870 // they may become equal:
872 // class X<T,U> : I<T>, I<U>
873 // class X<T> : I<T>, I<float>
875 if (b.IsGenericParameter)
876 return a.DeclaringType == b.DeclaringType;
879 // We're now comparing a type parameter with a
880 // generic instance. They may become equal unless
881 // the type parameter appears anywhere in the
884 // class X<T,U> : I<T>, I<X<U>>
885 // -> error because you could instanciate it as
888 // class X<T> : I<T>, I<X<T>> -> ok
891 return !ContainsTypeParameter (a, b);
894 if (b.IsGenericParameter)
895 return MayBecomeEqualGenericTypes (b, a);
898 // At this point, neither a nor b are a type parameter.
900 // If one of them is a generic instance, compare them (if the
901 // other one is not a generic instance, they can never
904 if (TypeManager.IsGenericType (a) || TypeManager.IsGenericType (b))
905 return IsEqual (a, b);
908 // If both of them are arrays.
910 var a_ac = a as ArrayContainer;
912 var b_ac = b as ArrayContainer;
913 if (b_ac == null || a_ac.Rank != b_ac.Rank)
916 return MayBecomeEqualGenericTypes (a_ac.Element, b_ac.Element);
920 // Ok, two ordinary types.
926 public static bool Equals (TypeSpec[] x, TypeSpec[] y)
931 if (x.Length != y.Length)
934 for (int i = 0; i < x.Length; ++i)
935 if (!IsEqual (x[i], y[i]))
942 // Identity type conversion
944 // Default reference comparison, it has to be used when comparing
945 // two possible dynamic/internal types
947 public static bool IsEqual (TypeSpec a, TypeSpec b)
950 // This also rejects dynamic == dynamic
951 return a.Kind != MemberKind.InternalCompilerType || a == InternalType.Dynamic;
955 // object and dynamic are considered equivalent there is an identity conversion
956 // between object and dynamic, and between constructed types that are the same
957 // when replacing all occurences of dynamic with object.
959 if (a == InternalType.Dynamic || b == InternalType.Dynamic)
960 return b == TypeManager.object_type || a == TypeManager.object_type;
966 var a_a = (ArrayContainer) a;
967 var b_a = b as ArrayContainer;
971 return IsEqual (a_a.Element, b_a.Element) && a_a.Rank == b_a.Rank;
974 if (!a.IsGeneric || b == null || !b.IsGeneric)
977 if (a.MemberDefinition != b.MemberDefinition)
981 if (!Equals (a.TypeArguments, b.TypeArguments))
992 public interface ITypeDefinition : IMemberDefinition
994 IAssemblyDefinition DeclaringAssembly { get; }
995 string Namespace { get; }
996 int TypeParametersCount { get; }
997 TypeParameterSpec[] TypeParameters { get; }
999 TypeSpec GetAttributeCoClass ();
1000 string GetAttributeDefaultMember ();
1001 AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa);
1002 bool IsInternalAsPublic (IAssemblyDefinition assembly);
1003 void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache);
1006 class InternalType : TypeSpec, ITypeDefinition
1008 public static readonly InternalType AnonymousMethod = new InternalType ("anonymous method");
1009 public static readonly InternalType Arglist = new InternalType ("__arglist");
1010 public static BuildinTypeSpec Dynamic;
1011 public static readonly InternalType MethodGroup = new InternalType ("method group");
1012 public static BuildinTypeSpec Null;
1013 public static readonly InternalType FakeInternalType = new InternalType ("<fake$type>");
1015 readonly string name;
1017 InternalType (string name, MemberCache cache)
1023 InternalType (string name)
1024 : base (MemberKind.InternalCompilerType, null, null, null, Modifiers.PUBLIC)
1027 this.definition = this;
1028 cache = MemberCache.Empty;
1030 // Make all internal types CLS-compliant, non-obsolete
1031 state = (state & ~(StateFlags.CLSCompliant_Undetected | StateFlags.Obsolete_Undetected)) | StateFlags.CLSCompliant;
1036 public override int Arity {
1042 IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
1044 throw new NotImplementedException ();
1048 bool IMemberDefinition.IsImported {
1054 public override string Name {
1060 string ITypeDefinition.Namespace {
1066 int ITypeDefinition.TypeParametersCount {
1072 TypeParameterSpec[] ITypeDefinition.TypeParameters {
1080 public override string GetSignatureForError ()
1085 #region ITypeDefinition Members
1087 TypeSpec ITypeDefinition.GetAttributeCoClass ()
1092 string ITypeDefinition.GetAttributeDefaultMember ()
1097 AttributeUsageAttribute ITypeDefinition.GetAttributeUsage (PredefinedAttribute pa)
1102 bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
1104 throw new NotImplementedException ();
1107 void ITypeDefinition.LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
1109 throw new NotImplementedException ();
1112 string[] IMemberDefinition.ConditionalConditions ()
1117 ObsoleteAttribute IMemberDefinition.GetAttributeObsolete ()
1122 bool IMemberDefinition.IsNotCLSCompliant ()
1127 void IMemberDefinition.SetIsAssigned ()
1131 void IMemberDefinition.SetIsUsed ()
1138 public abstract class ElementTypeSpec : TypeSpec, ITypeDefinition
1140 protected ElementTypeSpec (MemberKind kind, TypeSpec element, MetaType info)
1141 : base (kind, element.DeclaringType, null, info, element.Modifiers)
1143 this.Element = element;
1145 // Some flags can be copied directly from the element
1146 const StateFlags shared_flags = StateFlags.CLSCompliant | StateFlags.CLSCompliant_Undetected
1147 | StateFlags.Obsolete | StateFlags.Obsolete_Undetected | StateFlags.HasDynamicElement;
1148 state &= ~shared_flags;
1149 state |= (element.state & shared_flags);
1151 if (element == InternalType.Dynamic)
1152 state |= StateFlags.HasDynamicElement;
1154 // Has to use its own type definition instead of just element definition to
1155 // correctly identify itself for cases like x.MemberDefininition == predefined.MemberDefinition
1156 this.definition = this;
1158 cache = MemberCache.Empty;
1163 public TypeSpec Element { get; private set; }
1165 public override string Name {
1167 throw new NotSupportedException ();
1173 public override ObsoleteAttribute GetAttributeObsolete ()
1175 return Element.GetAttributeObsolete ();
1178 protected virtual string GetPostfixSignature ()
1183 public override string GetSignatureForError ()
1185 return Element.GetSignatureForError () + GetPostfixSignature ();
1188 public override TypeSpec Mutate (TypeParameterMutator mutator)
1190 var me = Element.Mutate (mutator);
1194 var mutated = (ElementTypeSpec) MemberwiseClone ();
1195 mutated.Element = me;
1196 mutated.info = null;
1200 #region ITypeDefinition Members
1202 IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
1204 return Element.MemberDefinition.DeclaringAssembly;
1208 bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
1210 return Element.MemberDefinition.IsInternalAsPublic (assembly);
1213 public string Namespace {
1214 get { throw new NotImplementedException (); }
1217 public int TypeParametersCount {
1223 public TypeParameterSpec[] TypeParameters {
1225 throw new NotSupportedException ();
1229 public TypeSpec GetAttributeCoClass ()
1231 return Element.MemberDefinition.GetAttributeCoClass ();
1234 public string GetAttributeDefaultMember ()
1236 return Element.MemberDefinition.GetAttributeDefaultMember ();
1239 public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
1241 Element.MemberDefinition.LoadMembers (declaringType, onlyTypes, ref cache);
1244 public bool IsImported {
1246 return Element.MemberDefinition.IsImported;
1250 public string[] ConditionalConditions ()
1252 return Element.MemberDefinition.ConditionalConditions ();
1255 bool IMemberDefinition.IsNotCLSCompliant ()
1257 return Element.MemberDefinition.IsNotCLSCompliant ();
1260 public void SetIsAssigned ()
1262 Element.MemberDefinition.SetIsAssigned ();
1265 public void SetIsUsed ()
1267 Element.MemberDefinition.SetIsUsed ();
1273 public class ArrayContainer : ElementTypeSpec
1275 struct TypeRankPair : IEquatable<TypeRankPair>
1280 public TypeRankPair (TypeSpec ts, int rank)
1286 public override int GetHashCode ()
1288 return ts.GetHashCode () ^ rank.GetHashCode ();
1291 #region IEquatable<Tuple<T1,T2>> Members
1293 public bool Equals (TypeRankPair other)
1295 return other.ts == ts && other.rank == rank;
1302 static Dictionary<TypeRankPair, ArrayContainer> instances = new Dictionary<TypeRankPair, ArrayContainer> ();
1304 private ArrayContainer (TypeSpec element, int rank)
1305 : base (MemberKind.ArrayType, element, null)
1316 public MethodInfo GetConstructor ()
1318 var mb = RootContext.ToplevelTypes.Builder;
1320 var arg_types = new MetaType[rank];
1321 for (int i = 0; i < rank; i++)
1322 arg_types[i] = TypeManager.int32_type.GetMetaInfo ();
1324 var ctor = mb.GetArrayMethod (
1325 GetMetaInfo (), Constructor.ConstructorName,
1326 CallingConventions.HasThis,
1332 public MethodInfo GetAddressMethod ()
1334 var mb = RootContext.ToplevelTypes.Builder;
1336 var arg_types = new MetaType[rank];
1337 for (int i = 0; i < rank; i++)
1338 arg_types[i] = TypeManager.int32_type.GetMetaInfo ();
1340 var address = mb.GetArrayMethod (
1341 GetMetaInfo (), "Address",
1342 CallingConventions.HasThis | CallingConventions.Standard,
1343 ReferenceContainer.MakeType (Element).GetMetaInfo (), arg_types);
1348 public MethodInfo GetGetMethod ()
1350 var mb = RootContext.ToplevelTypes.Builder;
1352 var arg_types = new MetaType[rank];
1353 for (int i = 0; i < rank; i++)
1354 arg_types[i] = TypeManager.int32_type.GetMetaInfo ();
1356 var get = mb.GetArrayMethod (
1357 GetMetaInfo (), "Get",
1358 CallingConventions.HasThis | CallingConventions.Standard,
1359 Element.GetMetaInfo (), arg_types);
1364 public MethodInfo GetSetMethod ()
1366 var mb = RootContext.ToplevelTypes.Builder;
1368 var arg_types = new MetaType[rank + 1];
1369 for (int i = 0; i < rank; i++)
1370 arg_types[i] = TypeManager.int32_type.GetMetaInfo ();
1372 arg_types[rank] = Element.GetMetaInfo ();
1374 var set = mb.GetArrayMethod (
1375 GetMetaInfo (), "Set",
1376 CallingConventions.HasThis | CallingConventions.Standard,
1377 TypeManager.void_type.GetMetaInfo (), arg_types);
1382 public override MetaType GetMetaInfo ()
1386 info = Element.GetMetaInfo ().MakeArrayType ();
1388 info = Element.GetMetaInfo ().MakeArrayType (rank);
1394 protected override string GetPostfixSignature()
1396 return GetPostfixSignature (rank);
1399 public static string GetPostfixSignature (int rank)
1401 StringBuilder sb = new StringBuilder ();
1403 for (int i = 1; i < rank; i++) {
1408 return sb.ToString ();
1411 public static ArrayContainer MakeType (TypeSpec element)
1413 return MakeType (element, 1);
1416 public static ArrayContainer MakeType (TypeSpec element, int rank)
1419 var key = new TypeRankPair (element, rank);
1420 if (!instances.TryGetValue (key, out ac)) {
1421 ac = new ArrayContainer (element, rank) {
1422 BaseType = TypeManager.array_type
1425 instances.Add (key, ac);
1431 public static void Reset ()
1433 instances = new Dictionary<TypeRankPair, ArrayContainer> ();
1437 class ReferenceContainer : ElementTypeSpec
1439 static Dictionary<TypeSpec, ReferenceContainer> instances = new Dictionary<TypeSpec, ReferenceContainer> ();
1441 private ReferenceContainer (TypeSpec element)
1442 : base (MemberKind.Class, element, null) // TODO: Kind.Class is most likely wrong
1446 public override MetaType GetMetaInfo ()
1449 info = Element.GetMetaInfo ().MakeByRefType ();
1455 public static ReferenceContainer MakeType (TypeSpec element)
1457 ReferenceContainer pc;
1458 if (!instances.TryGetValue (element, out pc)) {
1459 pc = new ReferenceContainer (element);
1460 instances.Add (element, pc);
1466 public static void Reset ()
1468 instances = new Dictionary<TypeSpec, ReferenceContainer> ();
1472 class PointerContainer : ElementTypeSpec
1474 static Dictionary<TypeSpec, PointerContainer> instances = new Dictionary<TypeSpec, PointerContainer> ();
1476 private PointerContainer (TypeSpec element)
1477 : base (MemberKind.PointerType, element, null)
1479 // It's never CLS-Compliant
1480 state &= ~StateFlags.CLSCompliant_Undetected;
1483 public override MetaType GetMetaInfo ()
1486 info = Element.GetMetaInfo ().MakePointerType ();
1492 protected override string GetPostfixSignature()
1497 public static PointerContainer MakeType (TypeSpec element)
1499 PointerContainer pc;
1500 if (!instances.TryGetValue (element, out pc)) {
1501 pc = new PointerContainer (element);
1502 instances.Add (element, pc);
1508 public static void Reset ()
1510 instances = new Dictionary<TypeSpec, PointerContainer> ();