PageRenderTime 49ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/mcs/mcs/typespec.cs

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